Android Instant Apps: Best practices for managing download size

Posted by Maru Ahues Bouza, Developer Relations Partner, Google Play
Android Instant Apps provides rich, native experiences at the tap of a web link. People can experience your app without upfront installation, enabling a higher level and quality of engagement.
However, to provide comparable latency of loading a mobile webpage, an instant app needs to be lean and well structured, so it can be downloaded and run quickly in response to a URL tap. In light of that, we encourage that the binary loaded in response any entry-point URL is as small as possible, with a maximum of 4MB. The smaller the binaries, the faster the instant app will load and the smoother the user experience.
This document will propose best practices for managing the application structure and binary size to enable a smooth instant app experience. These practices will also benefit your installable app.

Refactoring your codebase

The biggest binary size benefit comes from refactoring your app into multiple feature modules. Even if your current size and feature set don’t require multiple features, we recommend designing for it, so you can quickly add more features in the future without affecting the binary size of existing features. We also highly recommend having a unified modular codebase to produce both installable and instant application binaries, as this will reduce the burden of maintaining separate projects and code and provide a cleaner project structure across both. Based on the experience of our early access partners, we believe this will have the largest impact to the binary size at download. However, it also requires the most investment.
To get to that end, you can start with a single (base) module and then refactor code by moving relevant portions to feature module(s). Note that you do not need to worry about the binary size while developing your instant app, as the size limit does not apply for locally built binaries. You can also publish your binary through the Play Developers Console to the Development track (special track for quick deployment of your instant app during development), where the size limit is 10MB. [1, 2] The 4MB restriction is applied once your binary graduate out of the Development track.
Each feature module can have one (or more) entry points – activities – that correspond to a given URL. When splitting a single code base into multiple modules, you will have different entry points for different features, and the platform will load the relevant feature as needed. Remember, the total binary to be downloaded for any given entry point should be under 4MB, so the combined size of any feature module and the base module must be below 4MB.

It is advised to define the feature–activity–entry point mappings first, and then structure the refactoring effort towards reducing the binary size for each entrypoint..
Also consider how your libraries are included. If a specific feature module requires certain libraries they should be included in the feature module only, instead of being added in the base APK. This will reduce the size of the base module. For example, let’s say you have an application that depends on libraries X, Y, and Z. Initially, you may pack all the libraries in the base module by placing all the dependencies in the base gradle.build file. But if only the code in the feature module requires library Z, it makes sense to move that dependency from the base module to the feature module.This works as long as no other feature modules depend on the same library. If multiple feature modules use the same library it definitely makes sense to keep it in the base module.

Lint checks

Many apps tend to acquire a lot of resources, and over a period of time, some of them are no longer used. Android Studio has useful built in lint check for unused resources. Press Alt+Ctrl+Shift+I (Cmd+Alt+Shift+I on Mac OS), type “unused resources” and start “Unused resources Android|Lint|Performance” inspection. It helps to reduce the size of the installable APK as well.

String resources

Similar to resources, pay attention to strings, not all of them may be in use, and typically the application size can be reduced significantly by removing unused string resources. If application supports multiple languages, you may want to reduce the number of localized resources, as it typically removes large chunks of the resources assets. This is especially important if the app supports only a few languages but uses AppCompat library, which includes messages in multiple languages. Use resConfig to select specific resources configurations only. Hint: typically you can use “auto” to restrict configurations pulled from third-party libraries to match the set of configurations defined in your project.

Switch to WebP

Significant reduction of the drawable resources size may be achieved by switching to WebP images instead of PNGs. Android Instant Apps supports all features of the WebP format (transparency, lossless, etc.) so there will be no loss in functionality. Keep in mind that application launcher icons must use PNG format, but it should not be a problem since projects normally keep those in mipmap- directories. If a backward compatible solution is required, you need to include the original PNG images in the APK module and it will override WebP resources automatically (main source set overrides all resources from AAR/feature module). [4]

Of course, going with vector drawables may let you save even more of the precious space, but using vector drawables will require a code change while the above mentioned trick with WebP images for the instant app and PNG images for the installable APK requires no code modifications.

Download assets at runtime

Finally, remember that technically there is no need to pack all the resources in the instant app APKs, as the application can download additional assets at run time. This approach also enables the app to download the required assets only. These modifications may require significant changes to the code base, but will also help you to reduce the size of the installable APK.
If shrinking resources does not bring your app feature modules size under the limit, it is time to look for the ways to reduce the code size.

Review native libraries

Some third-party libraries may include native code, which may not be used in the instant app at all. So the first step is to review the native libraries packaged within the APK and make sure the instant app has only those that are actually used. Remember to look into the compiled APK using APK Analyzer (Build -> APK Analyzer…) [5]

Review external libraries

Next review the list of all external libraries linked with the app’s code. You may find some unexpected surprises courtesy of transitive dependencies. Transitive dependencies occur when the library your project relies upon depends on another library, which in turn may depend on yet another library. Sometimes those transitive dependencies may contain unexpected surprises such as libraries you do not need at all (i.e. a JSON processing library you never use in your code.) Please see “Excluding transitive dependencies” section in the Gradle User Guide for further details.
Android Studio has several useful tools for analyzing the external dependencies for the project. It always helps to start with the Project view:

The “Project” view shows a section called “External libraries”, where you can see all the libraries used by the project including any transitive dependencies:

In order to further reduce the base feature size you may need to pay attention to the code dependencies and external libraries. Check the “Project” view and look for unused libraries that might be transitive dependencies the project does not need. Also look for libraries that provide the same functionality (e.g. multiple libraries for image loading/caching). [4]
You can also compare different builds with APK Analyzer tool, and it works with instant APKs, too.

Finally, review the list of transitive dependencies and exclude the ones you do not need. Use the following command to review the dependencies graph: gradle -q :MODULE:dependencies --configuration compile. Further details can be found in the Gradle documentation.

Other tips

Android Studio 3.0 includes the App Links Assistant tool, which can help to generate the necessary intent filters, and help in splitting the project into several modules. [3]

Once you got the instant app bundles under the size limit, it is the time to make sure the building process is up to date. Check that the application package and instant app APKs are signed using the “APK Signature Scheme v2“. If you sign the APKs using the latest version of the SDK tools, everything should be done automatically. However, if you manually sign the build artifacts you need to avoid using jarsigner and switch to apksigner instead.
And a few useful tips for adapting the app’s code to the instant runtime environment. Keep in mind that having a small branches of code for instant/installable applications, based on the InstantApps.isInstantApp(…), should be fine and typically does not make the source code unreadable (unless you abuse it, of course). Also, when using share intents make sure the code does not explicitly enumerate applications installed on the device, instant app security model does not allow that. Simply use regular Intent.createChooser() to present the list of all possible actions to the user.
The level of effort of developing an instant app for an existing Android application varies across developers and is heavily dependent on how your application is organized today. For some, it will be easy as your project is already organized as multiple modules. However, for some, the focus will be on reducing the code and resource assets size, and we have introduced tools and Android platform features above to help you with that.

Hear from other developers using Android Instant Apps

Finally, check out these great posts by developers that have already built an instant app:

Visit the Android Developers website to get started with Android Instant Apps and check out more instant apps success stories from other developers.


Android Developers Blog