Android SDK 接入指南(v0.0.7)

一.准备工作

概述

本文是 XingyunAvatarAgent SDK Android 版本的接入文档,用于指导 SDK 的使用方法,默认读者已经熟悉 Android Studio 的基本使用方法,以及具有一定的 Android 编程知识基础。

XingyunAvatarAgent SDK 在具身智能体渲染能力(虚拟人 Lite SDK)的基础上,集成了 E2E 语音对话能力(麦克风采集 → ASR 识别 → LLM 大模型 → 具身智能体自动播报),对外提供统一入口类 XingyunAvatarAgent,一次初始化即可同时获得:

  • 具身智能体渲染 + 播报(内部封装 XmovAvatar 全部能力)
  • 语音对话(ASR 实时识别、LLM 流式回答并自动驱动具身智能体播报)
  • 文本对话(ask 文本提问,LLM 流式回答并自动驱动具身智能体播报)

内部联动逻辑(无需接入方处理):

  • ASR 识别到完整一句话(isFinal=true)→ 具身智能体自动进入 think 状态
  • LLM 流式分片输出 → 自动流式驱动具身智能体 speak 播报
  • interrupt() → 同时打断具身智能体播报与 E2E 会话

快速体验 demo

工程中的 app 模块即示例工程,使用 Android Studio 打开后:

a. 修改 app/src/main/assets/agent_config.json 中的 asrConfig、ttsConfig、brainConfig、features、avatarAppId、avatarAppSecret、avatarGatewayServer 等参数(asrConfig / ttsConfig / brainConfig / features 的值是 JSON 字符串,转义后填入;ttsConfig 默认为空)

b. 直接运行到 Android 手机上体验

开发环境搭建

(1)将开发包拷贝到工程

将 SDK 的 aar 包拷贝到自己工程的 libs 目录下,如没有该目录需新建。

在 app 文件夹下的 build.gradle 的 dependencies 中配置对应版本的 aar 依赖:

implementation files('libs/xingyun_avatar_agent-xxx.aar')

(2)添加外部第三方依赖:

    implementation "com.squareup.okhttp3:okhttp:4.12.0"
implementation "com.google.code.gson:gson:2.13.1"
// Opus 音频编码(语音采集上行)
implementation "io.github.jaredmdobson:concentus:1.0.2"
implementation "javax.vecmath:vecmath:1.5.2"
implementation "org.msgpack:msgpack-core:0.9.3"
implementation "io.socket:socket.io-client:2.1.0"
// Protobuf 依赖
implementation "com.google.protobuf:protobuf-javalite:3.21.12"
// ExoPlayer dependency for WebM/Opus streaming
implementation "androidx.media3:media3-exoplayer:1.9.0"

(3)配置 AndroidManifest.xml 文件

在 manifest 标签内添加必要的权限支持:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

注意RECORD_AUDIO 属于危险权限,调用 startASR() 之前必须先完成运行时权限申请,否则音频采集会失败并通过 onError(domain="audio")回调。

(4)混淆规则:

-keep class com.xmov.xingyunavataragent.XingyunAvatarAgent { public *; }
-keep interface com.xmov.xingyunavataragent.XingyunAvatarAgentListener { *; }
-keep class com.xmov.xingyunavataragent.XingyunAvatarAgentConfig { public *; }
-keep class com.xmov.xingyunavataragent.XingyunAvatarAgentError { public *; }
-keep class com.xmov.xingyunavataragent.LlmUsage { public *; }
-keep class com.xmov.xingyunavataragent.SemanticJudgeResult { public *; }
-keep enum com.xmov.xingyunavataragent.XingyunAvatarAgentState { *; }
-keep public class com.xmov.metahuman.sdk.data.**{*;}
-keep public class com.xmov.metahuman.sdk.impl.data.**{*;}
-keep public class com.xmov.metahuman.sdk.impl.transport.http.**{*;}
-keep public interface com.xmov.metahuman.sdk.PreCacheListener {
public protected *;
}
-dontwarn io.github.jaredmdobson.concentus.OpusApplication
-dontwarn io.github.jaredmdobson.concentus.OpusEncoder
-dontwarn io.github.jaredmdobson.concentus.OpusSignal
-dontwarn io.github.jaredmdobson.concentus.OpusDecoder

