2. SplitInstall SDK 集成与工程配置

SplitInstall 动态交付的核心是 Play Core SDK。正确集成 SDK、配置清单、初始化管理器并处理好版本兼容性,是后续所有功能稳定运行的基石。本章从原理出发,给出无遗漏的工程配置步骤与稳定性规避策略。

2.1 原理:Play Core 在 SplitInstall 中的角色

Google Play Core 库提供了 SplitInstallManager 接口,App 通过它向 Play 商店请求按需模块的下载、安装与状态监听。整个交互流程如下:

  • Gradle 依赖:引入 Play Core 及其 .aab 分包所需插件。
  • AndroidManifest 声明:注册 SplitInstallService 相关权限与组件(自动合并)。
  • 初始化:通过 SplitInstallManagerFactory.create() 获得单例。
  • 版本兼容:确保 compileSdk、minSdk、Play Core 版本、Google Play 商店版本四者匹配。
关键事实:Play Core 从 2.0.0 开始迁移到 Kotlin 协程并移除旧回调 API;2.1.0 + 完全废弃 SplitInstallStateUpdatedListener 接口,必须使用 Task 或 Flow 监听。版本选择直接影响初始化代码的写法。

2.2 实现流程:四步稳定集成

Step 1 — 根项目与 Module 的 Gradle 配置

在项目层 build.gradle 中声明 Play Core 插件(仅用于 .aab 分包签名验证);在 App Module 中添加核心依赖。以下为典型配置(Groovy 语法,KT 同理):

// 项目根 build.gradle
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:8.1.4"
        classpath "com.google.android.play:core:1.10.3"  // Play Core Plugin (可选,用于签名校验)
    }
}

// app/build.gradle
android {
    compileSdk 34
    defaultConfig {
        minSdk 21
        targetSdk 34
    }
    // 启用动态交付
    dynamicFeatures = [":on_demand_feature"]
}

dependencies {
    implementation "com.google.android.play:core-ktx:1.9.1"   // KTX 协程版本
    // 或使用 Java 版: implementation "com.google.android.play:core:1.10.3"
    implementation "com.google.android.play:core-splitinstall:1.0.1" // 部分旧项目需要
}

版本选择建议(2025 年稳定组合):

Play Core 库版本 minSdk 最低要求 推荐 compileSdk 说明
1.8.x (旧版) 21 31+ 仍支持 Listener API,但不再更新
1.9.x ~ 1.10.x 21 33+ 推荐 core-ktx,协程 + Task 混合
2.0.0+ 23 34+ 仅 Kotlin,SplitInstallManager 返回 SplitInstallManagerCompat

Step 2 — AndroidManifest 配置

Play Core 通过 Manifest 合并自动注入必要组件(如 com.google.android.play.core.splitinstall.testing.FakeSplitInstallManagerService),开发者通常只需在 <application> 标签外保留以下配置(用于 Google Play 商店识别):

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 注意:不需要显式申明 INSTALL_PACKAGES,Play Core 内部通过 split APK 安装机制 -->

<application ...>
    <!-- 无额外组件,Play Core 自动合并 -->
</application>

若使用 Test 环境 或 内测 需要 FakeSplitInstallManager,可在 <application> 内添加:

<service
    android:name="com.google.android.play.core.splitinstall.testing.FakeSplitInstallManagerService"
    android:exported="false" />

Step 3 — SplitInstallManager 初始化

推荐在 Application.onCreate() 或 Activity.onCreate() 中一次性初始化,避免多次创建。以下为 Kotlin + KTX 的标准写法:

class MyApplication : Application() {
    lateinit var splitInstallManager: SplitInstallManager
        private set

    override fun onCreate() {
        super.onCreate()
        // 使用 SplitInstallManagerFactory 创建实例
        splitInstallManager = SplitInstallManagerFactory.create(this)

        // 可选:检查是否支持按需下载(判断 Google Play 商店版本)
        if (!splitInstallManager.isDeferredInstallSupported) {
            Log.w("SplitInstall", "设备不支持 deferred install,将回退全量安装")
        }
    }
}
稳定性陷阱:不要在 onCreate() 中调用 startInstall() 等耗时操作,否则可能触发 ANR。初始化仅创建管理器,不发起网络请求。

Step 4 — 版本兼容性检查与适配

运行时务必判断 isDeferredInstallSupported 和 isStagedInstallSupported,对于不支持设备的需提供降级方案。另外,Play Core 2.0+ 的 API 签名与旧版本不兼容,建议在 gradle.properties 中锁定版本:

// gradle.properties
play.core.version=1.10.3

2.3 集成流程图

SplitInstall SDK 集成与初始化流程 1. Gradle 依赖配置 2. AndroidManifest 声明 3. SplitInstallManager 初始化 4. 版本兼容性验证 5. 初始化完成(就绪) 注意:版本兼容检查包括 compileSdk、minSdk、Play Core 版本、Google Play 商店版本四个维度。

2.4 调试与验证方法

  1. Log 输出:初始化后调用 splitInstallManager.sessionStates(返回 Task<Set<SplitInstallSessionState>>),观察状态是否正常。
  2. adb 测试命令(需安卓 21+):
    adb shell am start -n "com.package.yourapp/.TestActivity" --es extra_module "on_demand_feature"
  3. Play Console 内测:上传 .aab 并启用“按需分发”,安装测试版 App 后检查 SplitInstallManager.supportedLanguages 是否返回正确。

2.5 常见错误与解决方案

错误症状 原因 解决
SplitInstallException: -3 (UNAVAILABLE) Google Play 商店版本过旧或设备不支持 调用 isDeferredInstallSupported 检查,降级为全量安装
NoClassDefFoundError: SplitInstallManager 依赖版本冲突或未引入 core-ktx 检查 Gradle 依赖树,统一版本号(如 1.10.3)
Manifest merger failed 重复申明了 FakeSplitInstallManagerService 移除 <application> 内的多余 service
java.lang.IllegalStateException: Single-threaded access required 在后台线程调用了 SplitInstallManager 非线程安全方法 始终在主线程操作 startInstall()、deferredInstall()

2.6 性能与稳定性优化建议

  • 懒初始化:将 SplitInstallManager 创建时机推迟到第一次需要按需加载时(如进入 Activity),减少 Application 启动耗时。
  • 版本锁定策略:在 gradle.properties 中定义 playCoreVersion,所有模块统一引用,避免传递依赖导致版本不一致。
  • 异常兜底:捕获 SplitInstallException 并上报 Crashlytics,但不打断用户主流程。
  • 多进程隔离:若 App 有多个进程,只在主进程初始化 SplitInstallManager,其他进程通过 IPC 获取状态。