flutter-nfc-manager icon indicating copy to clipboard operation
flutter-nfc-manager copied to clipboard

onDiscover callback isn't triggered on iOS

Open akhil-ge0rge opened this issue 5 months ago • 9 comments

Initially, I tested with MIFARE Classic cards, but later discovered that iOS does not support MIFARE Classic, so I purchased an NXP NTAG213 tag instead

However, the onDiscovered callback is still not triggering on iOS, even though everything works fine on Android.

On iOS, the NFC scanning prompt does appear, indicating that the session is starting correctly. However, the tag is not being read, and the onDiscovered callback is never triggered.

My goal is to read the UID (unique identifier) of the NFC tag (NXP NTAG213).

 void startNfc({required BuildContext context}) async {
    try {
      bool isAvailable = await NfcManager.instance.isAvailable();
      if (!isAvailable) {
        log("NFC not available");
        AppUtils.showToast(
          message: "NFC not available for this device",
          backgroundColor: AppColors.errorToastColor,
          textColor: AppColors.toastTextColor,
        );
        return;
      }
      try {
        log("Stopping any existing NFC session (if any)");
        await NfcManager.instance.stopSession();
      } catch (e) {
        log("No session to stop or error while stopping: $e");
      }
      if (_isNfcOn) {
        _isNfcOn = false;
        notifyListeners();
      } else {
        _isNfcOn = true;
        notifyListeners();
        NfcManager.instance.startSession(
          pollingOptions: {
            NfcPollingOption.iso14443,
            NfcPollingOption.iso15693,
            NfcPollingOption.iso18092,
          },
          alertMessageIos: "Hold the NFC-Tag on the upper back of your iPhone",
          onSessionErrorIos: (p0) {
            _isNfcOn = false;
            notifyListeners();
            log("Mesage${p0.message}");
          },
          onDiscovered: (NfcTag tag) async {
            log("Tag Discoverd");
            try {
              if (!_isNfcReading) {
                _isNfcReading = true;
                num decodeValue = 0;
                if (Platform.isIOS) {
                  log("iOS");
                } else {
                  Uint8List? idBytes;

                  // 1️⃣ Most Mifare / ISO 14443-3A cards
                  final nfcA = NfcAAndroid.from(tag);
                  if (nfcA != null) {
                    idBytes = nfcA.tag.id;
                  }

                  // 2️⃣ (fallback) Some MifareClassic cards
                  if (idBytes == null) {
                    final mc = MifareClassicAndroid.from(tag);
                    idBytes = mc?.tag.id;
                  }
                  log(idBytes.toString());
                  final List<int> encodedByte = idBytes!;

                  for (var i = 0; i < encodedByte.length; i++) {
                    log(encodedByte[i].toString());
                    decodeValue += encodedByte[i] * pow(256, i);
                  }
                  log(" ➡️ NFC TAG 🆔 : $decodeValue");
                }
                await Future.delayed(const Duration(milliseconds: 2000));

                _isNfcReading = false;
                log("📞 API CALL Done");
              }
            } catch (e) {
              await NfcManager.instance.stopSession();
              _isNfcOn = false;
              notifyListeners();
              log("Error while reading NFC CARD$e");
            }
          },
        );
      }
    } catch (e) {
      AppUtils.showToast(
        message: "NFC is not supported on this device.",
        backgroundColor: AppColors.errorToastColor,
        textColor: AppColors.toastTextColor,
      );
      log("Session Error: $e");
    }
  }

Info.plist

<key>NFCReaderUsageDescription</key>
    <string>Allow access to Read tag</string>
	<key>com.apple.developer.nfc.readersession.formats</key>
	<array>
    <string>TAG</string>
	</array>
	<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
	<array>
		<string>0003</string>
		<string>04D1</string>
		<string>8008</string>
		<string>80DE</string>
		<string>865E</string>
		<string>8592</string>
		<string>8B5D</string>
		<string>8FC1</string>
		<string>FE00</string>
	</array>
	<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
	<array>
		<string>A0000002310100000000000000000000</string>
		<string>A0000002310200000000000000000000</string>
		<string>A0000002480300000000000000000000</string>
		<string>A00000006510</string>
.......
.......
<string>A000000118454E</string>
	</array>

Runner.entitlements

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.developer.nfc.readersession.formats</key>
	<array>
		<string>TAG</string>
	</array>
</dict>
</plist>
  • I’ve enabled Near Field Communication Tag Reading under Signing & Capabilities in Xcode
  • No errors are shown in logs, but onDiscovered never fires on iOS

akhil-ge0rge avatar Jul 10 '25 17:07 akhil-ge0rge