欢迎光临
专注android技术,聚焦行业精粹,我们一直在努力

如何配置bundle app的动态交付 Android App Bundle

如果你想要支持Google Play的动态交付功能,你首先需要配置你的工程来构建一个Android App Bundle —— 它是一个单独的工件,包含了你应用所有的编译的代码和资源,但是将APK的生成和签名推迟给了Google Play来处理。

Google Play 使用你的 app bundle根据每个用户的设备配置来生成和提供优化后的APK,所以他们仅仅会下载他们需要的代码和资源来运行你的应用。你不必再构建,签名和管理多个APK了,而且用户会得到更小,更优化的下载内容。

大多数的App不需要太多的工作量来使用动态交付构建app bundle去支持提供优化的APK。例如,如果你已经按照android已经存在公约来组织你的代码和资源,你就可以使用Android Studio来构建签名的Andoid App Bundle,并且可以将它们上传到Google Play。动态交付则自动生效。

另外你可以添加动态功能模块到你的工程项目,并将它们包含在你的app bundle里面。通过动态交付,你的用户就可以根据需要下载和安装你应用的动态功能了。然而按需创建模块需要更多的努力并可能需要重构你的APP,所以仔细考虑应用程序的哪些功能最适合用户按需使用。

开始为动态交付配置项目的最简单方法是使用最新版本的Android Studio。所以如果你没有最新的版本,现在就下载Android Studio 3.2 Canary 吧。

1、动态交付与拆分APK

动态交付的一个基本组成部分是Android 5.0(API级别21)及更高版本中可用的拆分APK机制。拆分的APK和普通的APK非常相似 —— 它们都包含编译后的DEX 字节码,resources资源,一个android manifest文件。但是,android平台可以将多个安装的拆分APK作为一个单独的app来处理。也就是说,你可以安装多个可以访问公共代码和资源的拆分APK,就像安装在设备上的一个应用一样。

拆分APK的好处是可以将一个单独的APK分解开 —— 也就是说一个包含支持了所有设备配置的代码和资源分解为更小的离散的包,可以根据设备配置的需要安装到用户的设备上。

例如,一个拆分APK可能包含只有少部分用户需要的额外功能所需的代码和资源,另外一个拆分APK包含特定语言或屏幕分辨率的的资源。每个拆分后的APK都会根据用户的需要或者设备的需要下载和安装。

以下描述了可以安装在设备上以形成完整应用体验的不同类型的APK。您将了解如何配置您的应用项目以在本页后面的章节中支持这些APK。

  • 基础APK:这个APK包含了所有其它拆分APK可以访问的代码和资源,并为您的APP提供了基础的功能。当用户请求下载你的应用,这个APK是第一个下载和安装的。那是因为只有基础APK的manifest包含了所有您应用定义的service, content-provider, permissions, 所需的platform-version和对系统功能的依赖。Google Play从您工程的base module为您的应用生成这个基础APK。
  • 配置APK:每个这样的配置APK包含特定屏幕分辨率,CPU架构或者语言相关的native库和resources资源。当用户下载您的应用,他们的手机设备只会根据他们的设备配置下载和安装相应的配置APK。每个配置APK都依赖基础APK或者动态功能APK。也就是说,这些配置APK会随着提供代码和资源的APK一起下载和安装,你不需要单独为配置APK创建一个模块。如果您的基础模块和动态功能模块遵循android资源配置的标准实践Google Play 会自动为您生成这些配置APK
  • 动态功能APK:这些APK中的每一个都包含应用程序功能的代码和资源,这些功能在首次安装应用程序时不是必需的。也就是说通过使用Play Core Library,动态的APK可能会在基础APK安装后按需安装到设备,这些APK为用户提供了额外的功能。例如:在您的一个聊天APP里面如果用户需要用到拍照和上传图片的功能就会为用户下载和安装这些APK。由于动态功能在安装时可能不可用,因此您应该在基础APK中包含任何公共的代码和资源。 也就是说,您的动态功能应该假定只有基础APK的代码和资源在安装时是可用的。Google Play 会从您工程的动态功能模块为您生成动态功能APK.

