Ten tips to speed up Android app building

Ten tips to speed up Android app building

The build speed of the application will directly affect the development efficiency. This article will take you through the transformation of an Android application: "Google Santa Tracker" to provide you with ten tips to help you improve the Gradle build speed of the application. After we applied all the tips, the build speed of the demo application was more than three times faster.

First, let's take a look at the engineering background of the "Google Santa Tracker" application: This application is about 60M in size, it contains 9 modules, more than 500 Java files, more than 1,700 XML files, more than 3,500 PNG image resources, uses Mutil-dex, and has no annotation processor.

Secondly, before we start the speed improvement tuning, let's understand the description of the three performance indicators:

  • Full build, that is, recompiling the debug version of the entire project;

  • Incremental code build means we modify the Java/Kotlin code of the project;

  • Incremental resource construction refers to our modification of resource files, such as adding or reducing image and string resources.

After implementing each tip, we will compare the build time of the above three scenarios as our quantitative standard. Please note that due to different project sizes and development environments, the results of developers' actual operations may differ from the results in this article.

Tip 1: Use the latest version of the Android Gradle plugin

Each update of the Android Gradle plugin will fix a large number of bugs and improve performance and other new features, so it is very necessary to keep the latest version of the Android Gradle plugin.

Starting from version 3.0, we will distribute the new Android Gradle plugin through the google() Maven repository, so you need to add google() to your repositories to get the latest plugin updates (now Android Studio will add the google() Maven repository reference by default when creating a new project).

This is the result after updating the Android Gradle plugin version from 2.x to 3.0.0-alpha1 (the demonstration here is based on version 3.0.0-alpha1. As the plugin version is updated, the performance improvement will be more obvious). We can see that the time for a full build of the application is directly reduced by 25%, the incremental build of code changes is reduced by nearly 40%, and the incremental build of resource changes is also reduced by 16%.

Tip 2: Avoid activating older versions of Multidex

This tip should be familiar to everyone - avoid activating the old version of multidex. When the number of configuration methods of your application exceeds 64K, you need to enable multidex . When you enable multidex and the minimum API level of the project is before 21, the old version of multidex will be activated, which will seriously slow down your build speed because API levels before 21 do not natively support multidex.

  • Enable multidex
    https://developer.android.google.cn/studio/build/multidex.html

If you are building via the Run/Debug button in Android Studio, you don't need to worry about this issue. The new version of Android Studio will automatically detect connected devices and emulators, and provide native multidex support if the system API level is greater than 21, while ignoring the minimum API level (minSdkVersion) setting in the project.

 
Developers who are used to building projects through the command line window need to try to avoid this problem: configure a new productFlavor, set the minimum API level of the project to 21 or above, and call assembleDevelopmentDebug in the command line to avoid this problem.

The performance improvement results are very significant (the gray line is the initial result). We reduced the full build time by another 5.5 seconds, and the incremental build time for code changes was reduced by more than 50%. The incremental build time for resource changes is the same as before.

Tip 3: Disable Multiple APK builds


When the application needs to be released and put on the shelves, we often use " Multiple APK " build, which can create different versions of the application according to ABI and pixel density, reduce the package size, etc. But this seems a bit redundant in the development stage, so we need to disable the multiple APK build feature to increase the build speed.

Disabling multi-APK builds cannot be set only in splits, because the settings here are visible to all build variants in the project . The correct way to disable multi-APK builds is to create a property to make a judgment. Here we set a property called "devBuild" and pass this value to gradle during the build process. At this time, gradle will set splits.abi.enable and splits.density.enable to false, and it will not generate multiple APKs.

In Android Studio, you can add the command line parameter: -PdevBuild in the Build, Execution and Deployment category of Preferences. Android Studio will pass this value to gradle every time you build to avoid generating multiple APKs.

As shown in the figure above, this is the effect after I disabled multiple APKs, and all indicators continue to decrease.

  • Multiple APK

    https://developer.android.google.cn/google/play/publishing/multiple-apks.html

  • Build variants

    https://developer.android.google.cn/studio/build/build-variants.html

Tip 4: Minimize the use of resource files

When your app contains a lot of localized resources or adds special resources for different pixel densities, you may want to apply this trick to improve build speed - minimize the number of resources packaged into the app during development.

By default, the build system packages all declared or used resources into the APK, but during the development phase we may only use one set. In this case, we need to use resConfigs() to specify the resources needed to build the development version, such as language version and screen pixel density.

Here we see a significant improvement, with full build time reduced by another 6 seconds and incremental build time reduced by more than 20%.

Tip 5: Disable PNG compression

Like Tip 4, this feature itself is quite helpful in the packaging and release stage - PNG compression, but disabling this feature during the development stage can improve build efficiency. By default, AAPT will compress the project's PNG resources to reduce the APK size. Depending on the number and size of the images, this process may take a long time.

If we want to avoid using PNG compression, we can do it as mentioned in Tip 3 by adding aaptOptions.cruncherEnabled = false to the devBuild properties. Passing this value to gradle during the build process will prevent it from executing the PNG compression command.

