Google recently released Instant Apps to developers as part of an effort to help kickoff the next big enhancement to the native app experience in Android. Instant Apps aim to help bring users into the best native app experience as quickly as possible by downloading only parts of an application when they need them. This makes it fast and easy to engage users with great mobile app experiences, even though they do not have the application installed on their devices.
Instant Apps are delivered to the user in small feature modules, each containing only the code and resources needed to accomplish a specific action. Instant Apps are triggered by URL intents, meaning that they can be started from anywhere including, search results, social media shares, messages, beacons, NFC and other applications or even other Instant Apps.
Instant Apps share a single code base with the installed apk counterparts and are also distributed via the Google Play Store through the Android Instant Apps section.
In order to get started with Instant Apps, you’ll need to get a few new tools.
It contains a few useful static methods to help check if the user is interacting with the instant or installed version of your app, as well as prompt them with a system dialog to install the full APK.
The first, and possibly most important, step is to determine what parts of your app will work best as features in an Instant App. Instant Apps are driven by actions and make themselves available to users right when they are needed. For example, a user at a new parking garage may not have the right parking meter app installed before hand, but with Instant Apps, all the user needs to do is visit a URL and the native app can take advantage of all the rich payment APIs already available, quickly and easily.
Instant Apps should focus primarily on helping users complete whatever task they set out to do with as little friction as possible, not drive full app installs.
Similarly, Instant Apps should not act as trial versions or lite versions of the full app. This may warrant reconsidering how your users currently interact with your apps. How do they come to visit the app? As well as what kind of content do they frequently share?
Consider what the new flow would be like. There could be multiple entry points into your application where none of them may ever be from the launcher. And you must also work with the possibility that the app may be evicted from the system right after the user is done interacting with it.
With Instant Apps, having a lean app is more important than ever before.
Each feature of your Instant App must be under 4MB in size.
Which doesn’t really leave a lot of room for large dependencies. This means that it’s worth reconsidering what is important to you and your users. For example, you may be able to save on feature bloat by: reconsidering what your success factors are as well as how you track them; removing unused code; optimizing resources; and properly proguarding your modules can really help slim down your application.
If you have built complex apps that support multiple user flows, you will likely have implemented deep linking. Deep linking allows anyone to create a URL that links directly into a particular screen or flow in your app. Since Instant Apps run on URLs, deep links and app links are now a requirement. One major difference with regular deep links is that custom URI schemes are not supported such as
Instead, you must now support https URLs
You may continue to use your custom scheme in your installed app if you wish, however there is a strong case to be made for switching all deep links to URLs.
Every feature in your Instant App must have at least one entry point that is defined as a deep link. This defines what Activity users will see when they click an Instant App URL, or if they navigate to the feature from a different feature in your Instant App. Here is an example of an intent filter that binds a deep link pattern to an Activity.
In this case, ItemDetailActivity will be launched when a user visits
Secondly, you will also need to associate your web domain with your Instant App’s package name. This binding, known as Android App Links, proves to Google that you own and control the web domain that you wish to associate with your app. Previously, App Links allowed installed apps to automatically associate themselves with your web domain so that when users click on your website’s URLs, they skip the disambiguation dialog and are taken directly to your app. Now, by setting up App Links for your Instant App, users without your installed app will be routed seamlessly to your Instant App. App Links are optional for installed apps since users can manually choose what apps they want to handle your deep links, however App Links are a requirement for Instant Apps to work. To set it up, you simply need to host a single JSON file on the root of your domain or subdomain at <my-domain>/.well-known/assetlinks.json
While your Instant App modules will need to have separate package names for namespacing purposes, your Instant App and installable app can share their application ID, so you only need to register that application ID in the "package_name" field. You can find out more information on setting up app links here.
This is perhaps the most difficult step in putting together an Instant App especially for existing applications. This is because the vast majority of apps today are mostly single module builds while supporting Instant Apps requires developers to split their builds into multiple modules called features. Each feature represents a part of the application that can be downloaded on demand.
The feature module’s manifest is also worth noting because since it is functionally only a part of the full app, its manifest will be merged with others when the project is assembled. So feature module manifests should contain things like Activities that are contained in the module. Each feature manifest should also contain a unique package name for the module.
For example here’s a manifest from a sample feature module.
Every project that uses feature modules must have exactly one base module and every feature module must depend on the base module.
Here’s a sample base feature module build script.
The base feature manifest would generally contain global stuff like your application tag. Here’s a sample base feature manifest.
While not mandatory, it’s recommended that your base feature manifest contain an activity tag that references an activity that implements a default-url metadata. This tells Android which activity to launch in the event that your Instant App is not opened from a deep link but somewhere like a launcher instead.
The application manifest here is the result of merging all of the other manifests that it inherits from the other feature modules. As a result its manifest is pretty sparse.
Here’s a sample of an Instant App module build script.
Now that we’ve looked at how Instant Apps are structured, it’s important to take a look at some of the problems that we ran across putting together an Instant App. Some gradle plugins that you rely on may not work. Many gradle plugins for Android projects check for modules using the com.android.application or com.android.library plugins. While the new com.android.feature plugin, works similarly to the library project, they do not have the sample package name so your favorite gradle plugins may need to be updated.
In supporting Instant Apps, it makes sense to use deep links for all of your in-app navigation and, in some cases, it’s necessary. If you are just now adding https deep links to your app (or switch away from a custom scheme) you may notice that Android pops up a disambiguation dialog when you navigate from one activity to another via deep link. The system needs the user to decide whether to handle the deep link in the web browser or your app. Obviously, you would want the user to stay in your app by default and not give them the choice of leaving to the web browser. This is solved by implementing App Links as described above. But if during development you don’t have your web server setup correctly yet, you can implement this workaround to avoid the disambiguation dialog:
You can get your app’s package name from a Context and force the VIEW Intent to only consider activities under your package name.
To test your Instant App locally during development, you can obviously just use Android Studio to run your Instant App. But here’s how it works behind the scenes.
Let’s assume your instant-app module is name instantapp. First run the gradle task gradle :instantapp:assembleDebug This will produce a zip archive artifact in your builds folder. Next unzip this archive and you will find several APKs, one for each feature module. Finally, run this adb command to simultaneously install all of these APKs. adb install-multiple -r -t --ephemeral base.apk feature1.apk feature2.apk where base.apk, feature1.apk, and feature2.apk are your feature APKs. Warning: we have noticed that this adb command may fail intermittently.
In order to deploy your Instant App to the Google Play Store, you simply need to run the same gradle task as above but using the release variant: gradle :instantapp:assembleRelease And then upload the zip archive to the Play Store console. You do not need to unzip the archive. But before Google will accept your Instant App, you will need to ensure some things are setup correctly.
Instant Apps are essentially a bundle of APKs, one for each feature module. So you will need to sign each of these APKs the same way you sign your installable APK. This means you will need to add a signing config to each feature module’s build.gradle (including the base feature module).
In order to deploy your Instant App, you will also need to verify the intent filters in your manifests are formatted a certain way. For an example of a working setup, see the <activity> declaration for the ItemDetailActivity above. Here are the key points:
Make sure you include android:autoVerify="true". This attribute tells Android to automatically verify your App Links. Since Instant Apps works off of App Links, this attribute is required. Make sure you use multiple <data> tags with only one attribute each. So instead of
You should use
Notice above that we added a scheme declaration for http. Although Instant Apps only supports https URLs, your intent filters are required to handle both http and https.
We built a sample app, named Bumblebee, just to get a feel for what’s possible with Instant Apps. Bumblebee is a fictitious store with a simple catalog and shareable shopping carts. It uses Firebase for catalog data, user data, and resource hosting. We also architected the app using Google’s new Architecture Components, which we found to be tremendously helpful and easy to use.
Bumblebee is an Instant App with three feature modules, each containing their own screen. The root entry point is a Browse feature that shows off a grid of products available for purchase (actually just photos of items we found lying around the office). Tapping on one takes you to the Item Detail feature that lists a price and full description. From here, you can choose to add the item to your shopping cart. Once you have a cart, you can view it using the Shopping Cart feature and easily share an Instant App link to your cart. Remember, Instant App links are really just urls. Anyone who you share the link with can immediately access your cart directly as an Instant App without any need to download the catalog features.
You can invoke URLs as intents via adb commands:
And you can check out how it’s built on our github repo here: https://github.com/willowtreeapps/android-instant-apps-demo/