将即时应用迁移为支持 Android App Bundle

如果您仍将已弃用的 Feature Android Gradle 插件 (com.android.feature) 用于 Android Instant App 模块,则需要迁移到使用基本应用插件 (com.android.application) 和动态功能插件 (com.android.dynamic-feature)。

在 Android Gradle 插件 3.3.0 及更高版本中,基本应用插件包含对即时体验的支持。也就是说,如果基本应用模块满足即时体验的要求,您会自动获得此优势。然后,您可以使用动态功能插件,将用户可以按需下载的其他功能作为即时体验包含在内。此设置使得从单个项目支持已安装和即时应用体验变得更容易,并让您能够从使用 Android App Bundle 发布中受益。

下表更好地描述了您将迁移到的插件

模块说明 旧插件 当前插件
包含已安装或即时应用体验的基本代码、资源和功能的模块。 com.android.feature (含 baseFeature = true) com.android.application

注意:此模块包含将您的应用构建和打包为 Android App Bundle 或 APK 所需的所有清单和签名信息。

用户可以按需下载的其他模块化功能 com.android.feature com.android.dynamic-feature (在模块的清单中包含 dist:instant="true"dist:onDemand="false")
仅适用于应用的已安装版本的代码和资源。 com.android.application com.android.dynamic-feature (在模块的清单中包含 dist:instant="false"dist:onDemand="false")

本页面将向您展示如何迁移现有免安装应用项目以构建支持免安装功能的 Android App Bundle。它还描述了如何构建、测试和发布支持免安装功能的 Android App Bundle。

如果您正在为您的应用创建新的即时体验,请阅读创建支持免安装功能模块

了解变更

当您将项目迁移为使用动态功能插件时,Android App Bundle 提供了一种新的构建和发布应用方式,可大幅简化向用户分发优化 APK 的过程。

App Bundle 通过打包所有已编译的应用代码和资源以上传,从而简化分发,但将 APK 生成和签名推迟到 Google Play 进行。Google Play 的新应用分发模型随后使用您的 App Bundle 为每个用户的设备配置生成并分发优化后的 APK,因此他们只需下载运行应用所需的代码和资源。您不再需要构建、签名和管理多个 APK 来支持不同的设备,用户可以获得更小、更优化的下载内容。

当使用现已弃用的功能插件时,构建免安装应用需要创建一个基本功能模块,其中包含所有模块(包括免安装应用模块)的共享代码和资源。其余代码包含在多个非基本功能模块中,这些模块包含免安装体验的入口点。对于应用的已安装版本,您的项目可能包含一个单独的应用模块,其中包含仅适用于已安装应用所需的代码和活动。

当您迁移应用以支持 Android App Bundle 时,您的应用模块将重新承担基本模块的角色,并且您可以将其他已安装或即时体验组织为功能模块。也就是说,您的项目现在更像一个标准应用项目,具有支持免安装功能的基本模块,并能够包含其他模块化的即时体验。

要迁移现有免安装应用项目并采用 Android App Bundle 更优化的分发模型,请按照以下各节中描述的步骤操作。

将基本功能模块转换为应用模块

您首先需要编辑基本功能模块的 build.gradle 文件,然后将其转换为主要应用模块,具体如下:

  1. 删除 baseFeature true 行。
  2. 移除任何使用 featureapplication 依赖项配置的依赖项。

    Groovy

    dependencies {
        ...
        // delete any lines that look like
        // feature project(":foo")
        // feature project(":bar")
        // application project(":app")
    }

    Kotlin

    dependencies {
        ...
        // delete any lines that look like
        // feature(project(":foo"))
        // feature(project(":bar"))
        // application(project(":app"))
    }
  3. applicationId 以及您希望在基本应用模块中包含的任何其他构建脚本配置,从当前的 com.android.application 模块移动到 com.android.feature 模块。下面显示了一些示例。对于此步骤,根据您特定的 build.gradle 设置,将旧应用模块的 build.gradle 中的 android 块复制并粘贴到新应用模块的 build.gradle 文件中可能更容易。但是,您在执行此操作时应谨慎。

    Groovy

    android {
        ...
        defaultConfig {
            // You need to move the application ID from the app module
            // to your feature module.
            applicationId "com.example.myapp"
            ...
        }
        // Some additional build configurations you might want to
        // copy from your current ‘app’ module may include ProGuard
        // rules and code shrinking settings.
        buildTypes {
            release {
                minifyEnabled true
                proguardFiles getDefaultProguardFile(
                  'proguard-android-optimize.txt'),
                  'proguard-rules.pro'
            }
        }
    }

    Kotlin

    android {
        ...
        defaultConfig {
            // You need to move the application ID from the app module
            // to your feature module.
            applicationId = "com.example.myapp"
            ...
        }
        // Some additional build configurations you might want to
        // copy from your current ‘app’ module may include ProGuard
        // rules and code shrinking settings.
        buildTypes {
            getByName("release") {
                minifyEnabled = true
                proguardFiles(
                    getDefaultProguardFile("proguard-android-optimize.txt"),
                    "proguard-rules.pro"
                )
            }
        }
    }
  4. 通过向清单添加适当的 bundle 分发标签,将功能模块标记为支持免安装功能,如下所示。

    <manifest ... xmlns:dist="http://schemas.android.com/apk/distribution">
        <dist:module dist:instant="true" />
        ...
    </manifest>
    
  5. 通过将其插件类型更改为 com.android.application,将功能模块转换为您的基本应用模块

    Groovy

    // Replace  "plugins { id 'com.android.feature' }"
    // with the following
    plugins {
      id 'com.android.application'
    }

    Kotlin

    // Replace  "plugins { id("com.android.feature") }"
    // with the following
    plugins {
        id("com.android.application")
    }

