nfcim / flutter_nfc_kit

Flutter plugin to provide NFC functionality on Android and iOS, including reading metadata, read & write NDEF records, and transceive layer 3 & 4 data with NFC tags / cards
https://pub.dev/packages/flutter_nfc_kit
MIT License
200 stars 121 forks source link

SDK Version 31 leads to an Error #51

Closed thomasklaush closed 2 years ago

thomasklaush commented 2 years ago

Error when using targetSDKVersion 31:

E/MethodChannel#flutter_nfc_kit(30191): Failed to handle method call E/MethodChannel#flutter_nfc_kit(30191): java.lang.IllegalArgumentException: com.xxxx.xxxxxx: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. E/MethodChannel#flutter_nfc_kit(30191): Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles. E/MethodChannel#flutter_nfc_kit(30191): at android.app.PendingIntent.checkFlags(PendingIntent.java:375) E/MethodChannel#flutter_nfc_kit(30191): at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:458) E/MethodChannel#flutter_nfc_kit(30191): at android.app.PendingIntent.getActivity(PendingIntent.java:444) E/MethodChannel#flutter_nfc_kit(30191): at android.app.PendingIntent.getActivity(PendingIntent.java:408) E/MethodChannel#flutter_nfc_kit(30191): at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin.pollTag(FlutterNfcKitPlugin.kt:303) E/MethodChannel#flutter_nfc_kit(30191): at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin.handleMethodCall(FlutterNfcKitPlugin.kt:88) E/MethodChannel#flutter_nfc_kit(30191): at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin.onMethodCall(FlutterNfcKitPlugin.kt:62) E/MethodChannel#flutter_nfc_kit(30191): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233) E/MethodChannel#flutter_nfc_kit(30191): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:84) E/MethodChannel#flutter_nfc_kit(30191): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:865) E/MethodChannel#flutter_nfc_kit(30191): at android.os.MessageQueue.nativePollOnce(Native Method) E/MethodChannel#flutter_nfc_kit(30191): at android.os.MessageQueue.next(MessageQueue.java:335) E/MethodChannel#flutter_nfc_kit(30191): at android.os.Looper.loopOnce(Looper.java:161) E/MethodChannel#flutter_nfc_kit(30191): at android.os.Looper.loop(Looper.java:288) E/MethodChannel#flutter_nfc_kit(30191): at android.app.ActivityThread.main(ActivityThread.java:7839) E/MethodChannel#flutter_nfc_kit(30191): at java.lang.reflect.Method.invoke(Native Method) E/MethodChannel#flutter_nfc_kit(30191): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) E/MethodChannel#flutter_nfc_kit(30191): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

Harry-Chen commented 2 years ago

@thomasklaush What version of this plugin are you using? Seems the stack trace in your log cannot correspond to code in our latest version v3.1.0.

thomasklaush commented 2 years ago

It is the latest version v3.1.0

When I change SDK to 31 in your example, it works (after adding in Manifest: android:exported="true") In my App i use it in a different way, polling every 10 seconds in a stream with while(1) and a delay.

This is to see if there is still a Tag or it got removed!

Then this must be the real problem.

dangfan commented 2 years ago

Would you kindly provide a reproducer?

thomasklaush commented 2 years ago

That's the current one, I still get the error sometimes from the try-catch in the catch statement. It's not working yet, but I'm on the way.

I want to have a Stream which reads the Tag every period to check if there is a Tag or not. So I can detect if there is a Tag (Add connect via BLE to the found ID), or if there isn't (and disconnect from BLE.

Earlier, I forgot the await statement in front of the finish() and the Timer war before finish() and poll() This was the overkill for the application.