通过上面的几个步骤,工程就配置完成了,接下来就可以在工程中使用 XingyunAvatarAgent SDK 进行开发了。

二.SDK 使用说明

1.预缓存

预缓存是提前缓存视频资源或者 charbin 文件资源,可按需调用,不是必须调用的;调用时机在初始化方法之前调用。

(1)预缓存视频

文件较多,需要几分钟时间,大屏常驻设备可提前调用缓存,按需调用。

方法原型

fun preCache(
context: Context,
appId: String,
appSecret: String,
url: String,
listener: PreCacheListener?
)

(2)预缓存 charbin

时间较快,可提前调用,缩短初始化耗时。

fun preCacheCharBin(
context: Context,
appId: String,
appSecret: String,
url: String,
listener: PreCacheListener?
)

参数描述

参数

类型

说明

context

Context

一般传 Activity 或者 applicationContext 对象

appId

String

星云开放平台上创建对应应用角色的 appId

appSecret

String

星云开放平台上创建对应应用角色的 appSecret

url

String

预缓存资源地址

listener

PreCacheListener

回调监听

示例代码

val agent = XingyunAvatarAgent()
agent.preCache(this, appId, appSecret, preCacheUrl, object : PreCacheListener {
override fun onPreCacheProgress(progress: Int) {
runOnUiThread { setLoadingTitle("预缓存中 $progress%") }
}

override fun onPreCacheComplete() {
runOnUiThread { toast("预缓存完成") }
}

override fun onPreCacheFailed(errorCode: Int, errorMessage: String) {
runOnUiThread { toast("预缓存失败: $errorCode $errorMessage") }
}
})

1.进度回调 onPreCacheProgress(progress: Int),progress 范围是 0-100,缓存的进度

2.完成回调 onPreCacheComplete(),缓存完成

3.失败回调 onPreCacheFailed(errorCode: Int, errorMessage: String)

2.初始化

使用 SDK 功能前,必须先进行初始化操作。初始化会同时完成:

  1. 具身智能体渲染管线初始化(进房、加载资源、渲染首帧)
  2. 具身智能体就绪后自动建立 E2E 语音对话连接

E2E 连接建立成功后回调 onStateChanged(CONNECTED),此后即可调用 startASR / ask 等对话接口。

方法原型

fun init(
context: Context,
layout: ViewGroup,
config: XingyunAvatarAgentConfig,
listener: XingyunAvatarAgentListener
)

参数描述

参数

类型

说明

context

Context

一般传 Activity 对象

layout

ViewGroup

加载具身智能体所在的父布局

config

XingyunAvatarAgentConfig

统一配置类(包含 E2E + 具身智能体参数)

listener

XingyunAvatarAgentListener

统一回调监听

XingyunAvatarAgentConfig 类介绍

主配置类

参数

类型

必填

说明

asrConfig

String?

ASR 配置 JSON 字符串(原样透传到服务端 asr_config),默认 null

ttsConfig

String?

TTS 配置 JSON 字符串(原样透传到服务端 tts_config),默认 null,由服务端取默认 TTS 配置

brainConfig

String?

Brain/LLM 配置 JSON 字符串(原样透传到服务端 brain_config),默认 null

features

String?

特性开关配置 JSON 字符串(原样透传到服务端 features),默认 null

sessionSpeakReqId

Int

说话请求计数器,默认 1

avatarAppId

String

星云具身中应用对应的 appId

avatarAppSecret

String

星云具身中应用对应的 appSecret

avatarGatewayServer

String

进入房间的地址,如 "https://nebula-agent.xingyun3d.com/user/v1/ttsa_v2/session"

avatarInitConfigJson

String

具身智能体初始化 JSON 配置,默认 "{}"(字段含义与虚拟人 Lite SDK 的 config 完全一致,详见 Lite SDK 接入文档"config 配置"章节)

