Android Question Help: FLAG_IMMUTABLE or FLAG_MUTABLE

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
hi,

i get this error message when running on phone with android 13
on version 9 it works
i set targetsdk to 31
when reduce it to 30 it works on the new phone

my B4A version is 12

searching the forum i found some other posts on that topic and they were referred to use NB6 - here i got lost
i couldn't find any sample that works as all are either partial or used for services which i don't

i don't want to use sdk less than 31 as this is the recommendation now...

anyone can help ?
thanks
 
Solution
Last try - see if attached is working for "31". Have changed the Java code to be as follows:

B4X:
    NFCUtils(final Activity pActivity) {
        mActivity = pActivity;
        mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
        if (Build.VERSION.SDK_INT < 31) {
            mPendingIntent = PendingIntent.getActivity(mActivity, 0,
                    new Intent(mActivity, mActivity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        } else {
       
            mPendingIntent = PendingIntent.getActivity(mActivity, 0,
                    new Intent(mActivity, mActivity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 67108864);
        }  
    }

@agraham , please comment if I have it...

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
More information needed as to what the error is. Post the log.
here it is...

Error occurred on line: 182 (Main)
java.lang.IllegalArgumentException: arkom.CardReader.android: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
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.
at android.app.PendingIntent.checkFlags(PendingIntent.java:408)
at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:491)
at android.app.PendingIntent.getActivity(PendingIntent.java:477)
at android.app.PendingIntent.getActivity(PendingIntent.java:441)
at io.github.tapcard.android.NFCUtils.<init>(NFCUtils.java:87)
at io.github.tapcard.android.NFCCardReader.<init>(NFCCardReader.java:32)
at tapcardwrapper.tapcardWrapper.Initialize(tapcardWrapper.java:83)
at arkom.CardReader.android.main$ResumableSub_Activity_Create.resume(main.java:668)
at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resumeAsUserSub(DebugResumableSub.java:48)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:146)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:193)
at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resume(DebugResumableSub.java:43)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:267)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:139)
at anywheresoftware.b4a.BA$2.run(BA.java:387)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8741)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
** Activity (main) Pause, UserClosed = true **
 
