Recently I also needed to update my app's API level. In fact, making the compileSdkVersion lower than the targetSdkVersion seems to work, but while researching I noticed that this is not a recommended practice. I identified this here and here, for example. I know it's a difficult process, but I think it's worth trying to update the compileSdkVersion as well, and keep compileSdkVersion lower than targetSdkVersion only as a last resource.
In my case, I needed to make several updates to fix the side effects of the application's dependencies, updates that I will list below. Of course, other projects will probably need different configurations, but I hope this works for applications that have similar dependencies as mine.
API level
Changes in android/build.gradle:
Before
compileSdkVersion = 33
targetSdkVersion = 33
buildToolsVersion = "33.0.2"
After
compileSdkVersion = 34
targetSdkVersion = 34
buildToolsVersion = "34.0.0"
I have changed buildToolsVersion because of this page that says that "You should always keep your Build Tools component updated".
While updating the API version I started getting the following error:
Android Gradle build error "AAPT2 aapt2-4.1.0-6503028-windows Daemon #0: Unexpected error during link, attempting to stop daemon."
This answer gave me an insight that the issue was related to gradle, so I changed Gradle and Gradle Plugin versions:
Gradle
Changes in android/gradle/gradle-wrapper.properties
Before:
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
After:
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
Changes in android/build.gradle
Before:
classpath('com.android.tools.build:gradle:7.0.2')
classpath 'com.google.firebase:perf-plugin:1.4.0'
After:
classpath 'com.android.tools.build:gradle:7.2.2'
classpath "com.google.firebase:perf-plugin:1.4.1"
Note: I also needed to upgrade Firebase's plugin version because of this error:
Unable to load class AndroidComponentsExtension
I solved it thanks to this answer.
Important: keep in mind that the Gradle version is not the same as the Gradle Plugin version. This information is relevant so that you know how to choose the correct and compatible versions of Gradle and Gradle Plugin, instead of blindly trying to make it work.
Other tweaks
These updates ended up causing some problems with the libs in my package.json. This part is very specific and you may not have any errors, or you may have different errors, but in case it is useful to someone I will describe the fixes I made:
Changes in package.json
Before:
"react-native": "0.65.3",
"react-native-screens": "3.10.2",
"react-native-webview": "11.13.1"
After:
"react-native": "0.66.5",
"react-native-screens": "3.22.1",
"react-native-webview": "11.22.7"
I also needed to add resolutions, as below:
"resolutions": {
"@react-native-community/cli": "^7.0.0",
"@react-native-community/cli-config": "^7.0.0",
"@react-native-community/cli-debugger-ui": "^7.0.0",
"@react-native-community/cli-doctor": "^7.0.0",
"@react-native-community/cli-platform-android": "^7.0.0",
"@react-native-community/cli-platform-ios": "^7.0.0",
"@react-native-community/cli-server-api": "^7.0.0",
"@react-native-community/cli-tools": "^7.0.0",
"@react-native-community/cli-types": "^7.0.0"
}
Why those updates in package.json?
I needed to update the WebView because the app was not building correctly. I was able to fix it with the help of this page.
For React Native Screens, I came across the following error:
Type mismatch: inferred type is Canvas? but Canvas was expected
I fixed it by using this suggestion.
Now about React Native: due to the update of React Native Screens the app started to present a bug in the keyboard. I was able to fix it thanks to this answer.
Finally, for the resolutions, I added them because I started facing the error below, fixed thanks to this answer:
Could not find method exec() for arguments [ReactNativeModules$_getCommandOutput_closure16@4a1214df] on object of type org.gradle.api.internal.provider.DefaultProviderFactory_Decorated
As I said before, the tweaks in package.json are very specific, so you may encounter other errors. In any case, I hope I have given you some insight into this headache that is Android API level updates.
EDIT:
Error: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified
Some devices started to show an error after the API update:
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
Caused by:
com.github.yamill.orientation.OrientationModule.onHostResume
Apparently, when updating the API level this problem can happen with several React Native libs (it seems that it happened to @Alan too). In my case, the problem was in the react-native-orientation lib.
I fixed it thanks to this page, by creating a patch after changing two files:
node_modules/react-native-orientation/android/build.gradle
Original code from react-native-orientation:
apply plugin: 'com.android.library'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
}
dependencies {
compile "com.facebook.react:react-native:+"
}
Final result:
apply plugin: 'com.android.library'
def getExtOrDefault(name, defaultVal) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : defaultVal
}
android {
compileSdkVersion getExtOrDefault('compileSdkVersion', 23)
buildToolsVersion getExtOrDefault('buildToolsVersion', "23.0.1")
defaultConfig {
minSdkVersion getExtOrDefault('minSdkVersion', 16)
targetSdkVersion getExtOrDefault('targetSdkVersion', 22)
versionCode 1
versionName "1.0"
// ndk {
// abiFilters "armeabi-v7a", "x86"
// }
}
}
dependencies {
implementation "com.facebook.react:react-native:+"
}
And then I fixed the second file:
node_modules_react-native-orientation/android/src/main/java/com/github/yamill/orientation/OrientationModule.java
You need to replace this line:
activity.registerReceiver(receiver, new IntentFilter("onConfigurationChanged"));
with this one (don't forget to add the import):
import android.os.Build;
// ...
if (Build.VERSION.SDK_INT >= 34 && activity.getApplicationInfo().targetSdkVersion >= 34) {
activity.registerReceiver(receiver, new IntentFilter("onConfigurationChanged"), Context.RECEIVER_EXPORTED);
} else {
activity.registerReceiver(receiver, new IntentFilter("onConfigurationChanged"));
}
Finally, execute the command:
yarn patch-package react-native-orientation
and you're done.