1 介绍
Google引入新Android App Bundle应用文件格式。这种文件包括所有的应用程序的编译代码和资源,Google Play 根据用户的手机信息生成所需资源和SO的APK,用户只需要下载运行应用所需的资源。而且Android App Bundle提供功能动态加载的功能(类似插件化的概念),开发者可用将不重要或者独立的功能在用户需要的时候加载。
Android5.0(API 20)及以上,包含应用程序支持的所有功能和设备配置的代码和资源的APK,分解为安装在用户设备上的更小的独立包,并根据需要进行安装。拆分的APK与正常APK非常相似,它们包括编译的DEX字节码,资源和Android清单。以下描述了三种拆分APK关系。
- Base APK:这个APK包含所有其他拆分APK可以访问的代码和资源,并为应用提供基本功能。这是用户下载应用时安装的第一个APK。
- Configuration APKs: 这些APK中的每一个都包含用于特定屏幕像素密度,CPU架构库和资源。当设备下载一个基本或动态功能APK时,它只下载它需要的库和资源。对于大多数应用项目,无需重构应用即可支持Configuration APK,Google Play会根据您的应用包中包含的代码和资源生成。
- Dynamic feature APKs:这些APK主要是动态功能的代码和资源,不是用户第一次必须安装。
apk关系图
Android5.0(API 20)以下不支持动态加载,Google Play为手机直接生成一个完整功能和对应CUP架构、资源的APK。
2 创建Demo
*Android Stuidio 3.2
1).配置工程
①.创建一个正常的工程。
②. 新建Dynamic Feature Module。
③. 创建完成以后可以看到Dynamic Feature Module和普通的项目目录一样,在build.gradle中声明的是全新的module类型apply plugin: ‘com.android.dynamic-feature’,而且dynamic-feature模块中可以引用app模块,之前的版本中Application模块是无法作为lib被其他模块引用的。
1 | apply plugin: 'com.android.dynamic-feature' |
④. AndroidManifest中声明了一些动态功能模块属性。onDemand指定模块是否应作为按需下载提供,Title 指定模块向用户的展示的标题, fusing指定是否将模块包含在运行Android 4.4(API级别20)或更低的设备。
1 | manifest xmlns:android="http://schemas.android.com/apk/res/android" |
⑤.在App module build.gradle 中添加配置。
1 | android { |
2) 功能模块动态加载
①App项目中添加Google加载类库
1 | implementation 'com.google.android.play:core:1.2.0' |
②按需加载动态模块,首先创建SplitInstallRequest,然后通过SplitInstallManager执行一个加载请求。在下载和安装中会回调处理状态,可根据状态做一些处理。
1 | SplitInstallRequest request = SplitInstallRequest.newBuilder() |
③调用动态功能模块
1 | private void onSuccessfulLoad(String dynamicFeature) { |
3)编译文件格式的处理流程
Google这次为App Bundles推出.aab新的文件格式, 包含了应用所有模块的代码和资源。Google Play根据用户手机信息通过这个.aab的文件生成拆分APK文件。
① 使用Android Studio生成 aab文件。
- 从菜单栏中选择Build> Generate Signed Bundle / APK。
- 在Generate Signed Bundle or APK对话框中,选择 Android App Bundle 并单击Next。 然后继续后面步骤完成后就会生成一个.aab的文件。
② 文件拆分
首先从Github下载命令工具bundletool(https://github.com/google/bundletool/releases)
执行下面的命令后会生成一个my_app.apks的文件。
1 | java -jar bundletool-all-0.3.3.jar build-apks --bundle=C:\code\PP\app\release\bundle.aab --output=C:\code\PP\app\rel |
③ 提取拆分APK
首先通过命令获取设备信息。
1 | java -jar bundletool-all-0.3.3.jar get-device-spec --output=C:\code\PP\app\release\device.json |
执行命令后可以获取到设备信息如下device.json
1 | { |
然后根据设备信息生成APK,最终生成4个APK。
1 | java -jar bundletool-all-0.3.3.jar extract-apks --apks=C:\code\PP\app\release\my_app.apks --output-dir=C:\code\PP\app\release\ --device-spec=C:\code\PP\app\release\device.json |
base-mastet指Base APK,base-xhdpi指Config APK和介绍中的文件结构图对应。
④文件资源分析
将base-mastet.apk拖到Android Studio中,可以看见文件的差别,里面不包含xhdpi的资源。然后再分析base-xhdpi.apk的文件,里面包含base-mastet.apk所缺的xhdpi资源。
base-mastet资源图
base-xhdpi资源图
⑤动态功能代码分析
可以看到master-base中没有包含dynamic_feature-master中的代码。
base-mastet代码
dynamic_feature-master代码
4)动态加载原理浅析
因为Google库代码混淆,整体的流程无法分析,但是基本的一些原理关键点可以找到。主要集中在com.google.android.play.core.splitcompat.b包下。可以发现基本都是插件化中使用到的技术。
1 | com.google.android.play.core.splitcompat.c.b.a(var14, "addAssetPath", Integer.class, String.class, var9.getPath()) |
5) App Bundle总结
优势:
通过设备信息动态生成用户设备所需SO和资源的APK,并支持功能动态化加载,开发者可以根据用户按需加载功能模块,而不是仅限在安装过程中。最终使得安装包体积更小,下载速度也越快,同时也节省了设备存储空间。
App Bundle的实现技术方案类似于插件化,但是有官方的支持,兼容和稳定性上能做的更好。
劣势 :
暂时只有Google Play支持Android App Bundle,其他应用市场无法使用,而且需要上传私钥。
动态化功能虽然类似于插件化,但是编译打包必须在同一个项目下,来解决资源文件冲突和四大组件清单声明问题。