Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android 12 - Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent #465

Open
SachinAgarwal1337 opened this issue Feb 23, 2022 · 25 comments

Comments

@SachinAgarwal1337
Copy link

SachinAgarwal1337 commented Feb 23, 2022

The plugin works perfectly in all devices except for Andorid 12.
I get following error

 Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent

I see the problem is in createPendingIntent Method

 private void createPendingIntent() {
        if (pendingIntent == null) {
            Activity activity = getActivity();
            Intent intent = new Intent(activity, activity.getClass());
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            pendingIntent = PendingIntent.getActivity(activity, 0, intent, 0); // Problem in the last param here
        }
    }

Would like to know if I am doing something wrong? or is this needs to be fixed

P.S I use this plugin for only reading NFC tags

@ghost
Copy link

ghost commented Jul 4, 2022

I can confirm this issue, the plugin is not usable on Android 12. Please fix!

@escully27
Copy link

Can confirm the same issue. Disabling plugin for now but will check into work arounds.

@escully27
Copy link

escully27 commented Jul 15, 2022

I fixed it by editing "NfcPlugin.java" under the Android file to have this code:

`
private void createPendingIntent() {

if (pendingIntent == null) {

        Activity activity = getActivity();
        Intent intent = new Intent(activity, activity.getClass());

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            pendingIntent = PendingIntent.getActivity(activity, 0, intent, PendingIntent.FLAG_IMMUTABLE);
        } else {
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            pendingIntent = PendingIntent.getActivity(activity, 0, intent, 0);
        }
    }

}`

@escully27
Copy link

@dilo99
Copy link

dilo99 commented Jul 21, 2022

ok, but on line 486 of NfcPlugin.java there's an error:
instead of '(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)'
i should be 'f (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) '
or it will not compile.
please fix it or i create another fork for it, but it seems useless to me
thanks

@dilo99
Copy link

dilo99 commented Jul 21, 2022

i fixed this on my fork: https://github.com/dilo99/phonegap-nfc

@escully27
Copy link

OK thanks. Let me know if helpful I can change mine otherwise probably best to do a PR for yours

@dilo99
Copy link

dilo99 commented Jul 21, 2022

@escully27 > OK thanks. Let me know if helpful I can change mine otherwise probably best to do a PR for yours

ok i created a PR, I don't know how useful it is, there are another 15 waiting for more than two years ...

@ReneDyhr
Copy link

How does this work for you guys? I've tried adding the fix but it won't work.
The Java code does register, but the action returns null and therefor never sends it back to Cordova.

@escully27
Copy link

escully27 commented Aug 10, 2022 via email

@ReneDyhr
Copy link

You have to update the repo you’re using and reinstall it, changing the Java code will be overwritten whenever it’s built and run again.

That I'm aware of and have of course made sure it's not being overwritten again.
And that I can also see in the app. Before the app won't load on Android 12 to now it will load, but the String action = intent.getAction(); from the parseMessage function now returns null.
This results in the Cordova app not getting the response and therefor never reacts on the NFC scanning

@escully27
Copy link

Can you post the full code surrounding the .getAction line that's returning null?

@ReneDyhr
Copy link

Can you post the full code surrounding the .getAction line that's returning null?

Of course!
To start with, you can see the createPendingIntent that I changed to the code provided from the PR.

private void createPendingIntent() {
    if (pendingIntent == null) {
        Activity activity = getActivity();
        Intent intent = new Intent(activity, activity.getClass());
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            pendingIntent = PendingIntent.getActivity(activity, 0, intent, PendingIntent.FLAG_IMMUTABLE);
        } else {
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            pendingIntent = PendingIntent.getActivity(activity, 0, intent, 0);
        }
    }
}

And then the parseMessage function until it stops.

void parseMessage() {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "parseMessage " + getIntent());
                Intent intent = getIntent();
                String action = intent.getAction();
                Log.d(TAG, "action " + action);
                if (action == null) {
                    return;
                }

Before the createPendingIntent fix, the action returned a string: android.nfc.action.TAG_DISCOVERED
After the fix, it now returns null and get into the if and stops.

@ReneDyhr
Copy link

ReneDyhr commented Aug 11, 2022

Addition to my last reply, I have the logs from NfcPlugin while it works and when it's broken.
Seems like the intent is changed and therefor wont work properly.

This is when it works.

NfcPlugin: onPause Intent {  }
NfcPlugin: stopNfc
NfcPlugin: onNewIntent Intent { act=android.nfc.action.TAG_DISCOVERED flg=0x34000000 mp=com.cleanmanager.application/.MainActivity (has extras) }
NfcPlugin: parseMessage Intent { act=android.nfc.action.TAG_DISCOVERED flg=0x34000000 cmp=com.cleanmanager.application/.MainActivity (has extras) }
NfcPlugin: action android.nfc.action.TAG_DISCOVERED