@override
  Stream<dartz.Either<BleConnectionFailure, String>> getDIDStream() async* {
    logger.i('NFC is avaliable: $_nfcAvaliable');
    const Duration timeout = Duration(seconds: 15);
    Stream<dartz.Either<BleConnectionFailure, String>> nfcStream() async* {
      while (true) {
        const Duration timeout = Duration(seconds: 5);
        String deviceId = "";
        await Future.delayed(timeout, () => {});
        try {
          await FlutterNfcKit.finish();
          final NFCTag tag = await FlutterNfcKit.poll(timeout: timeout, androidPlatformSound: false);

          // read NDEF records if available
          if (tag.ndefAvailable) {
            for (final record in await FlutterNfcKit.readNDEFRecords(cached: false)) {
              if (record is ndef.TextRecord) {
                //logger.d(record.text);
                deviceId = record.text ?? "";
              }
            }
          }
          logger.e(deviceId);
          yield dartz.right(deviceId);
        } on Exception catch (e) {
          logger.e(e);
          yield dartz.right("");
        }
      }
    }

    yield* nfcStream();
thomasklaush commented 2 years ago

Failed to handle method call E/MethodChannel#flutter_nfc_kit(22539): java.lang.IllegalArgumentException: com.xxxx.xxxxx: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. E/MethodChannel#flutter_nfc_kit(22539): Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

thomasklaush commented 2 years ago

The same code from you don't work with my app. It seems to be in combination of some Android System Messages, where the PendingIntend is used. Maybe the BLE Lib. I try to find a solution, but I can't say currently, which lib is causing the Platform Exception

E/MethodChannel#flutter_nfc_kit(17215): Failed to handle method call E/MethodChannel#flutter_nfc_kit(17215): java.lang.IllegalArgumentException: com.xxxxxxx.xxx: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. E/MethodChannel#flutter_nfc_kit(17215): Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles. E/MethodChannel#flutter_nfc_kit(17215): at android.app.PendingIntent.checkFlags(PendingIntent.java:375) E/MethodChannel#flutter_nfc_kit(17215): at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:458) E/MethodChannel#flutter_nfc_kit(17215): at android.app.PendingIntent.getActivity(PendingIntent.java:444) E/MethodChannel#flutter_nfc_kit(17215): at android.app.PendingIntent.getActivity(PendingIntent.java:408) E/MethodChannel#flutter_nfc_kit(17215): at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin.pollTag(FlutterNfcKitPlugin.kt:303) E/MethodChannel#flutter_nfc_kit(17215): at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin.handleMethodCall(FlutterNfcKitPlugin.kt:88) E/MethodChannel#flutter_nfc_kit(17215): at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin.onMethodCall(FlutterNfcKitPlugin.kt:62) E/MethodChannel#flutter_nfc_kit(17215): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233) E/MethodChannel#flutter_nfc_kit(17215): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:84) E/MethodChannel#flutter_nfc_kit(17215): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:865) E/MethodChannel#flutter_nfc_kit(17215): at android.os.MessageQueue.nativePollOnce(Native Method) E/MethodChannel#flutter_nfc_kit(17215): at android.os.MessageQueue.next(MessageQueue.java:335) E/MethodChannel#flutter_nfc_kit(17215): at android.os.Looper.loopOnce(Looper.java:161) E/MethodChannel#flutter_nfc_kit(17215): at android.os.Looper.loop(Looper.java:288) E/MethodChannel#flutter_nfc_kit(17215): at android.app.ActivityThread.main(ActivityThread.java:7839) E/MethodChannel#flutter_nfc_kit(17215): at java.lang.reflect.Method.invoke(Native Method) E/MethodChannel#flutter_nfc_kit(17215): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)

Harry-Chen commented 2 years ago

@thomasklaush I searched around and it looks like a bug outside this plugin: https://stackoverflow.com/questions/68228666/targeting-s-version-10000-and-above-requires-that-one-of-flag-immutable-or-fl. Would this workaround work for your case?

implementation 'androidx.work:work-runtime-ktx:2.7.1'
thomasklaush commented 2 years ago

@Harry-Chen sorry, I have to change my answer. It does not work. Thank you anyway

Harry-Chen commented 2 years ago

@thomasklaush Happy to hear that!

thomasklaush commented 2 years ago

@dangfan @Harry-Chen the update to 3.2.0 resolved the issue! Thanks.