NFC Plus ๐
nfc_plus is a high-performance, developer-friendly NFC plugin for Flutter. It provides a modern, unified API for Android, iOS, Web (via WebUSB), and Desktop platforms.
Whether you're building a simple tag reader or a complex industrial access-control system, nfc_plus eliminates the boilerplate of low-level NFC protocols while keeping all the power at your fingertips.
โจ Key Features
- ๐ฏ One-Line Capture: Scan and read tags with a single
await NfcPlus.capture(). - ๐ Continuous Observation: Stream tags in real-time with automatic duplicate filtering and cooldowns.
- ๐ท๏ธ Strongly-Typed Models: Specialized classes for
MifareClassicCard,MifareUltralightCard,SmartCard (ISO 7816),VicinityCard (ISO 15693), and more. - ๐ NdefBuilder: High-level helper to create Text, URL, and WiFi records without manual byte manipulation.
- ๐งช Testing & Mocking: Built-in mock bridge for unit and widget testing without physical hardware.
- ๐ Debug Console: Formatted logs for tag data, session states, and APDU exchanges.
- ๐ณ Expert Access: Send raw APDUs to Smart Cards or read/write specific blocks on Mifare tags.
- ๐ WebUSB Support: Communication with dual-interface USB/NFC devices on browsers.
๐ Setup
Android
Add the NFC permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.NFC" />
iOS
- Add
NFCReaderUsageDescriptionto yourInfo.plist. - Enable Near Field Communication Tag Reading in the Signing & Capabilities tab of your Xcode project.
- Add the
com.apple.developer.nfc.readersession.formatsentitlement (for NDEF, ISO7816, etc.).
๐ Usage
1. Check System Support
Before starting a scan, check if the device supports NFC and if it is enabled.
final status = await NfcPlus.checkStatus();
if (status == NfcSupport.available) {
print("NFC is ready!");
}
2. Simple Tag Capture
The capture() method is the easiest way to read a tag. It starts a session, waits for a tag, reads its metadata, and automatically closes the session.
try {
final card = await NfcPlus.capture(
timeout: Duration(seconds: 15),
feedback: true, // Haptic/Sound feedback
);
print("Detected tag UID: ${card.id}");
} on NfcIssue catch (e) {
print("Scan failed: ${e.info}");
}
3. Continuous Observation (Streaming)
Ideal for attendance or inventory apps where you want to scan multiple tags in a row.
// Start the observer
await NfcPlus.start(
cooldown: Duration(seconds: 3), // Wait 3s before accepting the same tag again
);
// Listen to the stream
NfcPlus.stream.listen((card) {
print("Batch scan: ${card.id} of type ${card.type}");
});
// Stop when done
await NfcPlus.stop();
4. Writing NDEF Data
Use NdefBuilder to create records and writeNdef() to apply them to a tag.
// Create a WiFi record
final wifiRecord = NdefBuilder.wifi("Office_Guest", "password123");
// Write to the next tapped tag
await NfcPlus.writeNdef(wifiRecord);
// You can also write a list of records
await NfcPlus.writeNdef([
NdefBuilder.text("Property of MyCompany"),
NdefBuilder.url("https://mycompany.com"),
]);
5. Advanced Card Interaction
nfc_plus provides strongly-typed classes to interact with specific tag technologies.
Mifare Classic
NfcPlus.stream.listen((card) async {
if (card is MifareClassicCard) {
bool auth = await card.auth(0, keyA: "FFFFFFFFFFFF");
if (auth) {
final blockData = await card.readBlock(0);
print("Block 0: ${NfcToolkit.toHex(blockData)}");
}
}
});
Smart Cards (ISO 7816 / APDUs)
if (card is SmartCard) {
// Select Application (AID)
final response = await card.transmit("00A4040008A000000003000000");
print("AID Selection Result: $response");
}
๐งช Mocking for Tests
You can mock NFC behavior to test your UI or business logic without a physical device using NfcMockBridge.
class MyTestBridge extends NfcMockBridge {
@override
NfcCard poll() => BasicCard(...); // Return a fake card
@override
Future<List<NDEFRecord>> fetchNdef(String id) async => [...];
// Implement other methods...
}
// In your test
NfcPlus.mock(MyTestBridge());
๐งฐ Toolkit & Utilities
NfcToolkit provides high-performance methods for common data conversions:
NfcToolkit.toHex(bytes): ConvertUint8Listto a clean Hex string.NfcToolkit.fromHex(hexString): Convert a Hex string back toUint8List.
๐ WebUSB Integration
Web browsers do not support native NFC. nfc_plus uses a custom WebUSB protocol to bridge this gap for dual-interface devices.
To support this, your USB device must respond to specific vendor requests:
CMD (00h): Receive APDU.RESP (01h): Send Response.STAT (02h): Status check.PROBE (FFh): Identity check (must return_NFC_IM_magic bytes).
๐ฅ Desktop Support
nfc_plus is designed with a plugin architecture that allows it to easily scale to Desktop. Native drivers for Windows, macOS, and Linux are currently in the infrastructure phase, using the same unified NfcPlus API.
โ๏ธ License
This project is licensed under the MIT License - see the LICENSE file for details.