audioInputInitiallyOff

Boolean

连接建立后音频输入是否保持关闭,默认 true

debugLogEnabled

Boolean

SDK 内部调试日志开关,默认 false

extras

String?

预留扩展 JSON 字符串,原样透传到 startSession 请求体中(与 asr_config / features 同级)

注意asrConfig / ttsConfig / brainConfig / features / extras 均为 JSON 字符串,SDK 只原样透传,不解析、不校验。字段名采用下划线命名(如 base_urlenable_aec),具体格式见下方"配置 JSON 示例"。


已废弃hostuserTokensessionId 三个字段已不再使用。E2E 会话的 token 和 ws_url 现在由具身智能体 startSession 接口在响应的 data.e2e_resp 中直接返回,SDK 内部自动提取,无需接入方单独配置。

配置 JSON 示例(asrConfig / brainConfig / features 的值格式)

{
"asr_config": {
"provider": "doubao",
"base_url": "wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async",
"api_key": "your-api-key",
"model": "bigmodel",
"headers": {
"access_token": "your-access-token",
"app_id": "your-app-id",
"resource_id": "volc.bigasr.sauc.duration",
"secret_key": "your-secret-key"
},
"request": {
"model_name": "bigmodel",
"model_version": "400",
"result_type": "full",
"enable_itn": true,
"enable_punc": true,
"show_utterances": true
}
},
"brain_config": {
"provider": "doubao",
"base_url": "https://ark.cn-beijing.volces.com/api/v3",
"api_key": "your-api-key",
"model": "your-model-id",
"preset": "你是一个简洁的助手。",
"history_length": 5
},
"features": {
"anti_interference": {
"semantic_judge_enabled": false
},
"speech_frontend": {
"enabled": true,
"enable_aec": true,
"enable_speech_separation": true
},
"vad_merge_mode": true,
"volume_and_repetition_text_detection": true
}
}