将旧应用模块转换为安装时功能模块

如果旧应用模块中没有代码或资源,您可以直接将其删除,因为您在上一节中执行的步骤已将您的功能模块转换为应用的基本应用模块。

但是,如果旧应用模块中包含您希望用户安装应用时可用的代码和资源,请按照本节中的步骤将应用模块转换为功能模块。

创建功能模块涉及将插件类型从 com.android.application 更改为 com.android.dynamic-feature,以及对 build.gradle 进行其他一些更改,具体如下:

  1. 将插件类型从 com.android.application 更改为 com.android.dynamic-feature

    Groovy

    // Replace "plugins { id 'com.android.feature' }"
    // with the following:
    plugins {
      id 'com.android.dynamic-feature'
    }

    Kotlin

    // Replace "plugins { id("com.android.application") }"
    // with the following:
    plugins {
        id("com.android.dynamic-feature")
    }
  2. 如上一节所述,请确保您已将 com.android.application 插件所需的构建配置(例如 applicationIdproguardFiles 规则)移动到基本应用模块。

  3. 将模块重命名为“installed_feature”等名称,如下所示:

    1. 从菜单栏中选择 View > Tool Windows > Project,打开 Project 窗格。
    2. 右键点击功能模块,然后选择 Refactor > Rename
    3. 在出现的对话框中,选择 Rename module,然后点击 OK
    4. 输入模块的新名称,然后点击 OK
  4. 与步骤 3 类似,将您在上一节中创建的新应用模块重命名为“app”等名称。

  5. 在功能模块的 build.gradle 文件中,添加对“app”模块的实现依赖项,如下所示。

    Groovy

    dependencies {
        ...
        // In the feature module, add an implementation dependency
        // on the base app module.
        implementation project(":app")
    }

    Kotlin

    dependencies {
        ...
        // In the feature module, add an implementation dependency
        // on the base app module.
        implementation(project(":app"))
    }
  6. 将功能添加到新应用模块的 build.gradle 文件中,您已将 installed_feature 添加到功能模块列表中。

    Groovy

    android {
        ...
        // In the base app module, specify each feature module.
        dynamicFeatures = [":installed_feature"]
    }

    Kotlin

    android {
        ...
        // In the base app module, specify each feature module.
        dynamicFeatures.addAll(listOf(":installed_feature"))
    }
  7. 在功能模块的清单中,通过向清单添加适当的 bundle 分发标签,将功能模块标记为可安装模块。

    <manifest ... xmlns:dist="http://schemas.android.com/apk/distribution">
        <dist:module dist:instant="false" dist:onDemand="false"
                dist:title="@string/title_dynamic_feature">
            <dist:fusing dist:include="true" />
        </dist:module>
        ...
    </manifest>
    

将其他功能模块转换为支持即时功能的功能模块

如果您已将应用的附加功能模块化为多个功能模块,则需要按照本节中的步骤将这些模块转换为支持即时功能的功能模块。

对于项目中的每个剩余功能模块,请按照以下步骤将其转换为支持即时功能的功能:

  1. build.gradle 文件中的插件类型更改为 com.android.dynamic-feature,如下所示:

    Groovy

    // Replace 'com.android.feature' with 'com.android.dynamic-feature'
    plugins {
      id 'com.android.dynamic-feature'
    }

    Kotlin

    // Replace "com.android.feature" with "com.android.dynamic-feature"
    plugins {
        id("com.android.dynamic-feature")
    }
  2. 通过向清单添加以下内容,将每个功能模块标记为支持即时功能。

    <manifest ... xmlns:dist="http://schemas.android.com/apk/distribution">
        <dist:module dist:instant="true" dist:onDemand="false"
                dist:title="@string/title_dynamic_feature">
            <dist:fusing dist:include="true" />
        </dist:module>
        ...
    </manifest>
    
  3. 将功能模块添加到新应用模块的 build.gradle 文件中,您已将 installed_feature 添加到功能模块列表。

    Groovy

    android {
       ...
       dynamicFeatures = [":installed_feature", ":feature_1", ":feature_2"]
       // or whichever name exists for the instant enabled feature module
    }

    Kotlin

    android {
       ...
       dynamicFeatures.addAll(listOf(":installed_feature", ":feature_1", ":feature_2"))
       // or whichever name exists for the instant enabled feature module
    }

构建、测试和发布新的支持即时功能的 App Bundle

完成本页面上的步骤后,您的项目能够生成一个工件(Android App Bundle),您可以用来将应用的已安装版本和即时版本发布到 Google Play 管理中心,并针对即时和已安装轨道单独发布。此外,通过 App Bundle,您可以获得为每个用户的设备配置提供优化 APK 的好处,这样他们只需下载运行应用所需的代码和资源。也就是说,您不再需要构建、签名和管理多个 APK 来支持不同的设备,用户可以获得更小、更优化的下载内容。

要开始构建和测试您的支持即时功能的 App Bundle,请访问构建 App Bundle