As a mobile developer, you have to upgrade the SDK version time to time. Upgrading your React Native app to target SDK version 34 (for Android 14) can introduce several new challenges, leading to app crashes immediately after launch. If you’re experiencing crashes and your React Native version is 0.70.5, you might encounter the following errors:
Fatal Exception: java.lang.SecurityException
One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn’t being registered exclusively for system broadcasts
Before start solving you should understand the error first. This error arises in Android 13 (API level 33) and becomes mandatory in Android 14 (API level 34). It’s a security enhancement that clarifies whether your broadcast receiver is intended for internal app communication (not exported) or can be accessed by other apps (exported).
RECEIVER_EXPORTED: Use this flag if the receiver needs to be accessible by other apps on the device. This should be used cautiously, as it increases the potential attack surface of your app. RECEIVER_NOT_EXPORTED: Use this flag if the receiver is intended for internal app communication and should not be accessible by external apps. This is the recommended approach for most cases.
Solution
Here’s a step-by-step guide to resolve these issues without changing the React Native version:
1. Modify MainApplication.java
Open your Android project and follow these steps:
Import Required Classes: Add the following import statements at the top of your MainApplication.java
file:
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import org.jetbrains.annotations.Nullable;
Override registerReceiver
Method: Override the registerReceiver
method to specify the broadcast receiver permissions conditionally based on the SDK version. Add this code above the onCreate()
method in MainApplication.java
:
@Override
public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) {
if (Build.VERSION.SDK_INT >= 34 && getApplicationInfo().targetSdkVersion >= 34) {
return super.registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED);
} else {
return super.registerReceiver(receiver, filter);
}
}
Update build.gradle Dependencies: Open the android/app/build.gradle
file and add the following line inside the dependencies
block:
implementation 'org.jetbrains:annotations:16.0.2'
Now run your project. I hope this will fix the issue. However there may be multiple errors you will face some of them are.
Compile Sdk Issue:
The minCompileSdk (32) specified in a
dependency's AAR metadata (META-INF/com/android/build/gradle/aar-metadata.properties)
is greater than this module's compileSdkVersion (android-31).
Solution: upgrade minComplieSdk to 33
Third-Party package issues:
If your project is running successfully but giving the below error as soon as splash screen hides. Then the issue may be because of the third-party issue.
Fatal Exception: java.lang.SecurityException
One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
Solution: To fix the issue, you need to find the package which is using registerReceiver function, but finding exact package that is creating issue from list of packages is very hard. However i have some steps for you to help you to find the package below.
- Run the command below, which will show you the file that contains the registerReceiver function.
grep -r registerReceiver .
- After running the above command, you will have a clear idea of the package which is using the function. If the packages have latest version, you can update the package or go to the file where the function is used, add Context.RECEIVER_EXPORTED or Context.RECEIVER_NOT_EXPORTED as per your need as a third parameter of the function.
Some popular packages with the fixes.
- react-native-share:
File path: /node_modules/ react-native-share/ android/ src/main/java/ cl/json/ social/ TargetChosenReceiver.java
Replace: context.registerReceiver( sLastRegisteredReceiver , new IntentFilter(sTargetChosenReceiveAction));
by: context.registerReceiver(sLastRegisteredReceiver, new IntentFilter(sTargetChosenReceiveAction), Context.RECEIVER_EXPORTED);
- react-native-orientation:
File path: node_modules/ react-native-orientation/ android/src/ main/java/ com/github/ yamill/ orientation/ OrientationModule.java
Replace: activity.registerReceiver(receiver, new IntentFilter("onConfigurationChanged"));
by: activity.registerReceiver(receiver, new IntentFilter("onConfigurationChanged"), Context.RECEIVER_EXPORTED);
Similarly, you just have to add Context.RECEIVER_EXPORTED as a third parameter and run the project
I hope this blog helped you to fix the error, Happy coding !