nfcim/flutter_nfc_kit

Ios 14.2(iPhone XR) Dialog NFC scan don't show

saobang187 opened this issue · 15 comments

In my widget, I call:
print('BEFORE FlutterNfcKit.poll');
var tag = await FlutterNfcKit.poll(
// timeout: Duration(seconds: 600),
iosMultipleTagMessage: "Multiple tags found!",
iosAlertMessage: "Scan your tag");

print(jsonEncode(tag));
print('AFTER FlutterNfcKit.poll');

But dialog NFC scan don't show in iPhone and debug stop at line await FlutterNfcKit.poll(...
Please help me check it

I have two testing devices, the "NFC Scanning Window" shows up on one of my devices but not on the other one.

  • this library works on iPhone XS Max (iOS 14.3)
  • this library doesn't work ("NFC Scanning Window" not showing up) on iPhone 11 Pro (iOS 14.3)

I also tried a native iOS demo app janlionly/NFCReaderWriter, it works on both devices. But for my case, I need to use flutter. I hope this issue can be fixed.

@kensang Can you provide more detail on this, such as the log before / after the poll call on both two devices? Sorry to bother but we do not have enough devices to test our library on.

@Harry-Chen I just tried to sentry to log my co-worker's result (he is the one using iPhone 11 Pro 14.3), for some reason, this package suddenly works for his phone as well. I am not sure if it's just that there was a mistake with his previous testing or what, but I will let you know what I have done between my previous version and this version just in case:

I have done the following:

  • change the build version number of my iOS app
  • install flutter_sentry 0.4.4
  • setup and implement flutter_sentry the way the flutter_sentry example does it
  • upload from testflight

I then ask my tester with his iPhone 11 Pro 14.3 to do the following:

  1. download from Testflight
  2. restart your phone
  3. make sure your phone can connect to the internet (so that sentry can log)
  4. try to scan an nfc tag

The result from the tester is that it now works, meaning it can detect the nfc tag id & info correctly.

Again, I am not sure if it's a mistake made in previous testing, or is it a re-uploading to testflight, or is it just the "restarting the phone" step. It just works right now. And thank you for your reply.

@kensang Actually we have encountered some strange behaviour (bug?) with CoreNFC when developing this library, with the similar situation like you described (not responding to poll until a reboot). We haven't figured out how to reproduce (so not reported to Apple yet), but seems frequently calling polling and cancelling the request sometimes triggers this bug.

Again, I am not sure if it's a mistake made in previous testing, or is it a re-uploading to testflight, or is it just the "restarting the phone" step. It just works right now. And thank you for your reply.

So I believe rebooting is the magic. Who knows :-(

Rebooting doesnt work for me. I'm running in debug mode, press start polling and i get the platform exception. I reboot device, relaunch the app in debug mode and still same issue. Reboot is not a solution. There is something wrong with your library.

I have exactly the same issue on iOS 14.2 (iPhone 7 and iPhone SE 2020), also tried out rebooting

@devnullpointer Did you get the platform exception directly on the first polling attempt?

Hi @devnullpointer and @mbartn , do you have any reproducers? It would be much appreciated if you could provide a reproducer.

Hello @dangfan. First of all, thanks for addressing the issue.

The steps that I went through

  1. Created brand new empty Flutter project.
  2. Added Near Field Communication Tag Reading capability via newest XCode.
  3. Changed iOS deployment target to 13.0.
  4. Added
<key>NFCReaderUsageDescription</key>
<string>Some description</string>

to info.plist
5. Ran the code presented below on iPhone SE 2020 with iOS 14.2 (18B92)

import 'package:flutter/material.dart';
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Nfc demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Future<void> _readNfc() async {
    print("Starting pooling...");
    var tag = await FlutterNfcKit.poll();
    print("Got it! $tag");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("Hello world!"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _readNfc,
        child: Icon(Icons.add),
      ),
    );
  }
}
  1. Clicked floating button once and got these logs:
Launching lib/main.dart on Michał’s iPhone in debug mode...
Automatically signing iOS for device deployment using specified development team in Xcode project: 25UCG8AM44
Running pod install...
Running Xcode build...
Xcode build done.                                           46.7s
Installing and launching...
(lldb) 2021-04-01 20:09:26.178466+0200 Runner[596:44522] Warning: Unable to create restoration in progress marker file
Debug service listening on ws://127.0.0.1:60070/wfADq46S2gk=/ws
Syncing files to device Michał’s iPhone...
fopen failed for data file: errno = 2 (No such file or directory)
Errors found! Invalidating cache...
fopen failed for data file: errno = 2 (No such file or directory)
Errors found! Invalidating cache...
flutter: Starting pooling...

and app did nothing, also didn't react on my NFC chip. As you can see app never reached the print(...) succeeding FlutterNfcKit.poll(); call.
6. Clicked button second time and got:

flutter: Starting pooling...
[VERBOSE-2:ui_dart_state.cc(186)] Unhandled Exception: PlatformException(406, Cannot invoke poll in a active session, null, null)
#0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:581:7)
#1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:158:18)
<asynchronous suspension>
#2      FlutterNfcKit.poll (package:flutter_nfc_kit/flutter_nfc_kit.dart:204:25)
<asynchronous suspension>
#3      _MyHomePageState._readNfc (package:flutter_toy/main.dart:31:15)
<asynchronous suspension>

I also checked logs from XCode but looks like there is also nothing helpful printed.

Thanks @mbartn for providing the valuable reproducer. After some trial and error, I found that adding these lines to Info.plist works:

	<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
	<array>
		<string>A00000000386980701</string>
	</array>
	<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
	<array>
		<string>8008</string>
	</array>

Another way is to enable ISO14443 only without changing Info.plist:

      var tag = await FlutterNfcKit.poll(
          readIso14443A: true,
          readIso14443B: true,
          readIso15693: false,
          readIso18092: false);

So I suspect that iOS checks com.apple.developer.nfc.readersession.felica.systemcodes when FeLiCa is enabled.

What I have tried:

  • All Enabled + Info.plist(FeLiCa+ISO7816): works
  • Only ISO14443 Enabled + Info.plist(None): works
  • All Enabled + Info.plist(None): not working
  • ISO14443 + ISO18092 Enabled + Info.plist(FeLiCa): works
  • ISO14443 + ISO18092 Enabled + Info.plist(ISO7816): not working

P.S. device restart is required after testing a non-working scenario due to bug of CoreNFC.

In flutter_nfc_kit, the pollingOption passed to iOS by default is [.iso14443, .iso18092, .iso15693] and then CoreNFC might query the Info.plist and found that there are no requested ISO7816 idenfitifers nor FeLiCa system codes and then refuses to show up the scanning window.

I am looking at how to make this error visible to user.

I have submitted the issue to Apple via Feedback Assistant.

Appreciate your help @jiegec, adding

readIso14443A: true,
readIso14443B: true,
readIso15693: false,
readIso18092: false,

flags totally solved my issue 👍
You are right, providing some logs in similar cases would be very helpful for future plugin users 🙂

flags totally solved my issue 👍

Happy to see that!

You are right, providing some logs in similar cases would be very helpful for future plugin users 🙂

It is unfortunate that CoreNFC failed without reporting the error to user.

Update: Apple says the bug is resolved.

Update: the bug has been resolved since iOS 14.6.