asrConfig 字段说明(原样透传到服务端 asr_config

字段

类型

必填

说明

provider

string

ASR 服务商,支持 xmov / doubao / tencent

base_url

string

ASR WebSocket 地址

headers

object

ASR 鉴权字段:doubao 为 resource_id / access_token / app_id;xmov 为 app_id / secret_key

request

object

ASR 请求参数(如 end_window_sizevad_tail_sil),字段随 ASR 服务商协议而定,具体含义以服务商文档为准

brainConfig 字段说明(原样透传到服务端 brain_config

字段

类型

必填

说明

provider

string

LLM 服务商,支持 openai_compatible / anthropic / youling / coze / dify / doubao / qwen / youyan_agent / openai / deepseek

base_url

string

LLM API 地址

api_key

string

LLM API key;缺失、为空或仅含空白字符时服务端返回 HTTP 400

model

string

模型名称 / 模型 ID

preset

string

系统提示词;可省略或传空字符串,为空时不生成 system message

history_length

int

历史轮数,默认 5

extra_body

object

直连模型 provider 的原生请求扩展参数,默认 {}model / messages / stream / stream_options 由服务端管理,客户端值不生效;youling / coze / dify 不接受该字段,非空时返回 HTTP 400

注意:普通 Brain 由服务端按 history_length 维护并发送历史;youling / coze / dify 使用各自服务端会话(E2EMPServer 不重发本地历史),系统提示词由对应平台配置管理。

features 字段说明(原样透传到服务端 features

字段

类型

必填

说明

vad_merge_mode

bool

VAD 合并模式,默认 true

volume_and_repetition_text_detection

bool

音量与重复文本检测总开关,默认 true

anti_interference.semantic_judge_enabled

bool

语义判定开关,默认 false

speech_frontend.enabled

bool

SF 降噪桥接开关,默认 false

speech_frontend.enable_aec

bool

回声消除与降噪统一开关,连接前确定,默认 false

speech_frontend.enable_speech_separation

bool

人声分离开关

auto_send_asr_to_llm

bool

远端发送 ASR 结果给大模型,默认 true

注意features 为可选、可部分提供的对象,服务端按「代码默认值 → 服务端数据库 dict_config → 本次请求 features」递归合并:显式传入的 false / 0 会覆盖数据库值,省略的字段不覆盖,具体默认是否开启以服务端配置为准。speech_frontend 下还支持 ws_urlfixed_chunk_enabledchunk_samplessample_ratews_max_size 等服务端参数;anti_interference 下还支持音量阈值、重复文本相似度、次数、位置、时间窗口、相似度算法等参数(字段名以服务端数据库 dict_config 配置为准)。

实际接入时把对应片段转成 JSON 字符串填入 asrConfig / brainConfig / features 参数(可直接参考 demo 的 app/src/main/assets/agent_config.json)。

初始化示例代码

val agent = XingyunAvatarAgent()

agent.init(
this,
mBinding.avatarLayout,
XingyunAvatarAgentConfig(
// 以下均为 JSON 字符串,原样透传给服务端(格式参考上方"配置 JSON 示例")
asrConfig = """{"provider":"doubao","base_url":"wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async","headers":{"access_token":"your-access-token","app_id":"your-app-id","resource_id":"volc.bigasr.sauc.duration","secret_key":"your-secret-key"},"request":{"model_name":"bigmodel","model_version":"400","result_type":"full","enable_itn":true,"enable_punc":true,"show_utterances":true}}""",
brainConfig = """{"provider":"doubao","base_url":"https://ark.cn-beijing.volces.com/api/v3","api_key":"your-api-key","model":"your-model-id","preset":"你是一个简洁的助手。","history_length":5}""",
features = """{"anti_interference":{"semantic_judge_enabled":false},"speech_frontend":{"enabled":true,"enable_aec":true,"enable_speech_separation":true},"vad_merge_mode":true,"volume_and_repetition_text_detection":true}""",
avatarAppId = "your-app-id",
avatarAppSecret = "your-app-secret",
avatarGatewayServer = "https://nebula-agent.xingyun3d.com/user/v1/ttsa/session",
debugLogEnabled = true,
),
object : XingyunAvatarAgentListener {

// ===== E2E 语音对话回调 =====

override fun onStateChanged(state: XingyunAvatarAgentState) {
Log.d(TAG, "state -> $state")
// state == CONNECTED 后即可调用 startASR() / ask()
}

override fun onAsrResult(text: String, isFinal: Boolean) {
// 实时识别字幕;isFinal=true 表示一句话识别结束
tvSubtitle.text = "我:$text"
}

override fun onLlmChunk(text: String, isFirst: Boolean) {
// LLM 流式回答分片;isFirst=true 表示本轮回答的首个分片
// 具身智能体播报由 SDK 内部自动驱动,此处只需处理字幕展示
if (isFirst) llmSubtitle.clear()
llmSubtitle.append(text)
tvSubtitle.text = llmSubtitle.toString()
}

override fun onLlmDone(usage: LlmUsage) {
Log.d(TAG, "LLM done: $usage")
}

override fun onError(error: XingyunAvatarAgentError) {
Log.e(TAG, "ERROR: $error")
}

// ===== 具身智能体回调(均有默认空实现,按需重写) =====

override fun onInitEvent(code: Int, message: String?) {
Log.d(TAG, "avatar init: code=$code $message") // code=4000 成功
}

override fun onAvatarStateChange(state: String) {
Log.d(TAG, "avatar state: $state")
}

override fun onSpeakStateChange(speakState: String, clientSpeakId: String, errorMsg: String) {
Log.d(TAG, "speak: $speakState $errorMsg")
}

override fun onAvatarReconnectEvent(code: Int, message: String?) {
Log.d(TAG, "avatar reconnect: code=$code $message")
}

override fun onOfflineEvent() {
Log.d(TAG, "avatar offline")
}

override fun onSDKRuntimeError(code: Int, message: String?) {
Log.e(TAG, "avatar runtime error: code=$code $message")
}
},
)

回调线程说明:除 onAudioData 外,XingyunAvatarAgentListener 的其余回调统一在主线程执行,可直接操作 UI。onAudioData 在 SDK 专用后台线程回调(高频音频大包,避免阻塞主线程),如需更新 UI 请自行 runOnUiThread;回调积压超过阈值时 SDK 会丢弃中间帧只保最新。

3.语音对话(ASR)

3.1 开始语音识别

打开麦克风采集并开始 ASR 实时识别。识别文本通过 onAsrResult 回调;一句话识别结束(isFinal=true)后自动送入 LLM,回答通过 onLlmChunk 流式回调并自动驱动具身智能体播报。

调用前提:状态已为 CONNECTED,且已授予 RECORD_AUDIO 权限。

方法原型

fun startASR()

示例代码

if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.RECORD_AUDIO), REQUEST_RECORD_AUDIO,
)
return
}
agent.startASR() // 成功后 onStateChanged(LISTENING)

