启动与恢复
隐私同意和平台会话准备好后,先执行 recover,补交 SDK 保存的待确认结果,再执行 list 获取云端车辆。cached 仅用于展示,不能作为当前授权或绑定状态的依据。恢复失败时按错误类型提示或重试,不要删除恢复记录来绕过失败。
Android 可使用类型化方法或 execute(action, parametersJson, callback);iOS 使用 execute:parameters:resolve:reject:。下表是两端共用的云操作名,参数均为对象。
| action | 参数与用途 |
|---|---|
recover、list、cached |
空对象;恢复、云列表、缓存列表 |
add |
空对象;进入添加车辆流程 |
bootstrap |
discoveryId,可选 expectedTerminal;获取目标引导授权 |
bind |
terminalId;提交绑定证明并恢复目标连接权限 |
select、report |
vehicleId、deviceId、terminalId;选择车辆或上报已连接终端 |
restoreSelection |
terminalId;取消添加后恢复已有选择 |
clearBootstrap |
空对象;清理临时引导授权 |
release |
terminalId;近场撤销终端授权 |
unbind |
vehicle 为 list 返回的完整条目,含 vehicle.bindingVersion 与 terminals |
authorizePairingRecovery |
terminalId、nonce;返回恢复证明,交设备客户端继续 PIN 恢复 |
adoptLegacy |
空对象;仅核实旧记录来源后认领,见升级说明 |
首次连接
- 保存当前选择,执行
add,然后启动设备扫描。 - 从扫描结果取得
discoveryId,执行bootstrap;已知目标时同时传入expectedTerminal。 - 使用设备客户端配对接口完成安全握手,按真实终端屏幕提示提交 PIN。
- 配对成功后执行
bind;完成云绑定后刷新列表与目标状态。 - 按需要准备并连接目标车辆 Wi-Fi,确认目标
terminalId的认证状态与连接探测结果。 - 成功、失败或取消后清理 bootstrap。保留 SDK 自动保存的待确认回执,后续通过
recover处理。
蓝牙连接、系统配对成功、已连 SSID 和 Wi-Fi 入网回调都不能单独证明车辆业务连接成功。不要在 UI 提前显示“已绑定”或“控车成功”。
选择、取消与解绑
选择已授权车辆使用 select。取消添加时,先停止发现与临时配对、等待旧操作结束,再调用 restoreSelection 恢复原有车辆。每次异步回调核对当前操作和目标,避免上一辆车的迟到结果覆盖当前车辆。
取消调用 cancel(),然后等待 resolve/reject 完成。取消不会回滚终端或服务端已经确认的事实。导航中不应切换或移除车辆,收到 NAVIGATION_ACTIVE 时先让用户结束导航。
release 与 unbind 含义不同:前者撤销近场终端授权,后者通过车辆绑定版本执行云解绑。解绑响应未知时保留相同 bindingVersion 重试;重新登录原账号后由恢复流程完成待处理动作。不要手动清空 pendingReceipt、pendingChallenge 或 pendingUnbind。
控车与状态
根据终端返回的真实能力和用户权限展示按钮。每次明确用户操作只发送一次车辆命令,等待回执;网络重连、界面重建或超时后不能自动重放控车动作。
状态读取与命令回执是不同结果。需要展示执行成功时,使用对应命令的回执和后续有效状态,不用旧缓存推断成功。持续导航、媒体和后台连接还依赖宿主扩展、权限与终端能力。
并发约束
SDK 维护单设备业务会话。绑定、选择、解绑等互斥操作返回 CLOUD_BUSY 时,等待当前操作结束后刷新状态。Android 0.2.1 的同范围列表与恢复请求会合并;每个调用者单独取消自己的结果,不影响其他订阅者。全部取消后,已开始的共享工作仍可运行至完成或超时,以保留已确认回执。其他独占操作期间调用 recover 返回 CLOUD_BUSY,等待操作结束再重试。账号/token 改变后重建客户端。
Android:按顺序恢复与读取
下面的协调器实例只运行一次,在主线程创建、启动和取消;SDK 已配置且平台会话已安装。isCurrent 由宿主核对账号、车辆和页面操作代次;页面退出或会话改变时先使它失效,再调用 cancel()。宿主保留协调器至操作结束。
成功结果交给 result.resolve;失败交给 result.reject,按错误处理决定下一步。取消只撤回当前订阅者的结果,SDK 已开始的共享恢复仍可完成。
import net.oou.mobile.CloudOperation
import net.oou.mobile.CloudVehicles
import net.oou.mobile.ResultCallback
class VehicleRefresh(
private val vehicles: CloudVehicles,
private val isCurrent: () -> Boolean,
private val result: ResultCallback
) {
private var recovery: CloudOperation? = null
private var listing: CloudOperation? = null
private var started = false
private var cancelled = false
private fun current() = !cancelled && isCurrent()
private val listResult = object : ResultCallback {
override fun resolve(value: Any?) {
if (current()) result.resolve(value)
}
override fun reject(code: String, message: String?, cause: Throwable?) {
if (current()) result.reject(code, message, cause)
}
}
fun start() {
check(!started)
started = true
if (!current()) return
recovery = vehicles.recover(object : ResultCallback {
override fun resolve(value: Any?) {
if (current()) listing = vehicles.list(listResult)
}
override fun reject(code: String, message: String?, cause: Throwable?) {
listResult.reject(code, message, cause)
}
})
}
fun cancel() {
cancelled = true
recovery?.cancel()
listing?.cancel()
}
}