Upvote 0

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
Doesn't look like anything to do with NB6. Whatever arkom.CardReader is it looks like it needs an update.
update what?
it is on B4A 12
sdk 31
a simple app (most taken from Johan's TapCard sample - his code as is)
even his original code (link will follow) shows this error

i'm lost as this is going to be a very critical part of my project...

this is Johan's great great example and project

just run it with targetsdk = 31
 
Upvote 0

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
arkom.CardReader as I just said - whatever it is. Presumably it is part of a library or something if the original example also throws this error. Android now requires an additional flag for PendingIntents.
oh, thanks

what permission i need?
in manifest?
in code?
both?
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
I've poked around in the
what permission i need?
You don't. As I have said twice above some library needs updating to add an extra flag.

I've poked around inside Tapcard.jar and the constructor for the call to PendingIntent.getActivity(...) in the NFCUtils class constructor needs needs FLAG_IMMUTABLE specifying to run on SDK31 and higher. I've no idea where Tapcard.jar comes from but whoever wrote it needs to modify it.
 
Upvote 0

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
I've poked around in the

You don't. As I have said twice above some library needs updating to add an extra flag.

I've poked around inside Tapcard.jar and the constructor for the call to PendingIntent.getActivity(...) in the NFCUtils class constructor needs needs FLAG_IMMUTABLE specifying to run on SDK31 and higher. I've no idea where Tapcard.jar comes from but whoever wrote it needs to modify it.
ok
can you tell which libraries?
or where do i get these updates?
i just updated to b4a 12.20 - i'm not sure it did update any libs as it was quite small anf went very fast...
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
can you tell which libraries?
For God's sake I've just told you above exactly what is needed. Tapcard.jar needs modifying as I said. I think Johan Schoeman probably wrote it as it include the B4A wrapper class. He needs to modiy it.
 
Upvote 0

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
For God's sake I've just told you above exactly what is needed. Tapcard.jar needs modifying as I said. I think Johan Schoeman probably wrote it as it include the B4A wrapper class. He needs to modiy it.
thanks, i missed it, i'll try to contact him and ask...
by setting sdk to 30 all works perfectly - so my next "dumb" question is - what if i go with sdk 30?
will it be blocked by google?

and if i may i have another question on another topic -
file.makedir on external storage doesn't seems to work

B4X:
File.MakeDir(File.DirRootExternal,"/Zeev")

i got the permission
on older phone it works
on new/updated phones it just ignore it - no error generated

i need to create a shared folder to share it with another app i have
i see so many other apps do that and create their on folder to keep their stuff
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
For God's sake I've just told you above exactly what is needed. Tapcard.jar needs modifying as I said. I think Johan Schoeman probably wrote it as it include the B4A wrapper class. He needs to modiy it.
Zeev, you can try with the attached lib files (jar and xml). No idea if it will solve your problem. Have changed the constructor to be as follows:

FLAG_IMMUTABLE:
    NFCUtils(final Activity pActivity) {
       
        int flags = Intent.FLAG_ACTIVITY_SINGLE_TOP;
       
        if (Build.VERSION.SDK_INT >= 31)
            flags |= 67108864; //FLAG_IMMUTABLE
       
        mActivity = pActivity;
        mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
        mPendingIntent = PendingIntent.getActivity(mActivity, 0,
                new Intent(mActivity, mActivity.getClass()).addFlags(flags), 0);
    }
 

Attachments

  • TapCardImmutable.zip
    128.7 KB · Views: 73
Upvote 0

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
Zeev, you can try with the attached lib files (jar and xml). No idea if it will solve your problem. Have changed the constructor to be as follows:

FLAG_IMMUTABLE:
    NFCUtils(final Activity pActivity) {
      
        int flags = Intent.FLAG_ACTIVITY_SINGLE_TOP;
      
        if (Build.VERSION.SDK_INT >= 31)
            flags |= 67108864; //FLAG_IMMUTABLE
      
        mActivity = pActivity;
        mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
        mPendingIntent = PendingIntent.getActivity(mActivity, 0,
                new Intent(mActivity, mActivity.getClass()).addFlags(flags), 0);
    }
thank you Johan
i will go over the sample and hope it solves the issue
will of course revert and update
(hope you're well)
 
Upvote 0

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
Zeev, you can try with the attached lib files (jar and xml). No idea if it will solve your problem. Have changed the constructor to be as follows:

FLAG_IMMUTABLE:
    NFCUtils(final Activity pActivity) {
      
        int flags = Intent.FLAG_ACTIVITY_SINGLE_TOP;
      
        if (Build.VERSION.SDK_INT >= 31)
            flags |= 67108864; //FLAG_IMMUTABLE
      
        mActivity = pActivity;
        mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
        mPendingIntent = PendingIntent.getActivity(mActivity, 0,
                new Intent(mActivity, mActivity.getClass()).addFlags(flags), 0);
    }
Update 2
Seems there's a problem
I changed the sdk to 31 as I want it to be on Google store
I run the app from my main app as intent

On previous libs & sdk 30 it all worked perfectly, now with new libs and sdk 31 the app loads and crashes

I will change sdk back to 30 and check
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Update 2
Seems there's a problem
I changed the sdk to 31 as I want it to be on Google store
I run the app from my main app as intent

On previous libs & sdk 30 it all worked perfectly, now with new libs and sdk 31 the app loads and crashes

I will change sdk back to 30 and check
What is the "crash" message in the B4A log?
 
Upvote 0

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
ok, final update with findings

on sdk 30 all is perfect - checked on android 9 - 13

on sdk 31 on older versions like 9 - works fine
on android 13 it crached on the following line

B4X:
    tapcard.Initialize("ips")

the log for the error is: (all other logs you showed are ok)

Error occurred on line: 267 (Main)
java.lang.IllegalArgumentException: arkom.nfc: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
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.
at android.app.PendingIntent.checkFlags(PendingIntent.java:408)
at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:491)
at android.app.PendingIntent.getActivity(PendingIntent.java:477)
at android.app.PendingIntent.getActivity(PendingIntent.java:441)
at io.github.tapcard.android.NFCUtils.<init>(NFCUtils.java:105)
at io.github.tapcard.android.NFCCardReader.<init>(NFCCardReader.java:32)
at tapcardwrapper.tapcardWrapper.Initialize(tapcardWrapper.java:83)
at arkom.nfc.main$ResumableSub_Activity_Create.resume(main.java:673)
at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resumeAsUserSub(DebugResumableSub.java:48)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resume(DebugResumableSub.java:43)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:275)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:150)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
at anywheresoftware.b4a.keywords.Common$15.run(Common.java:1804)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8741)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
 
Upvote 0

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
here are two more things

on older android the expiry comes where year is 4 digits like 10/2025
on android 13 it come 2 digits like 10/25
that's not really an issue as is is solved in code simply by checking the year element so it can be ignored

one strange thing - with the new libs the returning of scanned data looks much faster - there is no delay time at all
also good (!)

so i think the only issue is sdk 31 with android 13 (obviously)
at this point i returned to sdk 30 and holding my breath... :)
 
Upvote 0
Top