Solve The Hassle Of Installations

Users are naturally resistant to installing apps. A person may have a low data limit on their carrier's plan, or may be located in a geographic area where a strong data signal is scarce. They could be apprehensive about giving up phone permissions to an app, or nervous of how much space an app may consume on their device.

According to Tune, Android users install, on average, 1.3 apps per device, per month while there are roughly 2.8 million apps in the Google Play Store. That is a narrow window of download probability for developers and organizations alike who have invested time and money into creating an app for the masses.

Just A Taste

Picture Google's Play Store as a new local ice cream parlor. You're given numerous flavors to choose from, and you're unsure how each might taste. If you're feeling daring, you could choose an option that you think you would fancy, pay for it, and see what happens. However, you might make the wrong choice, and feel disappointed because the chosen flavor has already been purchased. Fortunately, ice cream shops normally allow customers to sample flavors before purchasing. This concept is exactly what the introduction of instant apps accomplishes - a user is given a version of the app with selected pieces of functionality. It is the hope of the app development team that if the user samples their instant app, they will ultimately navigate to the Play Store and download the full app.

Instant App Introduction

Normally if a user needs to try an app, or just needs to use one feature in it, they are required to navigate to the Google Play store to download the entire app. An Instant App gives users a selection of features from the full app for temporary use. This eliminates the hassle of searching the Play Store and installing a full app, when really the user's intention is to use a quick feature. Instant apps can be installed directly from a website via a web URL, QR code, or NFC tag. The download and install times are kept at a minimum, due to the lesser size of the instant app compared to its full-size counterpart. In the end, when the user navigates away from the instant app and terminates it, it will not display with the user's other apps. At that point in its short overall lifecycle, the instant app is removed from the phone.

Instant App Examples

Parking Meter Payments App

Imagine a parking meter app that allows users to pay for metered street parking after parking their car. Normally a user would need to navigate to the Play Store, download the full app, and use the app to pay for their meter. Instead, the parking meter could have an NFC tag, which when touched could then initiate a small download of the instant app in the background. The user is then deep-linked straight into the instant app to the payment form for the particular meter. When the user is done, they are given a prompt to install the full app. If they choose to do so, they are taken to the Play Store page for the full app. If the user terminates the instant app, it is instantly removed from the phone.

Clothing Store App

A user sees a public flyer for a local clothing store, providing a description for a product ordering service. The flyer offers a QR code for downloading the instant app. Upon doing so, the user is taken directly to a listing of their products. The user can pick the clothes they desire, and is taken through a checkout flow in the instant app to complete their order. When the order succeeds, the app displays a dialog for an option to save their account information, in the full version of their app. A link, if pressed, would take the user to the Play Store page for the full app.

Instant App Development Strategy

All apps contain one or more features. These can include actions like sending an email, displaying a location's information, or taking and modifying a photo. An instant app provides an experience containing one or a limited amount of these features. When a feature is requested from the instant app, only the code of that feature is downloaded and run. After the feature is used and the user terminates the app, that feature's code is removed by the system.

Each feature should have an entry-point Activity. This acts as the leading Activity in that feature's flow and and should set up the overarching layout. Furthermore, each feature's associated classes and dependencies need to be contained in their own module, referred to as the feature module.

Every instant app requires a base APK. This houses common dependencies that the features will use, such as images or styles. If an instant app only has one feature, then that feature's classes can be contained in the base APK's module. However to be extensible, in the case that there is more than one feature, the developer must create modules separate from the base module, for each feature. Each feature module will then be compiled into a feature APK. To summarize, if there is one feature to be developed, its code can be contained in the base module, and the base APK is the output. If there is more than one feature to be included, then each feature needs its own module, as well as the base APK having its own module. There will then be one base APK and two feature APK's.

When an instant app is first used, the base APK is downloaded. Based on what features the user then uses, one or multiple feature APK's are downloaded at runtime and utilized.

Here are several encouraged strategies to keep in mind when developing an instant app:

  • Developers are encouraged to pick several core features from the full app to include in the instant app functionality. Choosing and narrowing the most important features will ensure that the instant app APK is reasonably sized.
  • In the instant app's flow, provide a link (when it is appropriate) to direct a user to the play store to present them with the full app.
  • The Google team encourages developers to keep features in an instant app identical to those in the full app counterpart, both visually and in the functionality. The instant app is not meant to appear drastically different from the full app's experience.
  • While you can have multiple activities in a single feature, there is a 4 MB size download limit for every instant app.
  • Android Studio 3.0 is required to develop instant apps.

Creating an Instant App Project

