Every time you release an Android app, you’ll have at least a rough idea of what you want this app to achieve.
These goals could be very specific, such as generating a certain amount of ad revenue in the first quarter, or they could be more general, such as getting a high rating on Google Play.
Whatever else is on your wish-list, getting your app in front of as many users as possible is always going to feature somewhere on that list—and Android Instant Apps is a new feature that can help you do just that.
Instant Apps provide you with an entirely new way of reaching users who don’t currently have your app installed on their device, by making your app discoverable and accessible from any location that supports URLs, including emails, Google search results, posts on social media platforms, YouTube comments, and forums.
Essentially, Instant Apps allow you to separate each of your app’s features into a stand-alone module. Users can then load any of these instant app modules on-demand by tapping a URL that you’ve mapped to this specific module, and without having to install your app at any point.
In this three-part series, I’ll be showing you how to add Instant App support to your Android projects. By the end of this series, you’ll have created an application that consists of two separate Instant App feature modules, which you can launch and test on any compatible Android device.
What We’re Going to Cover
In this first post, I'll focus on what Instant Apps are, how they work, and why you should care about them. To give you some first-hand experience of Instant Apps, we'll use Android Studio’s project creation wizard to generate an app that’s pre-configured with Instant App support, so you’ll be able to see all the different Instant App components, rather than simply reading about them.
While creating an app that’s pre-configured with Instant App support is the quickest and easiest way to use this feature, in reality you’re far more likely to add Instant App support to an existing project—so in part two I’ll show you how to do exactly that. I’ll supply an app that you can download from GitHub, and then take you through the step-by-step process of reconfiguring this project to support Instant Apps.
The final piece of the puzzle is creating a multi-featured Instant App, so in part three I’ll show you how to add a second feature module to your application, and how to use Android App Links to map this module to a different URL.
What Are Instant Apps?
One of the best ways to describe Instant Apps is to look at an example of when you might use them.
Imagine a friend has sent you a link to a cat video that they promise you’re going to love, but when you tap the link it becomes clear that you need to download an app before you can watch this particular video.
Regardless of whether you end up downloading the app, or ignore the link and risk missing out on the best cat video the Internet has to offer, this is a bad user experience—and it’s a scenario that many Android users are familiar with.
Most of us have had the experience of installing an app just to complete a one-off task. For example, you might download an app just to view an email attachment someone has sent you, to complete a purchase on a specific website, or to track a package that’s currently winging its way to your address.
Now let’s imagine our cat video scenario again, but this time the application’s developer has placed all the code and resources required to play video content inside its own instant app feature module, and mapped this module to the www.example.com/video URL. This time, when you tap www.example.com/video/cat-video, Google Play recognizes that this URL is associated with an instant app module and retrieves all the code and resources that you need to play this video. The end result? You can enjoy 20 seconds of a cat playing in a box without having to install anything, which is a much better user experience.
Why Should I Start Using the Instant App Feature?
As you’ll see in the next post in this series, adding Instant App support to an existing project can be a daunting process, often requiring you to completely change the way your application is structured.
Since restructuring a project isn’t a decision you should ever take lightly, in this section I’m going to help you decide whether all that time and effort is really worth it, by covering all the major benefits of adding Instant App support to your projects:
- It removes a barrier between your app and new users. Installing an application via Google Play isn’t a particularly difficult or time-consuming process, but it’s still the biggest barrier between your app and potential new users. No matter how much time you spend crafting a compelling Google Play page that’ll have the majority of users scrambling for that Install button, some people will always drop out at install time.
- It helps you reach new users. While you’ve always been able to promote your app on various locations around the web, such as your own website, blog or social media, connecting with new users has previously relied on them visiting your app’s Google Play page at some point (with the rare exception of users who prefer to sideload their apps). Instant apps remove this reliance on your app’s Google Play page, by making your application directly accessible from any location that supports URLs, giving you almost unlimited opportunities to connect with new users.
- It ensures that shared content is the best possible advert for your app. A user sharing your app’s content is one of the most effective ways of reaching a new audience, so you’ll want to make a good first impression! Previously, it’s been difficult to provide a consistent experience for users who don’t have your app installed on their device, but instant apps allow you to guarantee a seamless, native experience for everyone.
- Helps users access your app, even in the face of Internet restrictions. While Internet coverage is improving all the time, you may still occasionally struggle to find a fast and reliable network, or perhaps you’re approaching your monthly data allowance and are worried about incurring additional charges. When you’re struggling with a slow or inconsistent Internet connection, downloading an entire app can be a time-consuming and frustrating process, and when you’re in danger of going over your data allowance, downloading a new app may be enough to incur additional charges. All instant app modules must be 4MB or less, so even if downloading an entire app is out of the question, then accessing an instant app module may still be a viable option.
- Increase the appeal of location and time-sensitive apps. While apps that are designed for a specific location or event aren’t a new concept, ask yourself: how likely am I to install an app that I know I’ll only be able to use for a limited period of time, or in a certain location? Instant apps can increase the appeal of time and location-sensitive apps, by allowing the user to access all of your app’s most important functionality at the tap of a URL.
Restrictions and Limitations
Before we start our instant app journey, it’s worth noting that there are currently a few things that instant apps cannot do:
- Access device identifiers like IMEI and MAC addresses.
- Use background services.
- Perform background notifications.
- Access the device’s external storage.
- Access the list of apps that are installed on the user’s device—unless those applications have specifically made themselves discoverable to instant apps.
In addition, your application must:
- Be available to download for free from the Google Play store.
- Use the new permissions model introduced in Android 6.0 (API level 23). Since the user doesn’t install an instant app, there’s no opportunity to request permissions up front. If your instant app feature module(s) require access to sensitive device capabilities or user information, then you’ll need to request these permissions at runtime.
- Support App Links. This is the mechanism that you’ll use to map each of your instant app modules to a specific URL. I’ll cover App Links in detail in the next post.
Finally, if your app is part of the Designed for Families program, then you cannot offer it as an instant app.
Setting Up Your Development Environment
Before you can create your first project with instant app support, you’ll need to have the following or higher installed:
- Android Studio 3.0 Preview
- Android SDK 6.0
- Android SDK Build Tools 26.x
- Android SDK Tools 25.x
- Android SDK Platform Tools 25.x
You should also make sure you have the latest versions of the Android Support Library and Android Repository, so open Android Studio’s SDK Manager and install any available updates.
Once you’ve installed all of the above, you’ll be able to download the Instant Apps Development SDK:
- Open the SDK Manager, and select the SDK Tools tab.
- Select Instant Apps Development SDK.
- Click Apply.
Currently, you can only test instant apps on a Nexus 5X, Nexus 6P, Pixel, Pixel XL, or a Galaxy S7 that’s running Android 6.0 or higher. However, if you don’t own any of these devices then you can create an Android Virtual Device (AVD) that emulates one of these devices, with a few conditions: the AVD must use an x86 image, and it must include the Google APIs.
Since I don’t own any of these devices, I’m going to create an AVD that emulates a Pixel:
- Launch the AVD Manager.
- Click the Create virtual device... button.
- Select Pixel, and then click Next.
- Select the x86 Images tab.
- Select a system image that’s running Android 6.0 and includes the Google APIs, for example Marshmallow / 23 / x86 / Android 6.0 (Google APIs).
- Click Next.
- Give your AVD a name, and click Finish.
- Launch your AVD.
Finally, you’ll need to sign in to a Google account on your AVD:
- Switch to your AVD, and open the device’s launcher.
- Select the Google app.
- Enter a Gmail address and password. This can either be your real-life account, or an account you’ve created solely for the purposes of testing your Android projects.
Creating Your First Instant App
In Android Studio 3.0 Preview 1 and higher, creating a project that has built-in Instant App support is as easy as selecting a checkbox, so rather than just describing Instant App features, we’re going to create an Instant App project and then spend the rest of this article getting some first-hand experience with its various components.
Just be aware that this project doesn’t feature any App Links, so you won’t be able to test its Instant App components on your AVD (this is something we’ll be exploring in detail in part two).
To create your project:
- Launch the project creation wizard, either by selecting File > New > New project… from the Android Studio toolbar, or by clicking Start a new Android Studio project from Android Studio’s Welcome screen.
- Give your project a name, and click Next.
- Set the Minimum SDK to Android 6.0 (Marshmallow).
- Select the Include Android Instant app support checkbox, and click Next.
- To help keep things simple, accept the default module name (feature) and then click Next.
- Select Basic Activity and then click Next.
- On the next screen, accept all the default values, and then click Finish.
Immediately, we can see that this project is structured very differently from your typical Android project, and consists of the following modules:
- App. The installable app module, also known as an APK module.
- Base. The base feature module.
- Feature. Although this particular project only has one, an application can consist of multiple feature modules.
- Instantapp. The instant app module.
With the exception of the feature module, any project that supports instant apps must have all of the above modules, so let’s explore each of these modules in detail.
1. Application Module
The concept of an application module may be nothing new, but when your project supports instant apps, the application module’s Manifest looks much emptier than you’re probably used to:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jessicathornsby.myapplication.app" />
There’s a reason why this file is so empty: when you build your project, the contents of all the other Manifest files located throughout your base feature and feature modules are merged with this file—so it’s not going to stay this empty forever!
If you open this module’s build.gradle file, then you’ll notice two new elements:
dependencies { implementation project(':feature') implementation project(':base') }
Here, we’re declaring that our application module has a dependency on the feature
module and base
module.
When you add Instant App support to a project, you separate related code and resources into feature modules that can function independently of the installable application. However, these modules are still parts of your installable app, rather than separate entities, which is why our application module is declaring the feature and base modules as dependencies.
2. Base Feature Module
Every instant app project must include a single base feature module, which contains the code and resources that are used across all your application’s modules. For example, if you open our project’s base/res/mipmap folder, then you’ll see all of the application’s launcher icons, which are clearly going to be used across multiple modules.
Since it contains common code and resources, all of your project’s feature modules depend on this single base feature module.
Continuing this theme, the base feature module contains the Manifest entries that are used across your entire project. For example, your project’s base/src/main/AndroidManifest.xml file contains the settings for your application’s icon, theme, and label:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jessicathornsby.myapplication"><application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" /></manifest>
The other notable element is the base module’s build.gradle file, which contains a few new attributes:
//All base feature and “regular” feature modules use the com.android.feature plugin, rather than the com.android.application plugin// apply plugin: 'com.android.feature' android { compileSdkVersion 26 buildToolsVersion "26.0.0" //Specify that this is the project’s one and only base feature, using the ‘baseFeature true’ expression// baseFeature true … … … dependencies { //Use ‘application project’ to add a dependency from the base feature module, to your project’s installable ‘app’ module// application project(':app') //Use ‘feature project’ to reference our project’s feature module, aptly named ‘feature’// feature project(':feature')
You’ll also notice that this particular build.gradle file is missing an applicationID
attribute, and (spoiler alert) you’ll find exactly the same thing when we come to inspect our feature module’s build.gradle file. Our project’s applicationID
is declared in the application module’s build.gradle file only.
The application project(
:
app)
line in our base module’s build.gradle file (see above) ensures that the project’s single applicationID
attribute is propagated across all of our build.gradle files, which is why this attribute is missing from the rest of our project.
3. Feature Module
When you eventually come to add Instant App support to an existing project, your biggest task will be extracting each of your application’s features into its own feature module, as each feature module contains the code and resources that are required to deliver this feature only.
If you open our project’s feature module, then you’ll see that it contains the MainActivity
class, plus activity_main and content_main resource files—essentially all the components that are included in the Basic Activity template.
A single feature module can consist of multiple Activities, but each module must have at least one Activity that’s designated as this module’s entry-point Activity.
Each entry-point Activity is mapped to a specific URL, so that when the user taps this URL it loads the associated Activity and the user has access to this particular feature module.
You designate a module’s entry-point Activity via that module’s manifest. Essentially, you need to open this file and add the following to the Activity that you want to use as your entry-point:
- An intent filter, with the
CATEGORY_LAUNCHER
andACTION_MAIN
intents. - A
<data>
element containing all the information about the URL that you want to map to this entry-point Activity. - The
android:autoVerify
attribute. This tells the system to check that your app has permission to act as the default handler for this particular URL. This is an important security mechanism that helps to protect website owners from malicious apps that might try to hijack their URLs.
If you open our feature module’s manifest file, then you’ll see that all of this code has already been added to our MainActivity
declaration:
<activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"><intent-filter android:order="1"><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.BROWSABLE" /><category android:name="android.intent.category.DEFAULT" /><data android:host="jessicathornsby.com" android:path="www.example.com/MainActivity" android:scheme="https" /></intent-filter><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter android:autoVerify="true">
The final file we’re going to look at in this module is the build.gradle file, which contains a few lines of noteworthy code:
//Again, we’re using com.android.feature plugin, rather than com.android.application// apply plugin: 'com.android.feature' android { //As previously mentioned, this section is missing an ‘applicationID’ attribute// … … … dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) //All feature modules have a dependency on the base feature module, which we’re declaring here// implementation project(':base') testImplementation 'junit:junit:4.12'
Since all feature modules depend on the base feature module, the first time the user requests any feature from your application, they’ll receive the base feature module plus the feature module they’re actually trying to access.
Note that although this particular project consists of a base feature module and a feature module, if your app only has one feature that you want to make available as an Instant App, then it’s possible to create a project that consists of a base feature module only. We'll be looking at both "types" of Instant App project throughout this series.
4. Instant App Module
The Instant App module has a simple purpose: it acts as a container that takes all of your feature modules and turns them into Instant App APKs.
If you open this project’s Instant App module, then you’ll see that it’s pretty much empty apart from a build.gradle file, which simply declares your base feature module and your feature module as dependencies:
apply plugin: 'com.android.instantapp' dependencies { implementation project(':feature') implementation project(':base') }
Testing Your App
Since this project doesn’t contain any App Links, we won’t be able to test its instant app components, but we can still run this project as an installable app. This might not seem particularly exciting, but bearing in mind that the bulk of our project’s code and resources are located in the instant app feature module, it’s important to test how our project functions as an installable application.
Launch the AVD we created earlier or connect a compatible physical Android smartphone or tablet to your development machine, and then select Run > Run… > app from the Android Studio toolbar.
Despite the fact that all of our MainActivity
code is located in the feature module, once our app loads you’ll see the MainActivity
’s floating action button (FAB) and Hello World message. What we're seeing here is our application module taking code and resources that are located in separate Instant App feature and base feature modules, and combining them into an installable app.
Conclusion
In this tutorial we took a high-level look at how Instant Apps work, and explored the various reasons why you might want to add Instant App support to your Android projects.
In an ideal world, your decision to start exploring Instant Apps would perfectly coincide with the start of a new Android project, but unfortunately, being a developer is rarely this convenient! It’s far more likely that you’ll have to reconfigure an existing project to support Instant Apps, which isn’t quite as straightforward as selecting a checkbox in Android Studio’s project creation wizard!
In the next post, we'll take an in-depth look at how to add instant app support to an existing project. I’ll also show you how to implement App Links, so by the end of the next post you’ll have created a fully-functioning Instant App that you can launch and test on any compatible AVD or Android device.
Stay tuned! And in the meantime, check out some of our other posts on Android app development.
- Android SDKHow to Use Android O's Autofill Framework
- Android SDKGoogle I/O 2017 Aftermath: Building Lifecycle-Aware Components
- Android SDKAdding Physics-Based Animations to Android Apps