Register now for Android Dev Summit 2019!

Configure the base module

Most app projects won’t require much effort to support Dynamic Delivery. That’s because the module that includes code and resources for your app’s base APK is the standard app module, which you get by default when you create a new app project in Android Studio. That is, the module that applies the app plugin below to its build.gradle file provides the code and resources for the base functionality of your app.

// The standard application plugin creates your app's base module.
apply plugin: 'com.android.application'

If you are concerned with reducing your app’s initial download size, it’s important to keep in mind that all code and resources included in this module are included in your app’s base APK.

In addition to providing the core functionality for your app, the base module also provides many of the build configurations and manifest entries that affect your entire app project. For example, signing for your app bundle is determined by information you provide for the base module, and versioning of all your app’s APKs are specified on the versionCode attribute in your base module’s manifest. Other important aspects of the base module are described below.

The base module manifest

The manifest for your app’s base module is similar to that of any other app module. Keep in mind, when Google Play generates your app’s base APK, it merges manifests for all modules into that of the base APK. So, if you are considering adding dynamic feature modules to your app project, there are some aspects to the base APK's manifest that you should keep in mind:

  • Because the base APK is always installed first, it should provide the main entry point for your app. That is, it should declare an activity with the following intent filter:

    <intent-filter>
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    
  • When downloading dynamic feature modules on demand, devices running Android 6.0 (API level 23) and lower require the app to restart before completing installation of the new modules. However, if you want to be able to access the downloaded module’s code and resources immediately after it’s downloaded, you should include support for the SplitCompat library in your manifest. To learn more, read Access code and resources from downloaded modules.

  • Similarly, on devices running Android 6.0 (API level 23) and lower, apps need to restart before the platform can apply new manifest entries. So, if you require certain permissions or services as soon as a dynamic feature module is downloaded, consider including them in the manifest of your base module.

  • Android App Bundles include support for uncompressed native libraries. So, if you include native libraries in your app and want to reduce disk usage, include the following in your base module's manifest:

    <application
        android:extractNativeLibs="false"
        ... >
    

The base module build configuration

For most existing app projects, you don’t need to change anything in your base module’s build configuration. However, if you are considering adding dynamic feature modules to your app project, there are some aspects to the base module’s build configuration that you should keep in mind:

  • App signing: You don’t need to include signing information in the build configuration file unless you want to build your app bundle from the command line. However, if you do include signing information, you should include it in only the base module’s build configuration file. For more information, see Configure Gradle to sign your app.
  • Code shrinking: If you want to enable code shrinking for your entire app project (including its dynamic feature modules), you must do so from the base module’s build.gradle file. That is, you can include custom ProGuard rules in a dynamic feature module, but the minifyEnabled property in dynamic feature module build configurations is ignored.
  • The splits block is ignored: When building an app bundle, Gradle ignores properties in the android.splits block. If you want to control which types of configuration APKs your app bundle supports, instead use android.bundle to disable types of configuration APKs.
  • App versioning: The base module determines the version code and version name for your entire app project. For more information, go to the section about how to Manage app updates.

Re-enable or disable types of configuration APKs

By default, when you build an app bundle, it supports generating configuration APKs for each set of language resources, screen density resources, and ABI libraries. Using the android.bundle block in your base module’s build.gradle file, as shown below, you can disable support for one or more types of configuration APKs:

android {
    // When building Android App Bundles, the splits block is ignored.
    splits {...}

    // Instead, use the bundle block to control which types of configuration APKs
    // you want your app bundle to support.
    bundle {
        language {
            // Specifies that the app bundle should not support
            // configuration APKs for language resources. These
            // resources are instead packaged with each base and
            // dynamic feature APK.
            enableSplit = false
        }
        density {
            // This property is set to true by default.
            enableSplit = true
        }
        abi {
            // This property is set to true by default.
            enableSplit = true
        }
    }
}

Manage app updates

With Android App Bundles and Dynamic Delivery, you no longer have to manage version codes for multiple APKs that you upload to Google Play. Instead, you manage only one version code in the base module of your app, as shown below:

// In your base module build.gradle file
android {
    defaultConfig {
        …
        // You specify your app’s version code only in the base module.
        versionCode 5
        versionName "1.0"
    }
}

After you upload your app bundle, Google Play uses the version code in your base module to assign the same version code to all the APKs it generates from that bundle. That is, when a device downloads and installs your app, all split APKs for that app share the same version code.

When you want to update your app with new code or resources, you must update the version code in your app’s base module, and build a new, full app bundle. When you upload that app bundle to Google Play, it generates a new set of APKs based on the version code the base module specifies. Subsequently, when users update your app, Google Play serves them updated versions of all APKs currently installed on the device. That is, all installed APKs are updated to the new version code.

Download additional configuration APKs

One exception to the update flow described above is when an installed app requires additional configuration APKs. Consider a user who changes their default system language after already downloading your app. If your app supports that language, the device requests and downloads additional configuration APKs for those language resources from Google Play. However, this type of update to your app does not change its version code, so the device downloads and installs only the configuration APKs that it requires.