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

  1. Add NFCReaderUsageDescription to your Info.plist.
  2. Enable Near Field Communication Tag Reading in the Signing & Capabilities tab of your Xcode project.
  3. Add the com.apple.developer.nfc.readersession.formats entitlement (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): Convert Uint8List to a clean Hex string.
  • NfcToolkit.fromHex(hexString): Convert a Hex string back to Uint8List.

๐ŸŒ 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.