Introduction to Android App Bundle

In this blog post, we will understand what is Android App Bundle, what benefits it has brought to the table, what is split APK’s and why this is regarded as the best thing to have happened in Android!

What is Android App Bundle?

Android App Bundle(AAB) is a new format similar to Android Application Package(APK) that includes all your app compiled code and its resources.

What are the advantages of using Android App Bundle?

Multiple Apks: A thing of Past – Currently, if our app is targetting different resolution devices, we need to build, sign and manage multiple APK’s for each type of resolution but with use of Android App Bundle, we don’t need to worry about all these conditions. Android App Bundle takes the responsibility of creating different resolution APK’s.

Dynamic & Optimized Apk’s – Google Play has introduced a new App Serving Model called as Dynamic Delivery which makes use of AppBundle to create APK’s which are specific to the end-user.

For example: If your app is targetting different languages and have different size drawable but the end-user only needs English Strings and only XX-HDPI resources, the APK available for download will only have English Strings and XX-HDPI resources thus resulting in an optimized & reduced size APK.

This reduced size APK is a result of Dynamic Delivery with split APK’s. We will look into Split APK’s later in the blog post.

Dynamic Modules: With the introduction of Android App Bundle, we can create Dynamic Modules in our project. These Dynamic modules can contain resources or features which are not required when the user first installs the Application from the play store. Using the Play Core Library, the app can request to download any of these modules as dynamic feature Apks which are installed on top of the base Apk already installed.

Split Apk’s

Split Apk’s are very similar to the regular APK as they consist of compiled DEX bytecode, resources, and Android manifest file. The major advantage of Split APK’s over the conventional APK is that it is able to break the large APK into smaller, disjoint packages that can be installed on a user’s device as one Single APK.

Let’s think of a scenario, where we have an Application in which the base module has a set of Holiday destination shown to the user in a listview. The details of the destination rest inside another module let’s say module. If the user wants to view this information, it needs to download this module with the help of Dynamic Delivery from Play Store under the hood.

An Important point to note here is that device running Android 4.4 and lower don’t support Split APK’s. Google Play instead serves those devices a single APK, called Multi APK that is optimized for that device configuration.

Now, let’s have a look at a high-level delivery structure, how it will look like when the user downloads this app from the play store:

Base APK: This APK contains all the code and resources that are required to run the basic functionality of the application. The manifest file contains the declaration of all the app’s services, content providers among others.

Configuration APK: Each APK contains libraries and resources for the specific screen resolution, language, architecture, etc. When a request comes to download the Application, only the end-user mobile-specific configuration APK is downloaded and installed on the device hence resulting in a more optimized APK.

Dynamic Feature APK: This APK contains the code and the resources which are not required during the first installation. These are the add-on functionality which is applied on top of the base APK.

Creating Dynamic Module in the project

Step 1

  • Go To file -> New -> new module. You will see a new Module Dialog, select Dynamic Feature Module and click Next
  • Give your module a name(Project Specific) and click Next
Give Module a Name
  1. Give a title to the module which will be visible for the users when they download this module
  2. Enable the checkbox “Enable on-demand”, if you want this module to be available for on-demand download for the user through the dynamic delivery from the play store.
  3. Enable the checkbox “Fusing”, if we want this module to be available to devices running Android 4.4 and lower and thus making it available for multi APK’s as well.
  4. Click Finish
  5. Wait for the syncing of the project to complete.

Step 2

android {
    compileSdkVersion 28
    defaultConfig {
      ......
      .......
    }
    buildTypes {
        release {
          .........
        }
    }
    // Add this block and enable/disable the parameters as follows
    bundle {
        language {
            enableSplit = true
        }
        density {
            enableSplit = true
        }
        abi {
            enableSplit = true
        }
    }
//Block Ends
}

Add the bundle tag inside the app’s build Gradle file

language {
enableSplit = true
}

Different Apk’s are generated, depending on the number of languages supported by the APK.

density {
enableSplit = true
}

Different Apk’s are generated, depending on the screen densities.

abi {
enableSplit = true
}

Different APk’s are generated, depending on the different CPU architecture.

You can set the value to false if you do not want different APK’s to be generated for a particular parameter.

Step 3

Modifying the feature module’s manifest file when you have declared an activity in it.

<manifest .... >
 //Add this Block  
 <dist:module
            dist:onDemand="true"
            dist:instant="false"
            dist:title="@string/title_module">
        <dist:fusing dist:include="true"/>
    </dist:module>
  // Block Ends 
 <application>
        <activity android:name=".TripDetailActivity">
          .............
        </activity>
    </application>

</manifest>
  • <dist: module>: It is a new XML element that determines how the module is packaged and distributed as APKs
  • <dist:onDemand>: Its value can be true/false. It determines whether the module will be available as part of dynamic delivery or not
  • <dist: title>: Specifies the titles which the user will see when downloading the module
  • <dist: fusing dist: include>: Its value can be true/false. It Determines whether the module will be available in Multi-APKs which will be available below API level 21

Note: In Case your module has not defined any code i.e the feature module does not generate any DEX code then you must add the following code in the application tag of your feature module manifest file:

 
 <application
            android:hasCode="true"
            tools:replace="android:hasCode">
    .........
    </application>

Step 4

Modify the build.gradle of the Feature Module by adding the following line:

apply plugin: 'com.android.dynamic-feature'

Let’s have a look at the complete structure:

apply plugin: 'com.android.dynamic-feature'// Added this plugin
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 28
    defaultConfig {
       .....
    }
}

dependencies {
   ......
}
repositories {
    mavenCentral()
}

Step 5

Cross-check whether the App Build Gradle file has the following dynamic features added in it:

 
dynamicFeatures = [":module"]

The complete file with our changes looks like this:

apply plugin: 'com.android.application'

........

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "sarabjit.blog.appbundlesample"
        minSdkVersion 19
        targetSdkVersion 28
       ...........
    }
    buildTypes {
        release {
                ........
        }
    }
    bundle {
// The change we made for split Apk's earlier in the blog post
        language {
            enableSplit = true
        }
        density {
            enableSplit = true
        }
        abi {
            enableSplit = true
        }
    }
     //This statement should be present[":moduleName"]
    dynamicFeatures = [":module"]
}

dependencies {
.........
}

Step 6

Go to Feature Module build Gradle file and check if the app module is added as a dependency:

 implementation project(':app')

The complete file with our changes looks like this:

apply plugin: 'com.android.dynamic-feature' // Plugin we added earlier //in the blog post
....

android {
    compileSdkVersion 28
    defaultConfig {
     .....
    }
}

dependencies {
  ......
    implementation project(':app') // This must be present
  .....
}
repositories {
    mavenCentral()
}

Few Important Points to Remember:

  • All the Feature Modules are signed using the Base Module signing configuration
  • Gradle uses the App Version Information( version name & version number) of the base module.
  • The minify enable property is driven by the base module.

In the next blog post, we will look at the implementation of the Bundle tool with an example. Until then stay tuned…