I am getting a crash with my android apps. Which shows security exception with the targetSDKVersion 34.
How to resolve this. The error is showing as below (playcore library) com.google.android.play.core.listener.zzc.zzb (com.google.android.play:core@@1.10.3:3)
Note: I am using the LocalBroadcastManager in my app. Is this issue raised because of this?
Code:
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, filter)
Error:
Fatal Exception: java.lang.SecurityException
pck: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
android.os.Parcel.createExceptionOrNull (Parcel.java:3057)
android.content.ContextWrapper.registerReceiver (ContextWrapper.java:755)
com.google.android.play.core.listener.zzc.zzb (com.google.android.play:core@@1.10.3:3)
com.google.android.play.core.listener.zzc.zzf (com.google.android.play:core@@1.10.3:4)
com.google.android.play.core.appupdate.zzf.registerListener (com.google.android.play:core@@1.10.3:1)
fragments.Summaryfragment.onCreate (Summaryfragment.java:144)
androidx.fragment.app.Fragment.performCreate (Fragment.java:2949)
androidx.appcompat.app.AppCompatActivity.onStart (AppCompatActivity.java:246)
ActionBarFragmentActivity.onStart (ActionBarFragmentActivity.java:358)
android.app.Instrumentation.callActivityOnStart (Instrumentation.java:1582)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:971)
Since Android 14 there is a requirement to specify the export flag when registering context-registered receivers - https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported
Apps and services that target Android 14 and use context-registered receivers are required to specify a flag to indicate whether or not the receiver should be exported to all other apps on the device either
RECEIVER_EXPORTED
orRECEIVER_NOT_EXPORTED
, respectively.
If your MessageReceiver
is supposed to be called only by the components within your app, then you should use RECEIVER_NOT_EXPORTED
. If it is supposed to be accessible to components beyond your own app - use RECEIVER_EXPORTED
.
Now, before you try to apply the change, you have to migrate from the deprecated LocalBroadcastManager
since it does not allow you to specify the export flag. I would advise you to use ContextCompat
class to register the receiver now. Your code should look more or less like this now:
import androidx.core.content.ContextCompat
ContextCompat.registerReceiver(
this,
mMessageReceiver,
filter,
ContextCompat.RECEIVER_NOT_EXPORTED
)
Now this code will not throw an error now, but it still might not work - Android 14 introduced another restriction when it comes to sending implicit intents to non-exported components: https://developer.android.com/about/versions/14/behavior-changes-14#safer-intents
In your case, if you're using the RECEIVER_EXPORTED
flag, you should not worry about this change in this context.
If you're using RECEIVER_NOT_EXPORTED
(like on the code above) and you're calling the MessageReceiver
with an implicit intent, probably using intent action:
context.sendBroadcast(Intent(YOUR_APP_ACTION))
then you should make that Intent
explicit, because otherwise it would not be received on Android 14+:
context.sendBroadcast(
Intent(YOUR_APP_ACTION).apply {
setPackage(context.packageName)
}
)
Specifying a package makes the Intent
explicit - the non-exported MessageReceiver
is able to receive those intents now.