Android Dynamic Delivery是Google在2018年推出的一种应用交付机制,它允许开发者将应用拆分为多个模块,Google Play根据设备配置和用户需求动态组合并分发这些模块。传统APK将所有功能打包在一个文件中,而Dynamic Delivery则基于Android App Bundle(AAB)格式,将应用拆分为基础模块和多个动态功能模块。基础模块包含应用启动必需的核心代码,动态功能模块则包含可选功能,例如登录、支付、AR滤镜等。用户安装应用时只需下载基础模块,其他模块按需获取,从而显著减小初始下载体积,提高安装转化率。

要理解Dynamic Delivery,必须先了解App Bundle与APK的区别。传统APK是一个完整的安装包,包含所有资源和代码,无论用户是否需要某些功能。App Bundle则是一种发布格式,开发者上传AAB文件到Google Play,Play根据用户设备的屏幕密度、CPU架构、语言等条件,仅生成并交付该设备所需的APK组件。Dynamic Delivery在此基础上更进一步,允许将某些功能模块从基础APK中剥离,变成可独立下载的模块。这些模块可以配置为安装时交付、按需交付或条件交付,开发者通过Play Core Library在运行时请求和安装模块。
Dynamic Delivery的核心机制与模块类型
Dynamic Delivery支持三种主要的交付方式:安装时交付、按需交付和条件交付。安装时交付的模块在用户首次安装应用时随基础模块一同下载,适合核心功能或使用频率极高的功能。按需交付的模块仅在用户实际触发相关功能时才下载,适合可选功能或付费功能。条件交付则根据设备条件(如国家、API级别、设备特性)在安装时决定是否包含该模块,适合针对特定市场或设备的功能。开发者需要在模块的AndroidManifest.xml中声明模块类型,并通过Gradle配置模块的交付行为。
在工程结构上,动态功能模块与普通库模块类似,但需要在build.gradle中应用com.android.dynamic-feature插件,并指定dist:module属性。以下是一个动态功能模块的构建配置示例:
// 动态功能模块的 build.gradle
apply plugin: 'com.android.dynamic-feature'
android {
compileSdk 34
defaultConfig {
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0"
}
// 动态模块声明
dynamicFeatures = []
}
dependencies {
implementation project(":app") // 依赖基础模块
implementation 'androidx.core:core-ktx:1.12.0'
}
还需要在模块的AndroidManifest.xml中通过<dist:module>标签声明交付属性,例如设置dist:onDemand="true"表示按需交付,设置dist:title为模块显示名称。同时必须在基础模块的AndroidManifest.xml中声明所有动态模块的包名,否则Google Play无法识别模块间的依赖关系。
实现按需交付:Play Core Library详解
按需交付是Dynamic Delivery最常用的场景。开发者通过Play Core Library中的SplitInstallManager类来请求和管理动态模块的安装。首先需要在项目中添加依赖:
// 基础模块的 build.gradle
dependencies {
implementation 'com.google.android.play:core:1.10.3'
// 如果使用Kotlin,可以使用 play:core-ktx
implementation 'com.google.android.play:core-ktx:1.8.1'
}
然后获取SplitInstallManager实例,并检查目标模块是否已安装。以下代码演示了请求并按需安装一个名为“camera”的动态模块:
// 获取 SplitInstallManager
SplitInstallManager splitInstallManager = SplitInstallManagerFactory.create(context);
// 检查模块是否已安装
if (splitInstallManager.getInstalledModules().contains("camera")) {
// 模块已安装,直接使用
launchCameraFeature();
} else {
// 创建请求
SplitInstallRequest request = SplitInstallRequest.newBuilder()
.addModule("camera")
.build();
// 开始安装
splitInstallManager.startInstall(request)
.addOnSuccessListener(sessionId -> {
// 安装请求已提交,等待完成
})
.addOnFailureListener(exception -> {
// 处理错误,如网络问题、用户取消等
});
}
安装过程是异步的,需要注册状态监听器来跟踪进度。当模块安装完成后,需要重启应用或动态加载代码。Android支持通过SplitCompat在运行时加载已安装但未在启动时加载的模块。在Application类中调用SplitCompat.install(this),并在Activity中使用SplitCompat.install(this)确保模块中的Activity能够被找到。另外,还可以使用PlayCore.splitcompat库处理模块间的资源合并。
条件交付的配置则在dist:module标签内添加<dist:conditions>子标签,例如指定<dist:device-feature dist:name="android.hardware.camera.ar" />表示仅当设备支持AR功能时包含该模块。条件交付模块在Play Store生成APK时被自动合并,开发者无需在运行时代码中处理。
开发注意事项与常见问题规避
模块化架构带来了灵活性,但也带来了一系列挑战。首先是模块间依赖管理:动态模块不能反向依赖基础模块的私有资源,只能依赖基础模块的公共API。所有跨模块的通信应通过接口或反射实现,或者使用依赖注入框架(如Hilt)的组件隔离。资源命名冲突是另一个常见问题,建议为每个模块的资源添加前缀,避免合并时覆盖。
测试动态交付比测试普通APK复杂得多。本地无法直接模拟Google Play的按需下载过程,需要将App Bundle上传到Play Console的内部测试轨道,然后通过测试链接安装。调试时可以使用bundletool工具从AAB生成特定设备配置的APK集,并模拟安装模块。此外,按需模块的体积应控制合理,因为下载过程需要用户等待,过大的模块会导致体验下降。最佳实践是将大功能拆分为多个小模块,或将不常用的资源放在云端而不是打包在模块中。
还应注意版本兼容性:Dynamic Delivery要求设备运行Android 5.0(API 21)及以上,但Play Core Library支持旧版本。如果应用需要支持更低版本,则需要回退到传统APK发布方式。另外,使用按需交付时,用户可能拒绝安装模块(例如设备存储不足、网络不稳定),开发者必须优雅处理安装失败,提供重试机制和必要的提示,避免应用崩溃。最后,不要忘记处理模块卸载后的状态:用户可能在系统设置中清除应用数据,导致模块被移除,此时需要重新请求模块。
总结而言,Android Dynamic Delivery是现代化应用架构的重要组成部分。合理使用动态交付能够将应用初始体积降低30%以上,显著提升安装率和用户留存。但开发者需要提前规划模块边界,设计清晰的依赖关系和资源管理策略,并充分测试不同设备条件下的交付行为。随着Google不断优化Play Store的交付能力,掌握Dynamic Delivery将成为Android开发者的必备技能。
Android Dynamic DeliveryApp Bundle动态交付修改时间:2026-08-29 03:30:50