Say bye-bye to Android Jetifier

6 steps to stop using Jetifier and reduce your build speed

Maxi Rosson
Dec 9, 2020 · 6 min read

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.

Having 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 Jetifier.

Step 1

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:

Step 2

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:

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?

The 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

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("com.dipien:bye-bye-jetifier:X.Y.Z")
}
}

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.

Example output:

========================================
Project: app
========================================

Scanning com.github.bumptech.glide:glide:3.8.0
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.github.bumptech.glide:glide:3.8.0
Issues found:
* 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:
* android.arch.core:common:1.1.1
* android.arch.lifecycle:common:1.1.0


> Task :canISayByeByeJetifier FAILED

Step 3

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 androidx databinding.

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 android.enableJetifier enabled

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.

Tip 1

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
allprojects {
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("com.parse.bolts:bolts-applinks:1.4.0")).using(module("com.sample:bolts-applinks:1.4.0"))
}
}
}

Tip 2

If you need to force the upgrade of a transitive dependency, you can add a dependency constraint.

For example, suppose that com.sample:lib:1.0.0 defines 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 androidx

api("com.sample:lib:1.0.0") // 
constraints {
implementation("com.transitive:lib:2.0.0") {
because("previous versions use android support")
}
}

Step 4

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 theandroid.enableJetifier flag from your gradle.properties.

Step 5

Run your app and test it to be sure that all is working as expected.

Step 6

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 thecanISayByeByeJetifier 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:

Follow us for more productivity tools & ideas for Android, Kotlin & Gradle projects.

Dipien

Boost your Productivity

Maxi Rosson

Written by

Developer Productivity Engineer | Android | Productivity tools & ideas for Android, Kotlin & Gradle developers on medium.dipien.com

Dipien

Dipien

Productivity tools & ideas for Android, Kotlin & Gradle developers.

Maxi Rosson

Written by

Developer Productivity Engineer | Android | Productivity tools & ideas for Android, Kotlin & Gradle developers on medium.dipien.com

Dipien

Dipien

Productivity tools & ideas for Android, Kotlin & Gradle developers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store