nfc_util 2.0.0 copy "nfc_util: ^2.0.0" to clipboard
nfc_util: ^2.0.0 copied to clipboard

A Flutter plugin providing access to NFC features on Android and iOS.

๐Ÿ“ก NFC Util #

A Flutter plugin for reading and writing NFC tags on Android and iOS.

It keeps the familiar nfc_manager v3 API โ€” migrating is usually just a change of import โ€” but ships its own Android and iOS implementations so it can be updated independently and keep pace with current Flutter, Android and iOS releases.

๐Ÿค– Android minSdk 24 ยท full tag I/O (NDEF, transceive, MIFARE Classic / Ultralight, NDEF formatting)
๐Ÿ iOS 15.6+ ยท NDEF, FeliCa, ISO7816, ISO15693, MIFARE
๐Ÿ“ฆ Packaging CocoaPods and Swift Package Manager
๐Ÿ”’ Privacy PrivacyInfo.xcprivacy bundled by both packaging paths

๐Ÿš€ Install #

dependencies:
  nfc_util: ^2.0.0

Requires Flutter 3.44.0 or newer. Earlier releases do not stage the FlutterFramework Swift package that the plugin's Package.swift depends on.


โš™๏ธ Setup #

๐Ÿค– Android #

Add the NFC permission to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.NFC" />

Nothing else โ€” the plugin ships its own manifest and Gradle configuration.

๐Ÿ iOS #

1. Entitlement. Add Near Field Communication Tag Reader Session Formats to Runner.entitlements:

<key>com.apple.developer.nfc.readersession.formats</key>
<array>
  <string>NDEF</string>
  <string>TAG</string>
</array>

2. Usage description. Add NFCReaderUsageDescription to Info.plist โ€” the text shown on the scan sheet.

3. Deployment target. Set IPHONEOS_DEPLOYMENT_TARGET to 15.6 or higher in ios/Runner.xcodeproj/project.pbxproj. A lower target fails at install time under both SwiftPM (requires minimum platform version 15.6) and CocoaPods.

4. Tag-specific Info.plist keys, if you use those technologies:

Key Needed for
com.apple.developer.nfc.readersession.felica.systemcodes polling iso18092 (FeliCa)
com.apple.developer.nfc.readersession.iso7816.select-identifiers before an ISO7816 tag reports its applications

โš ๏ธ The mistake that costs everyone an afternoon #

startSession polls every option when you omit pollingOptions โ€” including iso18092. CoreNFC rejects a FeliCa session unless com.apple.developer.nfc.readersession.felica.systemcodes is in your Info.plist.

When that happens the scan sheet never appears and startSession still succeeds, because iOS reports the failure asynchronously. With no onError callback you get total silence and nothing to debug.

Fix it either way:

// Ask for only what you need...
NfcManager.instance.startSession(
  pollingOptions: {NfcPollingOption.iso14443},
  onDiscovered: (tag) async { /* ... */ },
  onError: (error) async => debugPrint('$error'), // ...and always pass this
);

๐Ÿ“– Usage #

๐Ÿ”„ Session #

// Is NFC present and switched on? Returns false instead of throwing.
final available = await NfcManager.instance.isAvailable();

await NfcManager.instance.startSession(
  onDiscovered: (NfcTag tag) async {
    // Read and write here โ€” the session stays open until you stop it.
  },
  onError: (NfcError error) async {
    // iOS only: timeout, user cancel, or a session that could not start.
  },
);

await NfcManager.instance.stopSession();
Method Behaviour
isAvailable() Returns false rather than throwing when the platform cannot answer
startSession(...) Throws PlatformException if the session could not be started
stopSession(...) Never throws โ€” safe in finally and dispose

alertMessage / errorMessage set the text on the iOS scan sheet. invalidateAfterFirstRead (iOS, default true) stops polling for further tags after the first one. Either way the session stays open so you can run tag commands inside onDiscovered; close it yourself with stopSession().

๐Ÿท๏ธ Tag technologies #

Get an instance with the from factory. It returns null when the tag does not support that technology:

final ndef = Ndef.from(tag);
if (ndef == null) {
  print('Tag is not NDEF compatible');
  return;
}

final message = await ndef.read();   // null when the tag holds no message
await ndef.write(NdefMessage([NdefRecord.createText('Hello')]));
Class ๐Ÿค– Android ๐Ÿ iOS
Ndef โœ… โœ…
NfcA NfcB NfcF NfcV โœ… โ€”
IsoDep โœ… โ€”
MifareClassic โœ… โ€”
MifareUltralight โœ… โ€”
NdefFormatable โœ… โ€”
FeliCa โ€” โœ…
Iso7816 โ€” โœ…
Iso15693 โ€” โœ…
MiFare โ€” โœ…

Import the platform classes from:

import 'package:nfc_util/nfc_util.dart';        // NfcManager, NfcTag, Ndef, NdefMessage
import 'package:nfc_util/platform_tags.dart';   // NfcA, MiFare, FeliCa, ...

โœ๏ธ Building NDEF records #

NdefMessage([
  NdefRecord.createText('Hello World!', languageCode: 'en'),
  NdefRecord.createUri(Uri.parse('https://flutter.dev')),
  NdefRecord.createMime('text/plain', Uint8List.fromList('Hello'.codeUnits)),
  NdefRecord.createExternal('com.example', 'mytype', Uint8List.fromList('data'.codeUnits)),
]);

These factories enforce the NDEF specification and throw ArgumentError on invalid input. NdefRecord.fromPlatform skips that validation and is what the plugin uses to decode records read off a tag, which may legitimately hold shapes the creation rules reject (a chunked record, for instance).


๐Ÿงฏ Error handling #

Tag operations throw PlatformException:

Code Meaning
invalid_parameter Unknown tag handle, or the tag does not support that technology
tag_lost The tag moved out of range mid-operation
io_exception Communication with the tag failed
no_result The platform returned no value for a call that requires one
unavailable The session could not be started

On Android the message says whether the failure happened while connecting or while running the command, e.g. connect: TagLostException: .... Failures are also logged under the NfcUtilPlugin tag.

On iOS a session can fail after startSession returns โ€” user cancel, the 60 s system timeout, or a rejected session. Those arrive on onError, never as a thrown exception, so always pass the callback.


๐Ÿ“ฆ CocoaPods and Swift Package Manager #

Both are supported and share one copy of the native sources under ios/nfc_util/Sources/nfc_util/. You do not choose: Flutter uses SwiftPM when it is enabled (the default) and falls back to CocoaPods otherwise. The privacy manifest ships either way.


๐Ÿ“ฑ Example #

The example/ app exercises the plugin on a real device: read a tag, write NDEF, lock a tag, and a Tag I/O button that runs read-only commands against every technology the tag supports and reports each result with timings.

NFC hardware does not exist in emulators or the iOS Simulator โ€” the example needs a physical device.

2
likes
0
points
388
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin providing access to NFC features on Android and iOS.

Repository (GitHub)
View/report issues

Topics

#nfc #ndef #mifare #felica

License

unknown (license)

Dependencies

flutter

More

Packages that depend on nfc_util

Packages that implement nfc_util