Before we dive into the prepared instant app demo, it is important to review the steps for creating an instant app from scratch. Due to the fact that instant apps can be used on Nougat and later, it is very likely that many developers will need to integrate their instant apps into their existing full app. This requires several preparation steps, which will be provided in an upcoming blog this July. The steps below outline creating an instant app from scratch using Android Studio.

  • Launch Android Studio, and create a new project
  • In the "Create Android Project" screen, fill in your desired package information and project location, hit Next
  • In the "Target Android Devices" screen, ensure Phone and Tablet is checked, and you are running API 23. Check off the "Include Android Instant App support" box. Hit Next.
  • You should now see the "Customize Instant App Support" screen, which has the default module name as "feature". Leave this default as-is, and hit Next.
  • On the "Add an Activity to Mobile" screen, you may select your activity template. For our example, we went with the "Empty Activity".
  • The "Configure Activity" pane has a few important fields. Every instant app feature that is developed must have a unique route. This is established by having a unique URL route in the "Instant App URL Route" field. For our example, since we have two features, we have we used "/information" when we created this project, then later added our second feature and used the route "/sales". Hit Finish, and your project has been created.

Instant App "Cacti Collector" Example

Synopsis

For this example, we will be reviewing a simple demo app, Cacti Collector. This is for a cacti vendor who wishes to provide both information about the plants as well as a virtual shop for users who can view ones for purchase. This full app contains two features - one for displaying the cacti information, and the other for the cacti shop. Each feature adheres to the 4MB size limit for instant apps, and can be launched as its own standalone instant app. These two features share a base feature for a common model superclass, and a few resources.

I highly suggest downloading a copy of the complete demo source code from GitHub to follow along and reference as I run through these highlights. Only files utilizing the concept of instant apps will be discussed.

Build Configuration

This section outlines the steps necessary to run the sample full app as well as the two instant apps individually. If you chose not to download a copy of the demo, then you can skip to the next section, where we will begin reviewing the file hierarchy.

  • In Android Studio, go to "File", then "Open...", then locate and open the downloaded project directory.
  • Notice that there is only a configuration for app (our full app), and instantapp. We will want to rename instantapp to signify the configuration for one of the instant apps, and duplicate it to create the other instant app. Hit "Edit Configurations...".

  • Selecting the instantapp configuration will show you its configuration details. For the "Name" field, change "instantapp" to "instant-app-information". Verify under "Launch Options" that the URL reads "https://instantappsample.com/information", then hit "Apply". The configuration should appear like this when you are done.

  • That is the configuration for the cacti information instant app. Now for the cacti shop instant app configuration, duplicate (⌘D) this configuration.
  • In this duplicate configuration, change the "Name" field from "instant-app-information (1)" to "instant-app-shop". Under "Launch Options", update the URL from "https://instantappsample.com/information" to "https://instantappsample.com/shop". Hit "OK".
  • You should now see three configurations! Again app is for the full app, and instant-app-information & instant-app-shop are the two instant apps.

Project Contents Overview

There are five modules in total - each with a specific purpose.

  • The app module acts as the directory for the full, installed app. This module has its own manifest, classes, and resources, and can make use of components inside the feature modules. If you were integrating instant apps into an existing project, this module would be your existing app module.
  • The base module is the directory for the base feature of the instant apps. Any time an instant app module is developed, there must be one and only one base feature module. This houses its own manifest, as well as common classes and resources that the 'child' feature modules may use.
  • The featureinfo and featureshop are feature modules, each one compiled as an instant app. These features contain each of their own unique manifest, classes, and resources. They also reference common classes and resources from the base module. Their classes contain logic that tailor them towards the instant app or full app experience, depending on the situation. In this example, when launched as an instant app, the action bar in featureinfo shows an "install" action item, to provide the user with a link to the Play Store main app. When the main app is run, the activity in featureinfo is still utilized, but the conditional logic prevents the "install" action item from being displayed.
  • The instantapp module merely holds a build.gradle file, and has the instant app plugin applied, so the build configurations have a module to build off of.
Shared Classes and Resources

Picture a scaled-up codebase, with five instant apps. Those are five sets of models, used in various activities and fragments, which utilize potentially similar layouts, styles, drawables, and strings. Imagine the nightmare of making a change to a string resource's content only to realize that said resource has been copied in four of the other instant apps! This is where designing your modules with the base class in mind is key.

The programming paradigm of centralizing common logic applies here as much as it applies in other concepts. Using the base module, common resources and classes can be used amongst features. Let's view a few code blocks to see how they're used.

Shared String Example

Let's walk through some of the string resources in strings.xml in the base module.

...

HaworthiaCactoideaeRounded Point CactusAir SucculentEcheveria Succulent
...

These strings are used in both the featureinfo and featureshop modules. Let's view a block from CactiShopFragment.java in the featureinfo module.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
 Bundle savedInstanceState) {
 ...

 // Set up the RecyclerView
 RecyclerView mRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_cacti_list_rv);
 mRecyclerView.setHasFixedSize(true);
 mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

 // Set up the data. Note that data for a RecyclerView usually comes from a service or data
 // tier, but for the sake of example this is just sample information.
 List cactiInfoItems = new ArrayList<>();
 cactiInfoItems.add(
 new CactiInformationItem(com.instantappsample.cacticollector.R.drawable.cactus1,
 getString(com.instantappsample.cacticollector.R.string.cactus_1_title),
 getString(R.string.cactus_1_desc)));
 cactiInfoItems.add(
 new CactiInformationItem(com.instantappsample.cacticollector.R.drawable.cactus2,
 getString(com.instantappsample.cacticollector.R.string.cactus_2_title),
 getString(R.string.cactus_2_desc)));
 cactiInfoItems.add(
 new CactiInformationItem(com.instantappsample.cacticollector.R.drawable.cactus3,
 getString(com.instantappsample.cacticollector.R.string.cactus_3_title),
 getString(R.string.cactus_3_desc)));
 ...