Another way to avoid compressing PNG is to convert PNG to WebP format. Compared with PNG format, WebP can reduce the size by up to 25%. At the same time, Android Studio 2.3 and above directly supports the conversion of PNG to WebP format.
 
It should be noted that API level 15 and higher can support opaque WebP format images. If it is transparent format WebP, API level 18 and higher is required.

It can be seen that the full build time has been reduced by another 9 seconds. This is also because there are more than 3,500 PNG images in the Google Santa Tracker app, which takes a lot of time to compress and calculate, so the efficiency improvement in this area is obvious, while other incremental builds just maintain the previous situation.  

I would like to specifically mention the issue of APK size. After comparing the APK sizes with and without PNG compression enabled, we found that the sizes did not change much. This suggests that the PNG images used in the project have been fully optimized before import, and PNG compression is unnecessary here.

Tip 6: Use Apply Changes

Starting with Android Studio 3.5 (currently in the Beta build channel), developers can use the Apply Changes feature to improve build performance, which allows code and resource changes to take effect directly without restarting the app, and sometimes even without restarting the current Activity. Unlike the implementation of Instant Run, Apply Changes takes full advantage of the features of the Android 8.0 and above operating systems for runtime detection, thereby dynamically redefining classes. Therefore, if you want to use Apply Changes, you need to run your project on a real device or emulator running Android 8.0 (API level 26) or above.

Tip 7: Avoid passive changes

We use a small example to illustrate this tip: we set the project version number to a number based on the current time (in fact, you probably don't do this). The result is that the version number is new every time you build, and the project manifest file will change accordingly, which ultimately slows down the build speed.
As shown in the figure, we found that the incremental build time even doubled, so try not to add too much meaningless content to the build script.
Solving this problem is not difficult. We can determine whether there is a devBuild tag in the build script. If so, we can set the version number to a fixed value.

In this example, we deliberately add some messy code to the build script to show the damage it causes. We also give an actual example of using Crashlytics. This plugin will add a unique ID as a build identifier to each build by default, which will cause unnecessary time loss. You can avoid this by adding ext.alwaysUpdateBuildId = false to the build script. Of course, you can also choose to completely turn off Crashlytics during the development phase.

Tip 8: Don’t use dynamic version identifiers

Gradle provides a very convenient dependency library version management function, which allows developers to use a plus sign "+" to indicate that they want to use the latest version of the dependency library. However, there are several risks in using dynamic versions. From a performance perspective, Gradle will check for updates to the dependency library every 24 hours. If you have many dependent libraries and all use the setting of dynamically obtaining the latest version, it will have a certain impact on the performance of the build.

Even if you don't particularly care about these performance losses, it is still risky - version updates of dependent libraries will make your build full of uncertainty. Maybe two weeks later you are building a completely different project because updates to dependent library code are invisible to developers.

Tip 9: Optimizing Gradle memory allocation

In the default build environment, we will allocate 1.5G of memory to Gradle, but this is not suitable for all projects. You need to tune this number to get the best Gradle memory allocation for your project.
At the same time, since Android Gradle plugin version 2.1, dex has been in the process by default, so if you have set the javaMaxHeapSize value before, you can choose to delete it.

Tip 10: Enable Gradle build cache

Gradle's new cache mechanism works very well, and we recommend that you try to enable it. The latest Gradle supports Kotlin projects using build cache, which can greatly improve the build speed. Gradle's build cache is not enabled by default. You can enable build cache for everyone by adding the --build-cache parameter to the command line or adding org.gradle.caching=true to the gradle.properties in the project root directory. You can learn more about Gradle build cache in this document .

  • About Gradle build cache
    https://docs.gradle.org/current/userguide/build_cache.html

Summarize

After practicing all the speed-up tips, the overall improvement results are that the full build speed is more than three times faster than before, and the incremental build of code changes is more than 12 times faster. We have created a code repository on GitHub , and you can download and practice the build speed-up tips we mentioned today. For more information on how to improve application build speed, please pay attention to our official documentation .

  • Code repository
    https://github.com/jmslau/santa-tracker-android
  • Official Documentation
    https://developer.android.google.cn/studio/build/optimize-your-build

<<:  Dropbox engineers explain why they gave up sharing code and used native languages

>>:  Try to implement React Native application on iOS and Android

Recommend

Motorola President: Lenovo will fully support Moto's future development

Beijing time, September 8, noon news, Motorola Mo...

What is Wenchang Tower?

What is Wenchang Tower? Wenchang was originally t...

How to plan and promote an operational activity well?

Without further ado, here are the answers: 1. Cla...

Apple releases new version of MacOS: can share iOS applications

Today, Apple updated many of its systems. In addi...

Li Jiaqi and Li Ziqi: Where should traffic influencers go?

Two mobile phones and two internet celebrities tr...

Which one is better, 360 IOU or Ant Borrowing?

As people born in the 1980s and 1990s have become...

Things you need to know about Android push notifications

Some time ago, the "Unified Push Service All...

Apple Terminal Case—iOS16.4 Icon Display Inconsistency During Calls

For Apple iOS 16.4 mobile users who [enable 5G] a...

How to tap into iOS channels for app promotion

Question 1: I don’t know where to tap into the iO...