接口参考¶
本页记录当前语音助手向设备内应用开放的 gRPC 与用户信息 Provider,以及维护者使用的内部业务事件。字段以当前源码为准;内部 ChatEvent 不是稳定的跨进程 JSON 协议。
接口位置与数据流¶
| 契约 | 工程中的定位路径 |
|---|---|
| Omni Proto | core/grpc-server/src/main/proto/OmniAgentProto.proto |
| 用户信息字段 | data/src/main/java/com/jidouauto/voiceassistant/data/provider/user/UserSessionContract.kt |
| 内部业务事件 | domain/src/main/java/com/jidouauto/voiceassistant/domain/dialogue/entity/ChatEvent.kt |
以上是工程内的代码定位路径,公开文档站不包含 Android 源码。使用 Proto 时从配套工程版本取得文件,并与 Launcher 端协商同步。
flowchart LR
SDK[SDK 与后端结果] --> Event[ChatEvent]
Event --> Broadcast[GrpcEventBroadcaster]
Event --> Dispatch[AppCtrlDispatcher]
Broadcast --> Push[ServerPushMessage / ToolsConfirmToast]
Dispatch --> Ctrl[AppCtrlRequest]
Push --> Launcher[Omni Launcher]
Ctrl --> Launcher
Launcher --> Reply[AppCtrlResponse]
Account[登录会话存储] --> Provider[UserProvider]
Provider --> App[设备内接入应用]
Omni RPC 一览¶
包名为 omniagent,Java 包为 com.jidouauto.omni.agent.grpc,使用 proto3,服务名称为 OmniAgentService。
| RPC | 请求 → 响应 | 当前用途 |
|---|---|---|
StartOmniAgent |
Empty → SimpleResponse |
更新内部运行标记 |
StopOmniAgent |
Empty → SimpleResponse |
更新内部停止标记 |
QueryOmniAgentStatus |
Empty → AgentStatusResponse |
查询内部 Agent 状态 |
SubscribeServerStream |
StreamSubscription → 流式 ServerPushMessage |
接收文本、UI 状态、心跳等 |
ToastStream |
流式 ConfirmResponse → 流式 ToolsConfirmToast |
通知/确认与动作卡片 |
AppCtrl |
流式 AppCtrlResponse → 流式 AppCtrlRequest |
应用控制与回执 |
SyncDemoMode |
DemoModeRequest → SimpleResponse |
当前记录模式参数,尚未实际切换 |
SimpleResponse 包含 success、msg_string、error_code。Start/Stop 正常成功时错误码为 0,控制器返回失败时为 1,RPC 捕获异常时为 -1。这些方法成功不代表真实语音会话已经启动或停止。
AgentStatusResponse 包含 status 和毫秒时间戳 timestamp;查询异常时返回 AGENT_STATUS_UNKNOWN。当前服务端构造的消息时间戳采用 System.currentTimeMillis()。
订阅与推送¶
StreamSubscription 字段 |
Proto 类型 | 当前语义 |
|---|---|---|
client_id |
string |
稳定客户端标识,空值自动生成 |
subscribed_types |
repeated StreamType |
协议约定空列表订阅全部;当前实现未过滤 |
max_reconnect_attempts |
optional int32 |
已定义,当前服务端未使用 |
heartbeat_interval |
optional int32 |
协议单位秒,当前服务端固定 30 秒 |
ServerPushMessage 使用 oneof message_type,一次只携带一种消息;外层还有 timestamp = 10 和 message_id = 11。
| oneof 字段 | 编号 | 类型与用途 |
|---|---|---|
chat_text |
1 | ChatTextStream,用户或 AI 文本 |
tts_audio |
2 | TTSAudioStream,PCM;当前关闭推送 |
tts_event |
3 | TTSCtrlEvent,播控事件 |
cabin_tags |
4 | CabinTags,JSON 标签;协议已定义 |
heartbeat |
5 | Heartbeat,含 timestamp 与 client_id |
error |
6 | StreamError |
vad_event |
7 | VADEvent,协议保留的辅助事件 |
agent_status |
8 | AgentStatus,内部状态 |
assistant_state |
12 | AssistantState,Launcher UI 状态 |
StreamType 编号为 CHAT_TEXT=0、TTS_AUDIO=1、TTS_CONTROL=2、CABIN_TAGS=3、VAD_EVENT=4、AGENT_STATUS=5、ASSISTANT_STATE=7;不要自行把编号间隙补齐。
AssistantState 依次为 IDLE 0、LISTENING 1、THINKING 2、SPEAKING 3,完整枚举名带 ASSISTANT_STATE_ 前缀。AgentStatus 依次为 UNKNOWN 0、RUNNING 1、STOPPED 2、THINKING 3、REJECTED 4、BUSY 5、WORKING 6,前缀为 AGENT_STATUS_。
文本、音频与错误¶
| 消息 | 关键字段 |
|---|---|
ChatTextStream |
type、text、chat_id、message_id、is_final、sequence |
TTSAudioStream |
pcm_data、sample_rate、channels、bits_per_sample、is_last_chunk、chunk_index |
StreamError |
error_code、error_message、stream_type、message_id、should_reconnect |
文本角色为 CHAT_TEXT_TYPE_AI=0、CHAT_TEXT_TYPE_USER=1;sequence 当前保留,不能依赖它排序。外层消息标识和文本内层消息标识是两个字段,客户端不能假设每个增量都有不同标识。
TTSCtrlEvent 为 START 0、STOP 1、PAUSE 2、RESUME 3,前缀为 TTS_CTRL_。PCM 字段存在不等于当前有音频推送;本地语音助手是当前播报端。
当前业务错误广播设置通用提示和 should_reconnect=true;其他错误字段未完整赋值。不要把默认 error_code=0 当成“没有错误”,应先检查 oneof 是否为 error,也不要将业务错误直接当作长连接必须永久终止的信号。
AppCtrl 与通知字段¶
AppCtrlRequest 包含 app_id、request_id、command、parameters,并在 text_input、binary_data、json_data 中通过 oneof 选择一种负载。当前调度主要使用 APP_CTRL_START、APP_CTRL_INPUT。
AppCtrlCommand |
编号 |
|---|---|
APP_CTRL_START |
0 |
APP_CTRL_STOP |
1 |
APP_CTRL_RESTART |
2 |
APP_CTRL_INPUT |
3 |
APP_CTRL_GET_STATE |
4 |
AppCtrlResponse 包含 type、request_id、app_id、success、message、data。类型为 APP_CTRL_RSP_BY_REQ=0、APP_CTRL_RSP_BY_APP_STATE_CHANGED=1、APP_CTRL_RSP_BY_APP_MSG=2。按请求回执必须携带原 request_id。
ToolsConfirmToast 的通用字段包括工具类型、通知类型、toast_id、timeout_ms、title、message、choices、default_choice_index、确认/取消按钮文字、icon_url、extras 和 elicitation_ui_json_str。
ConfirmResponse 用 toast_id 关联通知,携带 confirmed、response_time、selected_option、user_input、extras。协议定义了确认回执通道;当前主要业务动作卡片为 NOTIFY,不能据此假定所有交互式确认均已完成业务闭环。
ToastType 包含 OK_ONLY、OK_CANCEL、NOTIFY、CHOICE、INPUT、ELICITATION,编号依次为 0..5,前缀为 TOAST_TYPE_。具体卡片扩展字段和导航回执示例见 Omni 接入。
用户登录信息 Provider¶
Provider 是只读查询入口,当前没有提供跨应用登录、登出或令牌刷新接口。
| 项目 | 当前值 |
|---|---|
| Authority | com.jidouauto.voiceassistant.provider |
| 查询 URI | content://com.jidouauto.voiceassistant.provider/user/current |
| MIME | vnd.android.cursor.item/vnd.tech.jidouauto.current_user |
user_id |
字符串,来自登录结果 relateSign |
user_phone |
字符串,来自登录结果 userMobile |
| 已登录结果 | 存在登录结果且 accessToken 非空时,返回一行 |
| 未登录结果 | 返回包含列定义的空 Cursor |
权限与返回值
当前主 Manifest 将 Provider 设置为 exported=true,未声明专用 readPermission。历史资料中的 READ_USER_SESSION 是条件性接入示例,不是当前必需权限。Provider 不返回 access token;调用方也不要将空 Cursor 当成网络或权限错误。
当前 query() 不使用传入的 projection、selection 或 sortOrder,始终返回两列。未知 URI 抛出 IllegalArgumentException。insert() 返回 null,update() 与 delete() 返回 0,不会修改登录态。
Android 接入示例¶
Android 11 及以上,在接入方 Manifest 中声明 Provider 可见性:
以下函数应在 IO 线程调用;无用户返回 null,Provider 不可用或权限错误向上抛出,由调用方呈现读取失败。
data class CurrentUser(val userId: String, val userPhone: String)
fun queryCurrentUser(resolver: ContentResolver): CurrentUser? {
val uri = Uri.parse(
"content://com.jidouauto.voiceassistant.provider/user/current",
)
val cursor = checkNotNull(resolver.query(uri, null, null, null, null)) {
"用户信息 Provider 不可用"
}
return cursor.use {
if (!it.moveToFirst()) return@use null
CurrentUser(
userId = it.getString(it.getColumnIndexOrThrow("user_id")),
userPhone = it.getString(it.getColumnIndexOrThrow("user_phone")),
)
}
}
在所需生命周期内注册 ContentObserver,监听查询 URI,或监听 authority 根 URI 并设置 notifyForDescendants=true。回调仅通知数据变化,收到后重新在 IO 线程查询;在生命周期结束时注销。
UserSessionStore.saveLoginResult()、updateAccessToken() 和 clearSession() 在同步持久化数据后通知查询 URI。不要仅监听前台页面,否则切到登录页时注销观察者可能错过变更;多用户车机应确保双方位于同一 Android user。
验证与故障定位¶
adb shell am get-current-user
adb shell content query --user current --uri content://com.jidouauto.voiceassistant.provider/user/current
查询可能输出真实用户信息,只在授权测试设备执行,不要将输出原样放入公开问题、文档或截图。公开验证记录仅保留“零行/一行”和列名。
| 现象 | 应检查的事实 |
|---|---|
| 找不到 Provider | 安装状态、authority、包可见性、Android user |
| 返回空 Cursor | 是否存在已保存登录结果且 token 非空 |
| 能查询但页面不更新 | Observer 生命周期、监听 URI、登录态保存/清除通知 |
| 安全异常 | 当前设备实际安装包的合并 Manifest 与调用方权限 |
内部业务事件¶
ChatEvent.Business.Result 包含 processType、message、data、id、functionName、showOnUi、pendingCommands。
processType决定业务处理路径;data是内部对象,当前类型为Any?,不能直接当成固定对外 JSON。showOnUi=false控制业务结果文字展示,不表示无需执行命令,也不表示必须禁止动作卡片。pendingCommands承载后续执行的命令,实际执行时机由调度器的业务分支决定。StreamingDelta.incrementalContent是增量文本;fullMessage为可选完整文本,当前 gRPC 广播使用增量字段。GRPC_NOTIFY的command_result是内部调度完成信号,不是支付、导航或车控成功凭证。
验证接口变更时至少覆盖 Proto 编解码、文本 final 更新、AppCtrl 原标识回执与超时、Provider 空行与登录通知。更多场景见调试与维护。