本页内容 按错误类型处理取消与恢复发布前检查诊断信息回调中的错误分流示例
APP SDK / Android · iOS

错误处理与发布检查

按错误类型处理取消、会话变化和业务冲突,检查真机权限、支付回调与交付配置。

按错误类型处理

错误 宿主处理
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)
    }
}