Say bye-bye to Android Jetifier
Jetpack is a set of libraries, tools, and guidance to help you write high-quality apps more easily. Jetpack makes coding easier through best practices, limiting boilerplate code, and simplifying complex tasks. All with the goal of enabling you to focus on the code that you really care about.
AndroidX is the package name for all the libraries within Jetpack. Think of AndroidX as the open-source project used to develop, test, version, and release Jetpack libraries.
Back at I/O 2018, Google announced that Support Library would be refactored into the AndroidX namespace, which was completed with Support Library 28 and the announcement of AndroidX 1.0.
Jetifier helps migrate third-party dependencies to use AndroidX. Jetifier will change the byte code of those dependencies to make them compatible with projects using AndroidX.
Jetifier enabled on your project (
android.enableJetifier = true on your
gradle.properties) impacts on the build speed, because the
Android Gradle Plugin has to transform all the support-library-dependent artifacts to
AndroidX. So, disabling
jetifier is a good idea for your android project if you want to reduce the build speed. But doing that is not always a trivial task. That’s why we prepared a list of
6 steps to follow, so you can fully migrate your app to
AndroidX and then safely disable
If your own source code is already migrated to
androidx, just skip this step and go directly to
step 2. If not, migrating your code to
androidx should be your first task. You can read this article with some tips & tricks:
Migrating to AndroidX: Tip, Tricks, and Guidance
Take advantage of the latest Jetpack has to offer.
Get a list of all the support-library-dependent dependencies in your project. This list should also include transitive dependencies.
To do that you can use our
Bye Bye Jetifier Gradle plugin:
Gradle Plugin to verify if you can keep Android Jetifier disabled This plugin verifies on each dependency JAR/AAR (and…
The plugin verifies on each dependency JAR/AAR (and its transitives) if:
- any class is using a support library import
- any layout is referencing a support library class
- the Android Manifest is referencing a support library class
It also verifies if any support library dependency is resolved on the project.
Why should I use this plugin instead of can-i-drop-jetifier?
can-i-drop-jetifier plugin only checks for legacy support libraries on the dependencies graph. That’s not enough to decide if you can drop Jetifier. Lots of libraries don’t properly declare on their POMs the legacy support libraries they use as transitive dependencies. So, for those cases,
can-i-drop-jetifier says that you can disable Jetifier. But, if you do that, then you are going to have runtime errors when the logic using the legacy support library is executed.
Bye bye Jetifier inspects each JAR/AAR, searching for legacy support libraries usages, so it will find more libraries than
can-i-drop-jetifier, and you will avoid those runtime errors.
The setup is easy. Just add this configuration to your root
build.gradle, replacing X.Y.Z with the latest version
apply plugin: "com.dipien.byebyejetifier"
And then execute the following task:
./gradlew canISayByeByeJetifier -Pandroid.enableJetifier=false
If you have any legacy android support library usage, the task will fail and print a report with all the details.
Absoulute path: ~/.gradle/caches/modules-2/files-2.1/com.github.bumptech.glide/glide/3.8.0/9bada6526fe0/glide-3.8.0.jar
Graphs to this dependency:
* com/bumptech/glide/Glide.class -> android/support/v4/app/FragmentActivity
* com/bumptech/glide/Glide.class -> android/support/v4/app/Fragment
* com/bumptech/glide/manager/RequestManagerRetriever.class -> android/support/v4/app/FragmentManager
* com/bumptech/glide/manager/RequestManagerRetriever.class -> android/support/v4/app/FragmentActivity
* com/bumptech/glide/manager/RequestManagerRetriever.class -> android/support/v4/app/Fragment
* com/bumptech/glide/manager/RequestManagerRetriever.class -> android/support/v4/app/FragmentTransaction
* com/bumptech/glide/manager/SupportRequestManagerFragment.class -> android/support/v4/app/Fragment
* com/bumptech/glide/manager/SupportRequestManagerFragment.class -> android/support/v4/app/FragmentActivity
* com/bumptech/glide/manager/SupportRequestManagerFragment.class -> android/support/v4/app/FragmentManager
Explicit declarations of legacy support dependencies on this project:
> Task :canISayByeByeJetifier FAILED
For each support-library-dependent library obtained in the previous step, you need to define how to remove all the support library references.
Upgrading the dependency to the latest version should be your first action. If you have luck, it is now migrated to
androidx. If not, here are some tips according to the kind of dependency.
For libraries which you are the owner of the source code:
Just migrate it to
androidx, upgrade all its dependencies and then release a new version. Remember to add this line to the
gradle.properties of your library:
android.useAndroidX = true
That line is especially important if you are using
databinding, because it will automatically switch from
support library databinding to
For libraries which you are NOT the owner of the source code:
These are some alternatives:
1. If you don’t have access to the library source code or if its usage is deprecated on your project, you can use the
jetifier-standalone command-line tool to transform the library
AAR/JAR to a
jetified AAR/JAR. This tool executes the same transformation as the Android Gradle Plugin when you have the flag
The command to run is simple:
./jetifier-standalone -i <source-library> -o <output-library>
On the Jetifier docs you can find more info about the tool.
Once you generated the
jetified AAR/JAR, you should deploy it on any Maven repository using your own
groupId and change the artifact coordinates on your project.
This approach is useful if you don’t have access to the library source code or if its usage is deprecated on your project.
2. If the library repo is public but abandoned, you can fork it, migrate the code to
androidx and release a new version with a different
groupId. This option is useful if you plan to add changes to the source code in the future.
3. If the library repo is public and not abandoned, you can clone it, migrate it to
androidx and send a pull request to the maintainer. This approach can take more time, but it is useful if you plan to continue using the library and its new versions in the future.
If the dependency you are replacing by a jetified version is a transitive dependency, then you can define Dependency substitution rules on Gradle, so the old dependency is replaced by the new dependency when resolved.
For example, suppose that
com.parse.bolts:bolts-applinks:1.4.0 uses android support, and you migrate/transform to
com.sample:bolts-applinks:1.4.0. With the following configuration, you will replace all the original artifact usages:
// Replace artifacts with android support with the jetifier version
If you need to force the upgrade of a transitive dependency, you can add a dependency constraint.
For example, suppose that
com.transitive:lib:1.0.0 as transitive, but this version uses android support. You can force to use
com.transitive:lib:2.0.0, which is migrated to
because("previous versions use android support")
You need to verify that your own code and all your dependencies (including transitives) are not support-library-dependent any more.
If you execute the following command:
./gradlew canISayByeByeJetifier -Pandroid.enableJetifier=false
and you get a
BUILD SUCCESSFUL with this message:
* No dependencies with legacy android support usages! You can say Bye Bye Jetifier. *
====================================================================BUILD SUCCESSFUL in 5s
1 actionable task: 1 executed
it means that you achieved that.
Now you can remove the
android.enableJetifier flag from your
Run your app and test it to be sure that all is working as expected.
Once you have disabled
Jetifier, you don’t want to add a new support-library-dependent library by mistake when adding/upgrading a dependency on your project. To avoid that kind of issue, you can run the
canISayByeByeJetifier task on your CI tool as part of the PR checks.
Our recommendation is to disable the Bye Bye Jetifier plugin on your local environment and run the verification task on your CI tool: on each PR and your default branches. The following article could help you to configure that:
If you enjoyed this article, you might get value out of these ones as well!
Stop generating the BuildConfig on your Android modules
Why generating the BuildConfig class is a bad idea
Firebase Remote Config: 3 lessons learned
3 important lessons learned after using Firebase Remote Config on Android