Android Question [SOLVED] API 31 FLAG_MUTABLE problem with Core.Intent object - November 1 deadline

JackKirk

Well-Known Member
Licensed User
Longtime User
I am way over my paygrade with this...

I currently use the Core.Intent object to provide media sharing capabilities in my app.

If I set [android:targetSdkVersion="31"] in the manifest I get the dreaded error message:
Caused by: java.lang.IllegalArgumentException: treetops.app.customer: 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.

Scratching around the B4A forum I see that Erel has already fixed a similar issue in the [NB6.b4xlib] library.

I tried to work out how to jury-rig my code by imitating(???) what he did in this library - with no success.

I have come to the conclusion that some fiddling in the Core.Intent code needs to be done that is way beyond me.

According to the Google Developer website any new app has to be at API 31 and any updates of older apps must be brought up to API 31 by November this year.

So if I can find no solution to this I will not be able to update my app from start of November.

Do the custodians of the Core have this in hand?
 
Last edited:

JackKirk

Well-Known Member
Licensed User
Longtime User
Please post the full error message and the relevant code.
Erel, here is the error dump:
Error occurred on line: 233 (Share_Handler_Class)
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
at treetops.app.customer.share_handler_class._send_intent(share_handler_class.java:523)
at treetops.app.customer.share_handler_class._initialize(share_handler_class.java:483)
at treetops.app.customer.share_handler_service._service_start(share_handler_service.java:176)
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:348)
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 treetops.app.customer.share_handler_service.handleStart(share_handler_service.java:100)
at treetops.app.customer.share_handler_service.access$000(share_handler_service.java:8)
at treetops.app.customer.share_handler_service$1.run(share_handler_service.java:71)
at anywheresoftware.b4a.objects.ServiceHelper$StarterHelper.onStartCommand(ServiceHelper.java:237)
at treetops.app.customer.share_handler_service.onStartCommand(share_handler_service.java:69)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4643)
at android.app.ActivityThread.access$2000(ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2095)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7842)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.IllegalArgumentException: treetops.app.customer: 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:375)
at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645)
at android.app.PendingIntent.getBroadcast(PendingIntent.java:632)
at treetops.app.customer.share_handler_class$MyBroadcastReceiver.SendIntent(share_handler_class.java:537)
... 27 more
As regards the relevant code, I have spent the last couple of hours trying to net it down to something relatively short without success.

I would be willing to PM you the entire project but I think you might gag on the scale of it.

Can't you add it with Flags? The value is 0x2000000.
Andrew, as I said in the first post "I tried to work out how to jury-rig my code by imitating(???) what he did in this library - with no success."

I came up with this:
B4X:
    'Following code required at Android 12 (SDK/API 31) to avoid runtime error:
    '    Caused by: java.lang.IllegalArgumentException: treetops.app.customer: 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.
    'And is inspired by NB6.bas code in:
    '    C:\Program Files\Anywhere Software\B4A\Libraries\NB6.b4xlib\
    'For FLAG_MUTABLE/FLAG_IMMUTABLE flag values see:
    '    https://developer.android.com/reference/kotlin/android/app/PendingIntent#FLAG_IMMUTABLE:kotlin.Int
    '    FLAG_MUTABLE = 33554432
    '    FLAG_IMMUTABLE = 67108864

    'Get SDK level
    Private wrk_sdklevel As Int
    Private wrk_jo2 As JavaObject
    wrk_sdklevel = wrk_jo2.InitializeStatic("android.os.Build$VERSION").GetField("SDK_INT")
    
    'If SDK level is >= 31, add FLAG_MUTABLE
    If wrk_sdklevel >= 31 Then wrk_intent.Flags = Bit.Or(wrk_intent.Flags, 33554432)
which I think is in the vein you are suggesting - unfortunately, it didn't work.
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
Erel, Andrew,

B4X:
Private Sub Send_Intent(In_tent As Intent)

    Private wrk_jo As JavaObject
    
    Private wrk_scrw As String

    'See:
    'https://www.b4x.com/android/forum/threads/solved-this-class-name.73206/post-465155
    wrk_jo = Me
    wrk_scrw = wrk_jo.RunMethod("getClass",Null)
    wrk_scrw = wrk_scrw.SubString(wrk_scrw.LastIndexOf(".") + 1)

    wrk_scrw = "." & wrk_scrw & "$MyBroadcastReceiver"

    wrk_jo.InitializeNewInstance(Application.PackageName & wrk_scrw, Array(Me))
    
    'This will launch standard Android share sheet
    wrk_scrw = "SendIntent"
Log(1)
    StartActivity(wrk_jo.RunMethod(wrk_scrw, Array(In_tent)))
Log(2)

End Sub

I added the 2 Log statements to show exactly where it fails.