And after the fix:

NfcPlugin: onPause Intent {  }
NfcPlugin: stopNfc
NfcPlugin: onNewIntent Intent { flg=0x34000000 cmp=com.cleanmanager.application/.MainActivity }
NfcPlugin: parseMessage Intent { flg=0x34000000 cmp=com.cleanmanager.application/.MainActivity }
NfcPlugin: action null

Could it be because I'm using cordova-android@9.1.0? (UPDATE: Have tried both @10.0.0 and @11.0.0)

@ReneDyhr
Copy link

I do think I found my issue.
For my case it seems like I need to use FLAG_MUTABLE instead of FLAG_IMUTABLE.

Though since our app is backwards compatible with older Android versions, we had to hardcode the value for the flag, since FLAG_MUTABLE isn't available in our stack.

@Pynka
Copy link

Pynka commented Aug 21, 2022

For all Capacitor developers: Capawesome has recently announced an up-to-date Capacitor NFC plugin. Maybe worth a try. My client unfortunately still hangs on Cordova.

@Nickholas
Copy link

Nickholas commented Aug 22, 2022

I have the same problem after upgrade my solution to Android 32 but i works good before (Android 30)

Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent

Is it possible to resolve by my own? Other solution will be return to previous version but Google Play doesnt allow 30 anymore.

I have tried to change the line 486 by my self and seems to work fine but i am not sure if it will works for all devices:

\android\capacitor-cordova-android-plugins\src\main\java\com\chariotsolutions\nfc\plugin\NfcPlugin.java

@Paradox7208
Copy link

@Nickholas If you are still having issues with API 32, please refer to my comment on a similar issue. I hope it works for you.

#476 (comment)

@Nickholas
Copy link

I solved changing the line 486 of the folder called NfcPlugin.java that you can find in the ·..android\capacitor-cordova-android-plugins\src\main\java\com\chariotsolutions\nfc\plugin" directory.

pendingIntent = PendingIntent.getActivity(activity, 0, intent, PendingIntent.FLAG_IMMUTABLE);

@alioucisse7
Copy link

I do think I found my issue. For my case it seems like I need to use FLAG_MUTABLE instead of FLAG_IMUTABLE.

Though since our app is backwards compatible with older Android versions, we had to hardcode the value for the flag, since FLAG_MUTABLE isn't available in our stack.

I do think I found my issue. For my case it seems like I need to use FLAG_MUTABLE instead of FLAG_IMUTABLE.

Though since our app is backwards compatible with older Android versions, we had to hardcode the value for the flag, since FLAG_MUTABLE isn't available in our stack.

hi, any update for a solution ?

@csaar95
Copy link

csaar95 commented Oct 11, 2022

Ist this plugin still under maintenance as there hasn't been any activity for nearly 2 years?
There is an open merge request, which obviously fixing this problem, no response either.
We depend on this bugfix and can't publish our application for Android 12+ devices.

Do you recommend any other NFC plugin?

Related issue: ionic-team/capacitor#5392

@pilz97
Copy link

pilz97 commented Nov 24, 2022

@escully27 and @ath0mas thx for your forks.

But i get an build error:
image

Does your build work?

@Paradox7208
Copy link

@pilz97 do you have the build tools for Android API 30/31 installed? When I made my code change, I didn't have to include any additional import references than what were already in the solution.

@ath0mas
Copy link

ath0mas commented Nov 24, 2022

@pilz97 Indeed in my fork I went a bit too quick on removing the check on android.os.Build.VERSION.SDK_INT and now did a bit more debug on it:

  • yes the constant MUTABLE requires API Level 31+ for compilation : the compileSdk/buildTools should be 31 or newer
  • same warning on possible compilation error if using any Build.VERSION_CODES.xxx newer than your compileSdk/buildTools
  • and the check on Build.VERSION.SDK_INT at runtime may be better to have indeed
    It gets the Android version of the device running the app. If APIs newer than this runtime Android version are used, the problem will be that they will not be resolved correctly. For final static constants, like version codes or flags, the compilation inlines their value so there is no failure at runtime. In spite of this, I don't know if there is any side effect, so better to do the check and have 2 distinct branches in the code.

@pilz97
Copy link

pilz97 commented Nov 24, 2022

@Paradox7208 @ath0mas thx for your answers i still was on cordova-android 9.x now i upgraded to 11.0.0 and it works.
Thanks for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests