The day Google decided to shake the React Native Community
Google is known for its drastically and very fast-breaking changes on their versions of Android, meaning that your app could stop working by doing nothing but just existing.
This could be caused by a maven library that was deprecated and removed from their repository or an indirect dependency that now requires an X version which conflicts with one of your other dependencies. One way or another it’s really tedious to deal with these kinds of situations. Ex:
Let’s say that your team is planning to make a release during this week with a bunch of bug-fixes + some neat new features that the team has been working on for days, and all of the sudden the project just stops building, therefore you need to spend time fixing something that you initially did not break + time testing that the whole app is still working as intended.
Anyways, these are the things that Android developers accept because, in the end, we cannot fully control our indirect dependencies + external repository changes.
In order to solve this kind of situations you normally inject a dependency repository into your conflicting dependency or force a specific version of an android dependency so there are no more conflicts on your direct or indirect dependencies.
These kinds of issues don’t really take that long to be solved because they’re caused by one single dependency, maybe two in a bad day. But one day, something else happened.
It was June 17th, 2019, Android released their new package names for their DEPRECATED support libraries + other tools inside AndroidX, and…
What this release basically did is that if you used to import a library import android.support.annotation.*;
it should now be imported as import androidx.annotation.*
because the package of the class was moved.
Here is the map for all new packages:
This is the list of affected libraries:
Basically, all of the basic libraries that Google provide for the Android + React Native Community, on the last or close to last versions were affected. In some cases, it was the fault of the react-native libraries maintainers for using imports like +
symbols that are ambiguous and generally take the last version available of the library and in some other cases was caused by the fact that the developer was actually using new features from the latest release.
Initially, Google was expecting this to happen and they decided to release a tool called Jetifier:
The standalone Jetifier tool migrates support-library-dependent libraries to rely on the equivalent AndroidX packages instead. The tool lets you migrate an individual library directly, instead of using the Android gradle plugin bundled with Android Studio.
And that tools work perfectly, assuming your project and all its dependencies are native, which is not the case for the React Native Comunity. When you add this tool directly to the build process it takes in consideration just some of your direct native dependencies, not the big list of indirect dependencies, it doesn’t even take in consideration your own code.
So in the end, as a React Native Android Developer you have a few options:
Take in consideration that you can’t be in between, you either are fully using AndroidX or not, so the number of dependencies in your project directly affect this decision.
- Downgrade your Gradle version, build tools, target SDK to an older unaffected version which could just not work with your react-native + dependency versions.
- Wait until all your dependencies release a new version of their library that doesn’t require AndroidX with cases of some libraries already supporting AndroidX or your own project needing something from AndroidX causing you to basically not be able to use this option.
- Wait until all your dependencies release a new version of their library that supports AndroidX which will take a long time inside the community, some project will not even be updated because there are no active maintainers on it.
- DIY: Just do it your self, basically use the latest version of Gradle, build tools and target SDK on your project and a Jetifier variant inside your
node_modules
, the ugly side is the need to create scripts to do so because it’s basically a workaround + your app will take more time to build.
If downgrading doesn't work for you or if you have a lot of dependencies, in the end, the most logical reason is DIY, and for that, you’ll need to update your Gradle config to the recommended version by Google.
- Upgrade
com.android.tools.build:gradle
to v3.2.1 or later. - Upgrade
compileSdkVersion
to 28 or later. - Upgrade
missingDimensionStrategy “RNN.reactNativeVersion”
to version"reactNative57_5"
Also, add these two options to your AndroidManifest.xml
in your application
tag:
android:appComponentFactory="androidx"
tools:replace="android:appComponentFactory"
Also, update your gradle.properties
with:
Also, update your gradle-wrapper.properties
:
And then the ugly part, the script:
We really recommend using the Jetifier tool and for that, you’ll need:
npm install -g npx
npm install jetifier --save
oryarn add jetifier
The normal command you’ll be executing is npx jetify
to migrate to AndroidX all your node_modules
.
Now, Create the script scripts/fix-androidx.sh
This script will run the Jetifier tool + some direct regex replacements on some libraries because the tool didn’t work on them, in my case these were some of the ones I had problems with, but in your case could be different, if you find any other bad imports on your dependencies, add them to this script and replace older imports with the ones specified by Google on AndroidX.
Then add your script as a command to your package.json
"fix-androidx": ".scripts/fix-androidx"
Then it’s up to you where will you add it to be executed, I recommend you use it right after an install
or a clean
command is executed.
Conclusion
Your problem could be solved now and your app should start building again, but keep in mind that if you decided not to use AndroidX, eventually one of your dependencies or your own native code will need it and you’ll be forced to update.
If you decided to do the workaround, then eventually you’ll need to update your dependencies to an AndroidX supported version and this could include breaking changes, but it’s something that needs to be done to depend less on the Jetifier tool which highly increases build time.
One way or another, the job is not yet done, there are more things we need to do and as React Native Android Developer we should be up to the challenge and face it, it was a few awful days, but a lot of lessons were learned and we should see to the future with hope.
What about you, what was your experience during this AndroidX outbreak and what did you do to solve your issue? did this work for you? do you know a better way? looking forward to see your comments.