按错误类型处理
| 错误 | 宿主处理 |
|---|---|
REQUEST_ABORTED |
操作取消;结束加载状态,按需读取恢复结果,不显示普通网络失败 |
AUTH_CHANGED |
隐私或账号/token 状态变化;丢弃旧 UI 结果,检查会话并创建新客户端 |
AUTH_EXPIRED |
平台会话失效;重新登录或按平台流程刷新 |
CLOUD_BUSY、SHOP_BUSY |
存在冲突任务;等待当前操作结束后刷新,不循环发起变更 |
NAVIGATION_ACTIVE |
当前导航不允许切车或移除车辆;先结束导航 |
NETWORK_ERROR、REQUEST_TIMEOUT |
状态可能未知;查询与恢复后再决定是否重试 |
RELEASE_PENDING |
先处理待完成的近场撤权,不能覆盖它开始新的绑定 |
2901 |
绑定挑战或版本冲突;重新查询授权状态,不盲目重复提交旧挑战 |
LEGACY_SCOPE_REQUIRED, LEGACY_SCOPE_CONFLICT |
旧记录待认领或已归属其他环境;先按升级说明核实来源,禁止自动认领 |
HTTP 请求使用 HTTPS,基址包含 /api/v1,SDK 自行追加 /app/...,不跟随重定向。保留服务端错误码与 HTTP 状态用于诊断,不将所有失败统一解释成“蓝牙不可用”。
取消与恢复
调用取消后等待最终回调,避免在互斥任务未结束前提交新任务。取消不是事务回滚:绑定、解绑和支付都可能已被远端确认。恢复应以服务端和终端状态为准。
不要自动重放控车、重新发起支付或用新购买 UUID 重试未知结果。避免在多个页面分别管理同一设备流程;使用一个业务协调入口管理当前账号、目标车辆与操作生命周期。
发布前检查
| 范围 | 必须确认 |
|---|---|
| 应用登记 | 正确的 clientId、厂家范围、API 环境与已启用服务 |
| 隐私与权限 | 同意前不启用相关能力;拒绝、撤回和重新授权流程可完成 |
| 车辆 | 首次/重复配对、PIN 错误、取消、车辆切换、解绑与账号切换 |
| 连接 | 蓝牙与热点拒绝/断开/重连后,认证状态与目标车辆仍一致 |
| 商城 | 不匹配厂家被拒绝、地址/价格变化重新报价、重复点击不重复下单 |
| 支付 | 冷启动与回前台 URL、取消与超时恢复、服务端查单,未确认结果不标记到账 |
| 生命周期 | 后台/前台、进程重启、token 更新、导航中的切车限制 |
| 二进制与签名 | 正确的平台包与版本、宿主签名、系统能力、第三方许可 |
在真实手机与已适配终端上验证这些路径。模拟器、编译成功、安装成功和云接口返回成功分别证明不同环节,不能替代真实控车与支付验收。
诊断信息
向平台反馈 SDK 版本、系统版本、动作名称、错误码、发生时间与可复现步骤,说明是否换过账号、车辆或网络。日志脱敏,避免收集 token、PIN、Wi-Fi 密码、设备凭据、完整个人地址或签名支付参数。
接入包和应用登记问题请联系平台。仪表固件与 FreeRTOS 问题请转到硬件 SDK 文档。
回调中的错误分流示例
以下示例把错误码交给宿主 UI 决策,不直接重放请求。把返回的回调传给 list 等云操作;onValue 接收当前操作的成功结果,onFailure 结束加载并选择提示、登录或查询恢复。宿主仍需核对操作代次。
import net.oou.mobile.ResultCallback
enum class FailureAction {
CANCELLED, RECREATE_SESSION, SIGN_IN, WAIT_FOR_ACTIVE,
QUERY_AND_RECOVER, INSPECT_BUSINESS_ERROR
}
fun cloudCallback(
onValue: (Any?) -> Unit,
onFailure: (FailureAction, String) -> Unit
): ResultCallback = object : ResultCallback {
override fun resolve(value: Any?) = onValue(value)
override fun reject(code: String, message: String?, cause: Throwable?) {
val action = when (code) {
"REQUEST_ABORTED" -> FailureAction.CANCELLED
"AUTH_CHANGED" -> FailureAction.RECREATE_SESSION
"AUTH_EXPIRED" -> FailureAction.SIGN_IN
"CLOUD_BUSY", "SHOP_BUSY" -> FailureAction.WAIT_FOR_ACTIVE
"NETWORK_ERROR", "REQUEST_TIMEOUT" -> FailureAction.QUERY_AND_RECOVER
else -> FailureAction.INSPECT_BUSINESS_ERROR
}
onFailure(action, code)
}
}