3.2 停止语音识别

关闭麦克风采集,停止 ASR 识别。

方法原型

fun stopASR()

示例代码

agent.stopASR()    // 成功后 onStateChanged(CONNECTED)

注意stopASR()异步收尾——SDK 会在后台完成采集/编码/发送的收尾(通常几十毫秒,积压时可能几百毫秒),收尾完成后才回调 onStateChanged(CONNECTED);收尾期间再次调用 startASR() 会被忽略,请等待回到 CONNECTED 后再操作。

4.文本对话(ask)

文本提问,走 LLM 大模型,回答通过 onLlmChunk 流式回调并自动驱动具身智能体播报。

调用前提:状态为 CONNECTEDLISTENING

方法原型

fun ask(text: String)

参数说明

参数

参数类型

说明

text(必填)

String

提问文本

示例代码

agent.ask("今天天气怎么样?")

5.Speak(直接驱动具身智能体播报)

不经过 LLM,直接让具身智能体播报指定文本(同时会将播报文本同步给 E2E 会话)。

SDK 提供两个重载版本:

(1)简化版本(推荐用于纯文本播报)

fun speak(text: String, isStart: Boolean, isEnd: Boolean)

参数

参数类型

说明

text(必填)

String

说话内容文本

isStart(必填)

Boolean

是否开始节点

isEnd(必填)

Boolean

是否输入结束

示例:

agent.speak("你好,我是具身智能体。", isStart = true, isEnd = true)

(2)完整版本(支持 SSML / ka 动作 / 流式播报 / 缓存控制 / 自定义 speakId)

fun speak(
ssml: String?,
isStart: Boolean,
isEnd: Boolean,
enableSpeechCache: Boolean? = null,
clientSpeakId: String? = null
)

流式文本输入示例:

// 开头
agent.speak("msg 1", isStart = true, isEnd = false)
agent.speak("msg 2", isStart = false, isEnd = false)
// ...
// 结尾
agent.speak("msg n", isStart = false, isEnd = true)

注意:LLM 回答的播报由 SDK 内部自动完成流式 speak 驱动,接入方不要onLlmChunk 中再次调用 speak,否则会重复播报。

6.打断

同时打断具身智能体当前播报与 E2E 会话中正在进行的回答。

方法原型

fun interrupt()

示例代码

agent.interrupt()

7.具身智能体状态切换

具身智能体常用的动作状态切换(ASR/LLM 流程中 think、speak 状态由 SDK 自动驱动,一般无需手动调用)。

agent.listen()            // 倾听
agent.think() // 思考
agent.idle() // 待机
agent.interactiveidle() // 交互待机

8.断线重连

SDK 具备两层重连机制,自动处理网络波动场景:

8.1 具身智能体(SocketIO)重连

网络波动或断网时,具身智能体自动进入离线状态,有网络时自动重连。重连事件通过 onAvatarReconnectEvent 回调(code=4000 成功,其他为错误码)。

也支持手动切换:

agent.switchModel(true)   // 手动切换到离线模式
agent.switchModel(false) // 手动重连(仅离线状态下有效)

