第3章:SplitInstall请求构建与参数调优

动态交付请求的构建质量直接决定模块下载的成功率、安装时效性和用户体验。本章围绕 InstallRequest 的核心构建流程,深入剖析语言/地区条件、延迟选项、回调监听、超时设置四项关键参数的调优策略,并结合调试手段与常见错误案例,提供可直接落地的稳定性提升方案。

3.1 InstallRequest 构建原理与流程

SplitInstallRequest 是动态交付的请求载体,开发者通过 Builder 模式装配模块标识和条件约束。请求构建分为四个阶段:

  1. 模块指定:通过 addModule() 添加一个或多个特性模块名。
  2. 条件注入:语言、地区、延迟策略等过滤条件在 Builder 中注册。
  3. 回调注册:绑定 SplitInstallStateUpdatedListener 监听全程状态。
  4. 超时绑定:通过 SplitInstallClient 配置请求级别超时。
设计原则:请求参数应尽量精简,避免添加无意义的条件导致下发过滤;同时所有回调必须在主线程注册,否则 IllegalStateException 会被抛出。

3.2 语言/地区条件配置

Play Core 提供 setLanguage() 和 setRegion() 方法,使动态模块仅在特定语言或地区环境下才被允许下载或触发安装。注意:条件不是过滤,而是“许可” – 若未设置,则所有用户均可获取;若设置,则仅匹配的用户才会在请求中被视为有效。

方法参数类型说明稳定性影响
setLanguage(String)BCP-47 语言标签,如 “zh-CN”限定模块仅对指定语言用户可用减少无效请求,降低带宽浪费
setRegion(String)ISO 3166-1 地区代码,如 “US”限定模块仅对指定地区可用避免跨区域异常分发
clearLanguageConditions()–移除之前设置的所有语言条件用于动态重置
常见错误:同时设置语言和地区条件时,若用户满足语言但不满足地区,请求会被忽略但不会报错,导致下载回调永久卡在 Pending 状态。务必在回调的 onError() 中检查错误码 SplitInstallErrorCode.ACCESS_DENIED。

3.3 延迟选项(Deferred Install)

延迟安装允许模块在后台静默下载,在用户下次重启应用时自动安装。通过 setDeferredInstall() 标记请求为延迟模式。参数调优建议:

  • 延迟 vs 即时:核心功能模块应使用即时请求(默认),非关键资源(如主题包)使用延迟请求以减少前台等待。
  • 网络条件:延迟请求默认仅在 Wi-Fi 下下载,可通过 setRequireCharging(true) 限制充电条件,避免耗电。
  • 批量延迟:多个延迟模块建议合并为一个请求,利用 addModule() 批量添加,减少系统调度开销。

3.4 回调监听与状态机

注册监听器后,SessionState 会依次经历:PENDING → DOWNLOADING → INSTALLING → INSTALLED。监听器必须处理 REQUIRES_USER_CONFIRMATION 状态,调用 showConfirmationDialog() 获取用户授权。

SplitInstallClient client = SplitInstallClientFactory.create(context);
SplitInstallStateUpdatedListener listener = state -> {
    switch (state.status()) {
        case SplitInstallSessionStatus.PENDING:
            log("请求排队中");
            break;
        case SplitInstallSessionStatus.DOWNLOADING:
            log("下载中 " + state.bytesDownloaded() + "/" + state.totalBytesToDownload());
            break;
        case SplitInstallSessionStatus.INSTALLED:
            log("安装完成");
            break;
        case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION:
            state.resolutionIntent().
                addOnSuccessListener(intent -> client.showConfirmationDialog(activity, intent));
            break;
        case SplitInstallSessionStatus.FAILED:
            log("失败: " + state.errorCode());
            break;
    }
};
client.registerListener(listener);
稳定性优化:在 FAILED 回调中,根据 errorCode 决定重试策略。例如 ERROR_NETWORK_ERROR 应等待网络恢复后重试,ERROR_INSUFFICIENT_STORAGE 则通知用户清理空间。

3.5 超时设置与防卡死

Play Core 不提供直接的请求超时 API,但可通过 SplitInstallClient 的 setTimeoutMillis(long) 设置会话超时。建议配置 60 秒,避免长时间占用资源。

SplitInstallClientConfig config = SplitInstallClientConfig.newBuilder()
    .setLanguage(Locale.getDefault().toLanguageTag())
    .setTimeoutMillis(60000)   // 60 秒超时
    .build();
SplitInstallClient client = SplitInstallClientFactory.create(context, config);

若超时后模块仍未完成,会触发 ERROR_SESSION_NOT_FOUND 或 ERROR_TIMEOUT(需结合客户端重试逻辑)。

常见陷阱:不要依赖 SplitInstallClient 的默认超时(可能是无限等待)。必须显式设置超时,并在回调中捕获 SplitInstallErrorCode.ERROR_TIMEOUT 后执行清理与重试。

3.6 调试与部署建议

  • 使用 adb shell am broadcast -a com.google.android.play.core.splitinstall.action.SPLIT_INSTALL 触发测试安装。
  • 在 build.gradle 中设置 splitDimension 的 language 和 region,确保本地测试时条件与正式环境一致。
  • 部署前使用 SplitInstallManager 的 getInstalledModules() 验证模块已存在,避免重复请求。
InstallRequest 构建与参数调优流程图 创建 InstallRequest addModule() + 语言/地区条件 延迟选项 (Deferred Install) 注册 SplitInstallStateUpdatedListener 设置超时 (setTimeoutMillis) startInstall() 参数调优要点 • 语言/地区条件精确过滤 • 延迟选项与网络策略结合 • 超时设为 60s 避免卡死

3.7 常见错误与稳定性优化

错误代码原因优化措施
ERROR_INVALID_REQUEST模块名不存在或条件冲突校验模块配置,避免同时设置互斥条件
ERROR_ACCESS_DENIED语言/地区不匹配回调中判断后降级或提示用户切换
ERROR_TIMEOUT请求超时未完成重试时增加指数退避;检查网络及存储
ERROR_SESSION_NOT_FOUND会话因超时被清除重新构建请求并设置更短的超时
稳定性最佳实践:在构建 InstallRequest 之前,先通过 SplitInstallManager 的 getSessionState() 检查当前是否有活跃会话;若有则取消旧会话或复用,避免并发冲突。同时建议将请求参数的构建封装为工厂方法,统一超时、条件和回调策略,便于线上动态配置。