The quick data List set up is for the sake of demonstration (normally this data is retrieved from a data tier).

In onCreateView(...) we are setting up the cactus information data (image drawable resource, title, and description) to be applied to our RecyclerView field. Both the base drawable and base string resources are being referenced to build each model. The featureshop module makes use of these in the same way.

Take note of the full package reference to the resources. Since we are currently in the featureinfo module, and cactus_1_title is defined in the base module's string resource file, merely specifying R.string.cactus_1_title will throw a compile time error, because the correct resource class isn't being referenced. The full directory to the resources in the base module is required: com.instantappsample.cacticollector.R.string.cactus_1_title.

Shared Model Example

Another example of a shared entity from the base module is the base model class CactiItemBase.

/**
* Base model object, which contains common fields used in cacti item models. This resides in the
* base feature module, so it will be used by both child features.
*/
public class CactiItemBase {

 private int cactiImageResId;

 private String cactiItemTitle;

 public CactiItemBase(int cactiImageResId, String cactiItemTitle) {
 this.cactiImageResId = cactiImageResId;
 this.cactiItemTitle = cactiItemTitle;
 }

 public int getCactiImageResId() {
 return cactiImageResId;
 }

 public void setCactiImageResId(int cactiImageResId) {
 this.cactiImageResId = cactiImageResId;
 }

 public String getCactiItemTitle() {
 return cactiItemTitle;
 }

 public void setCactiItemTitle(String cactiItemTitle) {
 this.cactiItemTitle = cactiItemTitle;
 }
}

This base model is used by both "plain old Java objects" in the featureinfo and featureshop modules. Let's look at the first few lines of the CactiItemInformation class from the featureinfo module.

import com.instantappsample.cacticollector.base.model.CactiItemBase;

/**
 * Model object containing a field for use in a cacti information card. Note the extension off of
 * the base model {@link CactiItemBase}, which is located in the base feature module.
 */
public class CactiInformationItem extends CactiItemBase {
 ...

Notice how the import statement points correctly to the model in the base module, so this model can successfully extend from it. This is a very simple example, but it pays well to stress inheritance in any in Android concept.

Main App

Finally, I demonstrate just how simple it is to include the feature activities within a new or existing main app. Below is the activity that is launched if Cactus Collector were to be installed.

...

public class CactiCollectorActivity extends AppCompatActivity implements View.OnClickListener {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 ...
 }

 @Override
 public void onClick(View view) {
 switch (view.getId()) {
 case R.id.activity_cacti_collector_btn_info:
 Intent infoActivityIntent = new Intent(this, CactiInformationActivity.class);
 startActivity(infoActivityIntent);
 break;
 case R.id.activity_cacti_collector_btn_shop:
 Intent shopActivityIntent = new Intent(this, CactiShopActivity.class);
 startActivity(shopActivityIntent);
 break;
 }
 }
}

As you can see, there are merely two different buttons that when individually clicked will each fire off an intent to one of the feature's activities.

Since these activities are both used in the instant app as well as main app, it is very likely that there will be some instant app-specific logic present. Fortunately, we can achieve this using the static method isInstantApp(Context) from the InstantApps class. To use the InstantApps class, we add the following dependency to the feature's Gradle file.

implementation 'com.google.android.instantapps:instantapps:1.0.0'

In the featureinfo module, in our CactiInformationFragment class, our action bar only needed to display the "install" action if the user was on said screen in the instant app. Wrapping the initialization of the menu item in the isInstantApp(...) method did the trick.

...
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
 if (BuildConfig.DEBUG) {
 Log.d(TAG, "onCreateOptionsMenu");
 }

 // Adds items to the action bar
 inflater.inflate(R.menu.action_info, menu);

 // Only show the "install" option for the instant app
 if (InstantApps.isInstantApp(getContext())) {
 inflater.inflate(com.instantappsample.cacticollector.R.menu.action_install, menu);
 }

 super.onCreateOptionsMenu(menu, inflater);
}
...

Closing

Instant apps allow a user to try a feature in an app in quick time, without the hassle of searching the Play Store and installing it. They have the ability to speak for the app in the form of a quick experience, and can be initiated by a web URL, QR code, or a quick tap on an NFC tag. It is incredibly possible to integrate instant apps into existing enterprise apps, and the pay-off is more user retention.

Sources

Interested in finding out more about CapTech? Check out our Contact Us page to connect or visit our Career page to learn more about becoming a part of a team that is developing world-class mobile apps for some of the largest institutions in the world.

CapTech is a thought leader in the Mobile and Devices spaces, and has deployed over 300 mobile releases for Fortune 500 companies. Additionally, CapTech was identified by Forrester as one of top Business to Consumer (B2C) Mobile Services Providers in their 2016 Wave.