第3章:SplitInstall请求构建与参数调优
动态交付请求的构建质量直接决定模块下载的成功率、安装时效性和用户体验。本章围绕 InstallRequest 的核心构建流程,深入剖析语言/地区条件、延迟选项、回调监听、超时设置四项关键参数的调优策略,并结合调试手段与常见错误案例,提供可直接落地的稳定性提升方案。
3.1 InstallRequest 构建原理与流程
SplitInstallRequest 是动态交付的请求载体,开发者通过 Builder 模式装配模块标识和条件约束。请求构建分为四个阶段:
- 模块指定:通过
addModule()添加一个或多个特性模块名。 - 条件注入:语言、地区、延迟策略等过滤条件在 Builder 中注册。
- 回调注册:绑定
SplitInstallStateUpdatedListener监听全程状态。 - 超时绑定:通过
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()验证模块已存在,避免重复请求。
3.7 常见错误与稳定性优化
| 错误代码 | 原因 | 优化措施 |
|---|---|---|
ERROR_INVALID_REQUEST | 模块名不存在或条件冲突 | 校验模块配置,避免同时设置互斥条件 |
ERROR_ACCESS_DENIED | 语言/地区不匹配 | 回调中判断后降级或提示用户切换 |
ERROR_TIMEOUT | 请求超时未完成 | 重试时增加指数退避;检查网络及存储 |
ERROR_SESSION_NOT_FOUND | 会话因超时被清除 | 重新构建请求并设置更短的超时 |
稳定性最佳实践:在构建
InstallRequest 之前,先通过 SplitInstallManager 的 getSessionState() 检查当前是否有活跃会话;若有则取消旧会话或复用,避免并发冲突。同时建议将请求参数的构建封装为工厂方法,统一超时、条件和回调策略,便于线上动态配置。