semlette / nfc_in_flutter

Cross-platform flutter plugin for reading and writing NFC tags. Not maintained anymore - not looking for new maintainer, fork instead.
MIT License
120 stars 119 forks source link

[iOS] CoreNFC "Session invalidated unexpectedly" #29

Closed martyfuhry closed 4 years ago

martyfuhry commented 4 years ago

I'm using an iPhone 8 running iOS 13.2. The plugin works fine for the first two interactions, but then I get this error:

2020-01-08 14:37:02.396459-0500 Runner[276:4816] [CoreNFC] 00000002 8364fea0 -[NFCHardwareManager queueReaderSession:sessionConfig:completionHandler:]:98 error=Error Domain=NFCError Code=202 "Session invalidated unexpectedly" UserInfo={NSLocalizedDescription=Session invalidated unexpectedly} 2020-01-08 14:37:02.396655-0500 Runner[276:4816] [CoreNFC] 00000002 818cfd00 -[NFCNDEFReaderSession beginSessionWithConfig:]:324 error:Error Domain=NFCError Code=202 "Session invalidated unexpectedly" UserInfo={NSLocalizedDescription=Session invalidated unexpectedly}, errorCode: 0xca 2020-01-08 14:37:02.397651-0500 Runner[276:4790] [VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: PlatformException(SessionTerminatedUnexpectedlyError, Session invalidated unexpectedly, null)

The NFC dialog won't come up, and only a reboot of the device will allow me to interact with CoreNFC again.

Steps to reproduce:

  1. Run the ReadExampleScreen (from the examples directory in this repository) on a physical iOS device.
  2. Tap the "Toggle scan" button. The NFC dialog comes up.
  3. Press "Cancel" on the dialog window.
  4. Tap the "Toggle scan" button twice (to turn NFC reading off, then turn it back on again). The NFC dialog comes up again.
  5. Press "Cancel" on the dialog window.
  6. Again, tap "Toggle scan" twice. The error message above should print out, and you won't be able to open the NFC dialog, even in other applications.

You'll need to reboot your device in order to get NFC working again. I tried walking through the debugger a few times, and the only thing I found was that second time I started reading NFC, the onCancelWithArguments function ran immediately, and then readerSession: didInvalidateWithError function ran after that.

Can anyone else with a physical device reproduce this behavior?

martyfuhry commented 4 years ago

I at least got it to stop crashing CoreNFC entirely by commenting out line 136 in NfcInFlutterPlugin.m:

// onCancelWithArguments is called when the event stream is canceled,
// which most likely happens because of manuallyStopStream().
// However if it was not triggered by manuallyStopStream(), it should invalidate
// the reader session if activate
- (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments {
    if (session != nil) {
        // commented this out: [session invalidateSession];
        session = nil;
    }
    events = nil;
    return nil;
}

Unfortunately, this stops readOnce: true from working properly since invalidateSession isn't called. Presumably, there are other unintended side-effects, as well.

Edit: I got it working again by checking for [session isReady] like so:

    if (session != nil && [session isReady]) {
        [session invalidateSession];
        session = nil;
    }

Hope this helps. I've never made a PR, but I can submit one if you'd like.

maganap commented 4 years ago

@martyfuhry Yes, the same happens here on iOS 13.3, iPhone X, nfc_in_flutter 2.0.3. Have you found a proper solution for this? Your patch indeed avoids part of the problem, but still the NFC dialog won't come up any more. Thanks

semlette commented 4 years ago

Your fix worked for me too 🙂 I have committed it on your behalf.

MobileSoftHK commented 2 years ago

This issue still occurs in version 2.0.5 -> tested on iPhone 8 iOS version 14.8