从8月份开始,Google要求在Google Play上架的应用必须使用新的AAB格式。对我来说,这并不是什么新鲜事,因为去年12月份官方就提前通知了这一变化。
请问您需要将这段话改写成什么样的形式呢?是要简化或者重述其中的内容,还是需要转换成其他风格的文案?请提供更多具体信息,我会尽力满足您的需求。
我感到惊讶的是,这条“旧闻”最近却引起了广泛的关注和热议,原来竟然是因为它蹭了鸿蒙操作系统的热度。
在2018年的Google I/O上,AAB首次亮相。难道当时谷歌就意识到鸿蒙的出现了吗?
不过客观来说,AAB 虽然早已出现,但在国内很少被提及,因此造成部分媒体的错误解读也有情可原。那么本文就为大家做一个关于 AAB 的科普,打消鸿蒙支持者们的顾虑。
Android App Bundle
AAB(Android App Bundle)是由Google于2018年推出的一种动态打包方式。通过以AAB格式上传至Google Play或其他支持AAB的应用市场,应用程序可以根据不同用户的需求按需下发功能或资源。目前,Google Play(简称GP)提供的动态化服务都是基于AAB实现的。尽管有些文章声称这些服务属于AAB本身,但准确来说它们是GP提供的服务。
- Play Feature Delivery(PFD) :借助 AAB 实现 Feature 的按需动态加载,这类似于国内流行的“插件化”技术
- Play Asset Delivery (PAD) :借助 AAB 实现一些资源素材的按需动态下载,这特别适合一些游戏类APP,无需为了适配所有机型保留全部游戏素材
除了游戏资源外,AAB 还可以根据需求下发常规资源。举个例子,不再需要同时存在 hdpi、xhdpi 等多套图片,这使得许多应用在包大小方面有了显著的提升。
在当今用户推广成本飙升的背景下,包体积越小意味着装机率越高,这一点至关重要。
App Bundle 文件格式
让我们首先来探究一下AAB文件格式,与传统的APK有何异同之处。
AAB 解压后的内容与 APK 非常相似,但也存在一些明显差异:
AAB 格式的重要部分包括后三个.bp
文件,它们详细描述了APP的各项服务目标。根据这些目标,在动态下发过程中,不同资源将从路径 drawable/hdpi
、lib/armeabi-v7a
或者 values/es
中进行组织和下发。
Split APKs
Split APKs 机制是 Android App Bundle(AAB)实现动态下发的基础。该机制允许将一个庞大的 APK 按照不同维度进行拆分,形成独立的 APK 文件。当用户在 Google Play 下载应用时,Android Framework 通过 IPC(进程间通信)与 Google Play 进行通信,并为当前设备匹配并下载最小构成的 APK 文件。需要注意的是,这一机制仅在 Android 5.0 及以上版本的设备上有效。
一旦AAB文件上传成功,GP将通过分析找出所有设备共享的资源,并生成一个名为Base APK的文件。当用户下载应用时,首先会安装Base APK。
根据language
、density
、abi
等三个维度,GP通过生成配置APKs(拆分), 拆分后的APKs与基础版本共享versionCode、packageName等信息,并以一个应用的形式存在于进程管理器中。
当用户从应用市场下载应用时,GP会根据设备类型为其下发不同的Splits,以实现最小化的下发量。
根据不同设备,我们将分别发布三种不同的Splits。请参考下图。
当用户的设备发生配置更改(例如切换系统语言)时,GP将向手机下发新的分割文件。如果此时手机处于离线状态,将会在下次上线时自动进行分发。
Split APKs 的动态下发只适用于 Android 5.0 及以上版本的设备。对于较旧的设备,AAB 将根据这些 Splits 的矩阵生成多个独立的APK文件。虽然缺少了动态下发功能,需要一次性安装完成,但相比传统APK,仍然减小了包大小。
作为开发者,我们无需关心这些具体的下发策略,只需要向市场上传一个 AAB ,后续就交给 FW 和 GP 去处理了。
创建 App Bundle
打包 AAB
使用 Android Studio,您可以轻松打包 AAB 文件。
此外,还可以利用Gradle命令进行打包,这在某些持续集成流程中更为适用。
以下是使用Gradle打包一个debug版本的AAB的步骤: 使用Gradle进行debug版本的AAB打包,可以按照以下方式操作:
要生成 release 的 AAB,需要进行签名配置。与 APK 的配置方式相同,使用命令./gradlew :base:bundleDebug
。AAB 默认会为三种配置生成拆分文件,当然您可以根据需求自行进行配置:
``` bundle { language { enableSplit = false } density { enableSplit = true } abi { enableSplit = true } } ``` **上传应用市场** 生成AAB后,您可以将其上传到应用市场。在Google Play中,将AAB和APK的上传入口放在一起。当然,在8月之后就不再有APK的上传入口了。
AAB 上传后,通过后台可以查看其详细信息
比如,您可以查看 AAB 支持的屏幕密度以及包体积减少等相关信息。
Bundle Tool
AAB 无法直接在手机上安装,如果要在本地对 AAB 进行测试,需要将其转换为 APK 格式。这一过程需要使用 Google 官方提供的 Bundletool 工具。
Bundletool 可以提取当前设备的信息
bundletool get-device-spec --output=/tmp/device-spec.json复制代码
设备的 Configurations 信息输出到指定 json 中
根据给定的 JSON 数据,Bundletool 将生成中间文件.apks
。该 JSON 数据包含以下信息:{ "supportedAbis": ["arm64-v8a", "armeabi-v7a", "armeabi"], "supportedLocales": ["zh-CN
bundletool build-apks --bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks --ks=/MyApp/keystore.jks--ks-pass=file:/MyApp/keystore.pwd--ks-key-alias=MyKeyAlias--key-pass=file:/MyApp/key.pwd--device-spec=file:device-spec.json复制代码
apks 的生成物分为
splits
和standalones
两个文件夹,splits 是按照 Configuration 维度进行拆分的 Split APKs,必须与 base.apk 一起安装;而 standalone 则需要单独安装,这样可以兼容 Android 5.0 及以下版本。
toc.pb
是 apks 的存档清单,它是一个描述文件,包含了 APK 集合的相关信息。接下来,根据 JSON 文件的内容,从 APKs 中提取 APK:
使用 Bundletool 提取 APK 并根据设备规范安装到指定目录: ``` bundletool extract-apks --apks=${apksPath} --device-spec={deviceSpecJsonPath} --output-dir={outputDirPath} ``` 请注意,此命令只是将 APK 提取并根据设备规范安装,并非直接安装 apks。Bundletool的整体流程是通过执行以下命令来安装APK文件:bundletool install-apks --apks=/MyApp/my_app.apks
创建 Dynamic Feature
除了下发 Configuration APKs,还可以以业务模块为单元进行动态下发,这种方式被称为“插件化”,也就是所谓的 Dynamic Features(简称 DF)。
IDE 中选择 New 一个 DF 的 Module:
点击下一步,选择 DF 安装的时间,例如一次性完全安装或按需安装。
创建的 DynamicFeature Module,其目录结构与普通的 Gradle Module 类似。
然而,在 build.gradle 文件中,插件的设置有一点不同:`com.android.dynamic-feature`。
在build.gradle中,不需要配置versionCode、versionName、signConfig等信息。动态特性本质上也是分割APK,因此可以共享基础APK的这些信息。当您重新打开 app/ 的 build.gradle 文件时,您会注意到以下配置已经添加进去了。
dynamicFeatures = [':dynamicfeature']最终,DF的宣言也经历了改变:
复制下面的这段话,“使用最新版本的Play Core库:'com.google.android.play:core:$latest_version'。通过Play Core,用户可以交互地请求下载和安装DF,并监听下载状态。”
发起下载请求
要下载 DF,您需要使用
SplitInstallManager
。使用SplitInstallManagerFactory创建一个SplitInstallManager实例,并将其赋值给splitInstallManager变量。然后,创建一个SplitInstallRequest对象,用于请求下载模块。SplitInstallRequest request = SplitInstallRequest.newBuilder() .addModule(someDynamicModule) .build();使用
SplitInstallManager
启动 Request 进行请求,并将下载状态的回调监听设置为。调用splitInstallManager.startInstall(request)
方法会立即发起请求。此外,还可以使用deferredInstall
来延迟请求,只有当应用在后台启动时才开始发送请求。splitInstallManager .deferredInstall(Arrays.asList("someDynamicModule"));复制代码
除了请求指定 DF 以外,也可以请求指定的资源,比如安装语言资源
SplitInstallRequest request = SplitInstallRequest.newBuilder() .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) .build();复制代码
发起请求后,会返回一个
Int
值作为 session ID,通过调用cancelInstall(Int)
, 可以取消当前的下载。在发起请求后,可能会遇到无法正常建立链接的情况。此时,系统将返回以下错误信息:
Error Descriptions ACCESS_DENIED鉴于当前设备的某些原因,无法下载ACTIVE_SESSIONS_LIMIT_EXCEEDED当前应用的请求 session 太多API_NOT_AVAILABLE请求 API 目前无法使用INCOMPATIBLE_WITH_EXISTING_SESSION请求的 session 中包含了已经请求中的 DFINTERNAL_ERROR内部错误INVALID_REQUEST无效请求MODULE_UNAVAILABLE请求的 DF 不存在NETWORK_ERROR网络错误NO_ERROR无法获得错误信息SERVICE_DIED服务无响应SESSION_NOT_FOUND无法获取被请求的 session下载安装
一旦成功建立连接,接下来就进入了下载和安装阶段。通过使用SplitInstallStateUpdatedListener监听下载和安装的状态,我们可以根据这些状态为用户提供有关下载进度等方面的提示。
val stateListener = SplitInstallStateUpdatedListener { state -> when (state.status()) { SplitInstallSessionStatus.PENDING -> { } SplitInstallSessionStatus.DOWNLOADING -> { } SplitInstallSessionStatus.DOWNLOADED -> { } SplitInstallSessionStatus.INSTALLED -> { } SplitInstallSessionStatus.INSTALLING -> { } SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> { } SplitInstallSessionStatus.FAILED -> { } SplitInstallSessionStatus.CANCELING -> { } SplitInstallSessionStatus.CANCELED -> {} }可以使用以下代码来获取已安装的模块: ```kotlin val installedModules = splitInstallManager.installedModules ``` 此外,您还可以使用 `deferredUninstall` 对动态功能进行指定卸载。``` splitInstallManager.deferredUninstall(listOf(someDynamicModule)) .addOnSuccessListener { } .addOnFailureListener { } .addOnCompleteListener { } ```AAB的优势
根据Google官方数据,使用AAB相比APK,平均可以减小20%的包大小,这也意味着节省了20%的下载流量。以Twitter为例,在采用AAB之后
```
- language 相关资源节省 95%
- density 相关的 Splits 节省 45%
- abi 相关资源节省 20%
使用AAB不仅在包大小方面有优势,而且在开发效率上也带来了收益。不再需要为不同目标设备配置多个Flavor、生成多个APK并分别上传,只需上传一个AAB文件即可,剩下的工作交由应用市场处理。
国内的 AAB 使用
Qigsaw是爱奇艺提供的一套基于Android App Bundle的动态化解决方案。该方案不依赖Google Play服务,用户可以在国内体验Android App Bundle开发工具。Qigsaw支持通过动态下发插件APK,并采用单类加载器方式,使应用能够在无需重新安装的情况下实现插件的动态安装。
此外,华为应用市场早已支持AAB的上传和动态下发。因此,请不要再错误地认为AAB是对华为的打压产物了 😄
华为开发者网站(developer.huawei.com)提供了丰富的消费者相关信息和资源。您可以在该网站上找到有关华为产品、应用程序开发、技术文档和工具等方面的内容。请访问developer.huawei.com/consumer/cn以获取更多详细信息。
作者:fundroid 链接:https://juejin.cn/post/6984588418554527774 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
还木有评论哦,快来抢沙发吧~