8.2 E2E WebSocket 重连

E2E 语音会话的 WebSocket 连接异常断开时(非正常关闭 code≠1000),SDK 会自动发起重连

  • 重连策略:指数退避,初始 1s,每次翻倍,最大 16s,最多重试 5 次
  • 状态回调:重连期间状态依次为 DISCONNECTED → CONNECTING → CONNECTED
  • 错误通知:每次断线回调 onError(domain="ws"),重连 5 次耗尽后回调 onError(domain="ws", message="reconnect exhausted after 5 attempts")

8.3 两层联动

具身智能体重连时 E2E 自动同步:

  • 具身智能体断线 → E2E 自动断开,等待具身智能体重连
  • 具身智能体重连成功 → E2E 用新的会话凭证自动建立连接(状态:IDLE → CONNECTING → CONNECTED
  • E2E 独立断线时,使用已有凭证自行重试,不触发具身智能体重连

9.生命周期与销毁

(1)前后台切换

在 Activity 对应生命周期中调用:

override fun onResume() {
super.onResume()
agent.onResume()
}

override fun onPause() {
super.onPause()
agent.onPause()
}

(2)停止与销毁

停止 E2E 会话 + 销毁具身智能体并释放资源;退出页面时调用。stop 之后可重新调用 init 再次启动。

方法原型

fun stop()

示例代码

override fun onDestroy() {
super.onDestroy()
agent.stop()
}

10.其他常用接口

方法

说明

fun setVolume(volume: Float)

设置具身智能体播报音量,0f~1f

fun getVersion(): String

获取 SDK 版本号

fun clearCache()

清除本地缓存资源

fun getIsOffLineMode(): Boolean

当前是否处于离线模式

fun getCurrentFps(): Float

获取当前渲染帧率

fun showDebugInfo() / hideDebugInfo()

打开 / 关闭调试信息展示

fun setLogStorageAndUploadEnabled(enabled: Boolean)

日志存储与上传开关

fun changeLayout(layout: LayoutConfig)

动态修改具身智能体布局

fun changeWalkConfig(walkConfig: WalkConfig)

重新设置行走配置

fun notifyVoiceEnd()

通知服务端具身智能体本轮播报已结束

三.状态与回调

1.E2E 会话状态

onStateChanged(state: XingyunAvatarAgentState) 回调,状态流转如下:

状态

说明

IDLE

初始 / 已停止

CONNECTING

E2E 连接建立中(init 后具身智能体就绪时自动进入)

CONNECTED

E2E 连接已建立,可调用 startASR / ask

LISTENING

麦克风采集与 ASR 识别中

DISCONNECTED

连接异常断开,E2E 会自动重连(指数退避),重连中状态切回 CONNECTING

状态流转图:

IDLECONNECTINGCONNECTEDLISTENING
↑ ↑ ↓ ↓
│ └── DISCONNECTED(异常断开后自动重连)
└── stop() 手动停止

2.回调一览

XingyunAvatarAgentListeneronAudioData 外全部回调在主线程执行(onAudioData 在后台线程回调,见下)。

(1)E2E 语音对话回调(必须实现)

回调

说明

onStateChanged(state)

E2E 会话状态变化

onAsrResult(text, isFinal)

ASR 识别结果;isFinal=true 表示一句话识别结束

onLlmChunk(text, isFirst)

LLM 流式输出分片;isFirst=true 表示本轮回答的首个分片

onLlmDone(usage)

LLM 本轮输出完成,usage 含 token 用量统计

onSemanticJudge(result)

语义判定结果(服务端开启时才会回调,默认空实现)

onError(error)

错误事件

LlmUsage 实体类

字段

类型

含义

promptTokens

Int

提问消耗 token 数

completionTokens

Int

回答消耗 token 数

totalTokens

Int

总 token 数

cachedTokens

Int

命中缓存 token 数

SDKMessage 实体类

字段

类型

含义

error_code

String

服务端返回的错误码字符串

session_id

String

会话 ID

request_id

String

请求 ID

speech_id

Int

语音 ID

client_speak_id

String

客户端 speak ID

(2)具身智能体回调(均有默认空实现,按需重写)

回调

说明

onInitEvent(code, message)

具身智能体初始化结果,code=4000 成功

onAvatarStateChange(state)

具身智能体状态变化(listen/think/speak/idle/interactive_idle)

onVoiceStateChange(status, clientSpeakId)

播报状态:"voice_start" 播报开始 / "voice_end" 播报结束

onSpeakStateChange(speakState, clientSpeakId, errorMsg)

speak 事件状态:speak_start / speak_end / speak_error

onAvatarReconnectEvent(code, message)

具身智能体重连事件,code=4000 成功

onWidgetEvent(widgetData)

Widget 事件数据(字幕等)

onSdkMessage(sdkMessage)

SDK 原始消息,参数为 SDKMessage 对象

onDebugInfo(type, payload)

调试信息

onNetworkInfo(connected, type)

网络信息变化

onAvatarStatusChange(status)

具身智能体内部状态

onStateRenderChange(state, duration)

状态切换到首帧渲染耗时

onWalkStateChange(walkState)

行走状态:speak_walk_start / speak_walk_end

onDownloadProgressAndSpeed(progress, speedMBps)

资源下载进度

onAudioData(audioData, speechId)

具身智能体音频数据(PCM 16kHz 单声道,s16le 小端);后台线程回调,积压超限时可能丢帧

onOfflineEvent()

进入离线模式

onSDKRuntimeError(code, message)

SDK 运行时错误,可在此做重新初始化保证长期运行

四.错误码

1.E2E 错误(onError 回调)

XingyunAvatarAgentError 实体类

字段

类型

含义

domain

ErrorDomain

错误域枚举,见下表

code

Int

错误码:HTTP 状态码 / WS 关闭码 / 服务端错误码

message

String

错误信息

错误域说明

枚举值

说明

SESSION

E2E 会话初始化失败(startSession 返回的 e2e_resp 缺失等)

WS

E2E WebSocket 连接错误 / 异常断开(code 为 WS 关闭码)

ASR

服务端 ASR 错误(code 为服务端错误码)

AUDIO

本地音频采集错误(如麦克风被占用、无权限)

INTERNAL

SDK 内部调用错误(如状态不满足时调用接口)

2.具身智能体返回码

主要用于 onInitEvent、onAvatarReconnectEvent、onSDKRuntimeError 回调。

返回码

返回码描述

4000

成功

4100

进入房间失败(包含服务端接口返回的报错,json 解析报错)

4101

正在初始化中,请稍后再试(仅在 onInitEvent 回调中)

4102

视频帧渲染超时(仅在 onSDKRuntimeError 回调中)

4103

socket 连接退出(仅在 onSDKRuntimeError 回调中)

4104

断开 socket 连接

4105

同步时间帧发生错误

4106

加载 charbin 失败(仅在 onSDKRuntimeError 回调中)

4107

服务升级

4108

暂无可用房间

4109

渲染失败(仅在 onInitEvent 回调中)

4110

socket 连接错误

4200

在未成功初始化时执行其他状态操作

4300

sdk 未在离线状态下进行重连(仅在 onAvatarReconnectEvent 回调中)

五.典型接入流程小结

// 1. 创建实例
val agent = XingyunAvatarAgent()

// 2.(可选)预缓存资源
agent.preCache(context, appId, appSecret, preCacheUrl, preCacheListener)

// 3. 统一初始化(具身智能体 + E2E 语音对话)
agent.init(context, avatarLayout, config, listener)

// 4. 等待 onStateChanged(CONNECTED) 后进行对话
agent.startASR() // 语音对话(需 RECORD_AUDIO 权限)
agent.stopASR()
agent.ask("你好") // 文本对话
agent.interrupt() // 打断

// 5. 直接播报(不经过 LLM)
agent.speak("欢迎光临", isStart = true, isEnd = true)

// 6. 生命周期
agent.onResume() / agent.onPause()

// 7. 退出释放
agent.stop()