假设一个包含三个动态功能模块的应用程序,并支持多种设备配置。下面的图1说明了应用的各种APK的依赖关系树可能看起来像什么。注意:基础APK在树的头部,所有其他APK都依赖于基础APK。(如果您对这些APK的模块在Android应用程序包中的表现感到好奇,请阅读Android App Bundle 格式

图 1. 应用提供的拆分APK的依赖树

记住: 你不需要自己构建这些APK —— Google Play 会根据你用Android Studio构建的一个签名的App Bundle来为您做这些事情。了解更多关于App Bundle格式和如何构建一个这样的App Bundle,请阅读构建,部署和上传Android App Bundles

Android 4.4(API level 20)及以下的设备

由于Android 4.4(API level 20)以及更低的版本的设备不支持下载和安装拆分APK。Goole Play 会为这些设备改为提供一个单独的APK,叫做一个多APK,这是一个为设备配置优化过的APK。也就是说,多APK代表您的完整应用体验,但不包含不必要的代码和资源——例如那些其它屏幕分辨率和CPU架构的。

但是,它们会为您的应用支持的所有语言提供资源。这样,用户就可以更改应用的首选语言设置,而无需下载其他多APK

多APK不能按需延时下载动态功能模块。想要在这个APK里面包含动态模块,您需要在创建动态功能模块时要么禁用On-demand或者启用Fusing开关。

请记住,通过动态交付,您无需为应用支持的每种设备配置构建,签名,上传和管理APK。您仍然只为您的整个应用构建和上传一个App Bundle,Google Play会为您处理其余的问题。因此,无论您是否计划支持运行Android 4.4或更低版本的设备,动态交付都可为您和您的用户提供灵活的服务机制。

基础模块

大多数应用程序项目不需要太多努力来支持动态交付。这是因为包含您应用的基础APK的代码和资源的模块是标准应用模块,当您在Android Studio中创建新的应用程序项目时,默认情况下会获得该项目。也就是说,将应用app plugin应用于其build.gradle文件的模块为您的应用程序的基础功能提供了代码和资源。

如果你关心的是减少你的应用程序的初始下载大小,请记住,该基础模块中包含的所有代码和资源都会包含在您应用的基础APK中,这一点很重要。

除了为您的应用程序提供核心功能之外,基础模块还提供许多影响整个app应用程序项目的build构建配置和manifest清单条目。例如,为您的App Bundle签名用的是您为基础模块提供的信息,并且您的基础模块清单中的versionCode属性会应用到所有拆分的APK的版本。下面介绍基础模块的其他重要方面。

基础模块 manifest

App Bundle的manifest和其它任何app模块的manifest很相似,但是,如果您考虑添加动态功能模块到您的工程,基础APK的manifest有一些方面您应该注意:

  • 由于基础APK都会首先被安装,它需要提供您应用程序的主入口。也就是说,它应该定义一个包含下面intent filter的activity:
  • 当需要按需下载动态功能模块时,在Android6.0(API level 23)及以下的设备上需要重新启动应用程序才能完成新模块的安装。但是,如果您想要在模块下载完成后立即访问这个模块的代码和资源,您需要包含支持SplitCompat 库到您的manifest,了解更多,请阅读访问已下载模块的代码和资源
  • 同样的,在Android6.0(API level 23)及以下的设备上,应用程序需要重新启动来让平台可以应用这些新增加的manifest条目。所以,如果您想要在一个动态功能模块下载完成后立即访问特定的permission和service,建议将它们放在基础模块的manifest文件中。

 

基础模块的 build 配置

对于大多数的app工程,您不需要对您的基础模块的build配置做任何的修改,但是,如果您考虑添加一个动态功能模块到您的app工程,基础模块的build配置有一些方面您需要注意:

  • App签名:您不需要再您在的build配置文件中包含签名信息,除非您想要使用命令行来生成你的App Bundle。但是,如果您包含了签名信息,您应该只将它包含到基础模块的build配置文件中。了解更多,请阅读使用Gradle配置来签名您的app
  • 代码压缩:如果您为您的整个工程(包括它的动态功能模块)想要启动代码压缩,您应该用基础模块的build.gradle文件来做这件事情。也就是说,您可以在一个动态功能模块添加自定义的Proguard 规则,但是在动态功能模块的build配置文件中的minifyEnabled属性将会被忽略。
  • split 块会被疏略:在构建一个App Bundle时,Gradle会忽略在android.splits块里面的属性。如果您想要控制哪种类型的配置APK您的App Bundle会支持,可以更改使用android.bundle禁用配置APK的类型
  • 应用版本控制基础模块决定了您整个app工程的版本号和版本名称。了解更多信息,查阅这一章节内容:关于如何管理App升级

 

禁用配置APK的类型

默认情况下,当您构建一个App Bundle,它将支持为每一套语言资源,屏幕分辨率资源和ABI库生成配置APK。按下面的方式在您的基础模块的build.gradle文件中使用android.bundle代码块,您可以实现禁用一种或多种类型的配置APK的支持。

管理 app 升级

有了Andoid App Bundle动态交付,您不再需要再为上传到Google Play的多个APK去维护版本号了。相反的,您只要管理您应用中基础模块的一个版本号就可以了,如下面显示:

在您上传您的App Bundle之后,Google Play会使用您基础模块里面的版本号,并将相同的版本号分配给它从App Bundle生成的所有APK。也就是说,当一台设备下载和安装了您的应用,所有该应用的拆分APK将共享相同的一个版本号。

当您想要用新的代码和资源来升级您的应用,您应该升级您应用中基础模块的版本号,并构建一个新的,全的App Bundle。当您上传那个App Bundle到Google Play,它将基于这个基础模块指定的新的版本号来生成新的一套APK。接下来,当用户升级您的应用,Google Play为它们提供了当前安装在设备上的所有APK的更新版本。也就是说,所有安装的APK将升级到这个新的版本号。

注意: 由于您不再需要维护您应用所有APK的版本号了,,您不再需要基于设备配置来动态修改版本号的代码逻辑了。

 

下载额外的配置APKs

上述更新流程的一个例外是安装的应用程序需要额外的配置APK。考虑一个用户在已经下载了您的app后改变了他们默认的系统语言设置。如果您的app支持这些语言,该设备会从Google Play为这些语言资源请求并下载其他配置APK,但是这种类型的app升级不会改变它的版本号,所以设备只会下载和安装它需要的配置APK。

 

动态功能模块

动态功能模块允许您从应用程序的基础模块中分离某些功能和资源,并将它们包含在App Bundle中。通过动态交付,用户可以在安装了您应用的基础APK后按需延时下载和安装这些组件。

例如,有一个包含拍照和发送图片消息功能的短信应用程序,但是只有小部分的用户需要发送图片消息。将图片消息作为可下载的动态功能模块可能是有意义的。这样做的话,初始下载的应用包对于所有用户会更小,而只有那些需要发送图片的用户需要下载额外的组件。

请注意,这种类型的模块化需要跟多的努力,并且可能需要重构您应用中已有的代码,所以请仔细考虑应用程序的哪些功能最适合用户按需使用。Android App Bundle提供了一些其他选项,可帮助您将应用程序转换为完全支持按需功能。这些选项会在本节稍后介绍。

注意: 如果您的应用包含了动态功能模块,您可以上传并通过Play Console控制台的内部测试环境测试您的app。 但是发布到生产环境,您必须申请动态功能Beta项目,了解更多,请转到Play Console帮助主题了解如何使用Beta 项目来为动态功能模块发布应用程序

通常,动态功能模块的组织方式与常规应用程序模块相同。他们在您期望的目录中提供他们自己的代码,resouces和assets资源。但是,还有一些manifest清单文件中附加属性和build构建配置中的属性允许动态功能模块用于开启按需下载这些动态功能模块

这一章节这些差别和怎样使用Android Studio来创建一个动态功能模块

 

创建一个动态功能模块

最简单创建一个动态功能模块的方式是使用最新的Android Studio的Canary版本。由于动态功能模块对基础应用程序模块具有固有的依赖性,因此只能将它们添加到现有的应用程序项目中。

要使用Android Studio为您的应用项目添加动态功能模块,请按照下列步骤操作:

1.如果您尚未这样做,请在IDE中打开您的应用程序项目。

2.菜单中选择 File > New > New Module

3.在Create New Module的对话框中,选择Dynamic Feature Module,并点Next

4.在 Configure your new module 区域,按以下步骤完成:

  1. 在下拉菜单中为您的工程选择Base application module
  2. 填写Module name。IDE会在您的Gradle settings配置文件中使用此名称将模块标识为您的Gradle子项目。当您构建您的App Bundle时,Gradle使用子项目名称的最后一个元素在动态功能模块的manifest清单中注入<manifest split>属性。
  3. 填写模块的package name。默认情况下,Android Studio会建议一个包名称,它将基础模块的根包名称与您在上一步中指定的模块名称结合起来。
  4. 选择您模块需要支持的Minimum API level,这个值应该和基础模块的匹配。

5.点击Next

6.在 Configure On-Demand Options 区域,按下面步骤处理:

a. 使用最多50个字符指定模块标题。例如,当确认用户是否想要下载模块时,平台使用该标题来向用户标识模块。出于这个原因,你的应用程序的基础模块必须包含模块标题的string resources,您可以翻译。当使用Android Studio来创建模块时,IDE会帮您把这个string放在基础模块,并在动态功能模块的manifest清单文件中注入下面的条目:

b. 如果您想要这个模块可以按需下载,请勾选Enable on-demand 旁边的选择框。如果您不勾选这个选项,这个动态功能会在用户首次下载和安装您的app时可用。Android Studio在模块的manifest清单中注入以下内容以反映您的选择。

c. 如果您希望此模块可用于运行Android 4.4(API级别20)或更低级别的设备并将其包含在多APK中,请选中Fusing旁边的复选框。这个选项只有在您之前一步勾选了Enable on-demand后才可以使用。这意味着您可以启用此模块的按需行为,并禁用Fusing,以便在不支持下载和安装拆分APK的设备上忽略它。Android Studio会在模块的manifest清单文件中注入以下的条目来反映您的选择:

7. 点击Finish

在Android Studio完成创建您的模块后,需要您自己在Project窗口检查该模块的内容(在菜单栏选择  View > Tool Windows > Project )。你会立即发现它的默认的代码,资源和结构和标准的app模块很相似。

 

动态功能模块的 build 配置

当您使用Android Studio创建了一个新的动态功能模块,IDE会添加下面的Gradle 插件到模块的build.gradle文件中。

许多可以在标准的application插件中使用的属性也可以在您的动态功能模块中使用。下面的章节介绍了哪些属性您应该和不应该在您的动态功能模块的build配置中包含。

什么不应该在动态功能模块的build配置中包含

由于每个动态功能模块都依赖基础模块,它也继承了某些配置。所以,您应该在动态功能模块的build.gradle文件中忽略下面的配置:

  • 签名配置:App Bundle会使用您在基础模块中的签名配置来签名。
  • minifyEnabled 属性:您只可以通过基础模块的build配置来为您整个app工程开启代码压缩。所以,您应该在动态功能模块中忽略这个属性。但是您可以为每个动态功能模块指定额外的ProGuard规则
  • versionCode和versionName:当构建您的app bundle时,Gradle使用的是基础模块提供的版本信息。您应该在您的动态模块的build.gradle文件中忽略这些属性。

 

关联基础模块

当Android Studio为您创建了动态功能模块,它通过将android.dynamicFeatures属性添加到基础模块的build.gradle文件中,使其对基础模块可见。如下面所示:

另外,Android Studio会在动态功能模块的依赖关系中包含基础模块,如下所示:

 

指定额外的ProGuard规则

尽管只有基础模块的build配置可以为您的app工程开启代码压缩,您可以使用下面consumerProguardFiles 属性为每一个动态功能模块提供自定义的ProGuard规则:

请注意,这些ProGuard规则在构建时会与其他模块(包括基础模块)的规则合并。因此,虽然每个动态功能模块都可以指定一组新的规则,但这些规则适用于应用程序项目中的所有模块。

 

动态功能模块的manifest

当使用Android Studio创建了一个新的动态功能模块,IDE引入了让该模块成为动态功能的大部分manifest清单属性。此外,一些属性在编译时由构建系统注入,所以您不需要自己去指定货修改它们。下面的表格描述了动态功能模块的重要的manifest属性。

AttributeDescription
This is your typical  block.
xmlns:dist="http://schemas.android.com/apk/distribution"Specifies a new dist: XML element that’s described further below.
split="split_name"Defines the name of the module, which your app specifies when requesting an on demand module using the Play Core Library.
When Android Studio builds your app bundle, it includes this attribute for you. So, you should not specify or modify this attribute yourself.

How Gradle determines the value for this attribute:

By default, when you create a dynamic feature module using Android Studio, The IDE uses what you specify as its Module name to identify the module as a Gradle subproject in your Gradle settings file.

When you build your app bundle, Gradle uses the last element of the subproject path to inject this manifest attribute in the module’s manifest. For example, if you create a new dynamic feature module in the MyAppProject/features/ directory and specified "dynamic_feature1" as its Module name, the IDE adds ':features:dynamic_feature1' as a subproject in your settings.gradle file. When building your app bundle, Gradle then injects in the module’s manifest.
android:isFeatureSplit="true | false">Specifies that this module is a dynamic feature module. Manifests in the base module and configuration APKs either omit this attribute or set it to false.
When Android Studio builds your app bundle, it includes this attribute for you. So, you should not specify or modify this attribute manually.
This new XML element defines attributes that determine how the module is packaged and distributed as APKs.
dist:onDemand="true | false"Specifies whether the module should be available as an on demand download. That is, if this attribute is set to true, the module is not available at install time, but your app may request to download it later.
If this attribute is set to false, the module is included when the user first downloads and installs your app.

To learn more about on demand downloads, read about Download modules with the Play Core Library.
dist:title="@string/feature_name" Specifies a user-facing title for the module. For example, the device may display this title when it requests download confirmation.

You need to include the string resource for this title in the base module’s module_root/src/source_set/res/values/strings.xml file.
 
Specifies whether to include the module in multi-APKs that target devices running Android 4.4 (API level 20) and lower.
Additionally, when you use bundletool to generate APKs from an app bundle, only dynamic feature modules that set this property to true are included in the universal APK.

Note: 动态功能模块不应该在它们的manifest文件中设置activity的android:exported的属性为true。这是因为当另一个应用尝试启动该Activity时,不能保证该设备已经下载了动态功能模块。.此外,您的应用程序应确认在尝试访问其代码和资源之前下载了动态功能. 了解更多,请阅读管理安装的模块

 

部署您的应用

在开发支持动态交付的应用程序时,您可以像往常一样通过选择菜单栏的Run > Run将应用程序部署到连接的设备。

如果您的工程包含了一个或多个动态功能模块,您可以选择在部署应用程序时包含哪些动态功能,按如下的方式修改您已有的run/debug 配置:

  1. 在菜单栏选择Run > Edit Configurations
  2. Run/Debug配置对话框的左边窗口,选择您需要的Android App配置。
  3. General选项卡下面的Dynamic features to deploy,选中您在部署应用程序时要包含的每个动态功能模块旁边的复选框。
  4. 点击OK

默认情况下Android Studio不会使用App Bundle来部署您的应用——它会构建APK并将其推送到您的设备,这些优化的是部署速度,而不是APK的大小。将Android Studio配置改为从App Bundle构建和部署APK,请参考使用App Bundle来部署您的应用

赞(1) 打赏
未经允许不得转载:花花鞋 » 如何配置bundle app的动态交付
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

国内精品Android技术社区

联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