The error dump is:
1
Error occurred on line: 225 (Share_Handler_Class)
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
at treetops.app.customer.share_handler_class._send_intent(share_handler_class.java:526)
at treetops.app.customer.share_handler_class._initialize(share_handler_class.java:483)
at treetops.app.customer.share_handler_service._service_start(share_handler_service.java:176)
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:348)
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 treetops.app.customer.share_handler_service.handleStart(share_handler_service.java:100)
at treetops.app.customer.share_handler_service.access$000(share_handler_service.java:8)
at treetops.app.customer.share_handler_service$1.run(share_handler_service.java:71)
at anywheresoftware.b4a.objects.ServiceHelper$StarterHelper.onStartCommand(ServiceHelper.java:237)
at treetops.app.customer.share_handler_service.onStartCommand(share_handler_service.java:69)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4643)
at android.app.ActivityThread.access$2000(ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2095)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7842)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.IllegalArgumentException: treetops.app.customer: 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:375)
at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645)
at android.app.PendingIntent.getBroadcast(PendingIntent.java:632)
at treetops.app.customer.share_handler_class$MyBroadcastReceiver.SendIntent(share_handler_class.java:543)
... 27 more
Note it gets to Log(1) but never makes Log(2).

Thanks for your attention to this...
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
I will answer that the error has nothing to do with Core.Intent and is not something that can be fixed by updating the core library.
Erel, well it sure has to do with something outside my area of expertise.

I had another crack at creating a small project that demonstrates the problem - this time I grafted the necessary code onto a basic app framework rather than trying to net down my big app.

Attached is the result.

Run it on an Android 12 device.

As supplied, the manifest is set to [android:targetSdkVersion="30"]

If you run the project as supplied you should end up seeing the Android share sheet displayed, something like:

Screenshot_20221008-145058.png


If you change the manifest to [android:targetSdkVersion="31"] and run it again, it bombs with:

Error occurred on line: 33 (Share_Handler_Class)
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
at b4a.example.share_handler_class._initialize(share_handler_class.java:114)
at b4a.example.share_handler_service._service_start(share_handler_service.java:163)
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:348)
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 b4a.example.share_handler_service.handleStart(share_handler_service.java:100)
at b4a.example.share_handler_service.access$000(share_handler_service.java:8)
at b4a.example.share_handler_service$1.run(share_handler_service.java:71)
at anywheresoftware.b4a.objects.ServiceHelper$StarterHelper.onStartCommand(ServiceHelper.java:237)
at b4a.example.share_handler_service.onStartCommand(share_handler_service.java:69)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4643)
at android.app.ActivityThread.access$2000(ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2095)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7842)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.IllegalArgumentException: b4a.example: 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:375)
at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645)
at android.app.PendingIntent.getBroadcast(PendingIntent.java:632)
at b4a.example.share_handler_class$MyBroadcastReceiver.SendIntent(share_handler_class.java:128)
... 26 more

I hope this helps to fix it...
 

Attachments

  • IntentTest.zip
    15.8 KB · Views: 87
Last edited:
Upvote 0

agraham

Expert
Licensed User
Longtime User
Simples! Uk cultural reference
Java:
#If Java
import android.content.*;
import android.app.*;
import android.os.Build;
public static class MyBroadcastReceiver extends BroadcastReceiver
{
    private BA ba;
    public MyBroadcastReceiver(B4AClass target) {
        ba = target.getBA();
    }
    public Intent SendIntent (Intent share) {
        String shareAction = "content_chooser_result_13";
        Intent receiver = new Intent(shareAction);
                int flags =  PendingIntent.FLAG_UPDATE_CURRENT;
          if (Build.VERSION.SDK_INT >= 31)
            flags |= 0x2000000;
        PendingIntent pi = PendingIntent.getBroadcast(ba.context, 0, receiver, flags);
        share = Intent.createChooser(share, null, pi.getIntentSender());
        ba.context.registerReceiver(this, new IntentFilter(shareAction));
        return share;
    }
    @Override public void onReceive(Context context, Intent intent) {
        ba.raiseEventFromUI(null, "contentchooser_receive", intent);
        ba.context.unregisterReceiver(this);
    }
}

#End If
It would have helped if you had shown us the code that was failing.
 
Last edited:
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
Andrew, thanks - that did the trick.

It would have helped if you had shown us the code that was failing.
I actually tried early in the piece to create a cut down version to demonstrate the problem - tried to take my big app and net it down - got into all sorts of grief. Second time I just grafted the necessary code onto a basic app framework which worked quite easily.

I guess there is a lesson in that.

String shareAction = "content_chooser_result_13";
While I have your attention - I have never understood this line - can you enlighten me?

Thanks again...
 
Upvote 0
Top