Kotlin SDK

ElevenAgents SDK:几分钟内为 Android 应用部署定制的交互式语音智能体。

有关 ElevenAgents 工作原理的说明,请参阅 ElevenAgents 概览。

安装

在应用级 build.gradle 文件中添加以下依赖项,即可将 ElevenLabs SDK 添加到 Android 项目:

build.gradle.kts
dependencies {
// ElevenLabs Agents SDK (Android)
implementation("io.elevenlabs:elevenlabs-android:<latest>")
// Kotlin coroutines, AndroidX, etc., as needed by your app
}

使用此 SDK 的 Android 示例应用可在 这里查看。

要求

  • Android API 级别 21(Android 5.0)或更高版本
  • 用于 API 调用的网络权限
  • 用于语音输入的麦克风权限
  • 用于 HTTPS 调用的网络安全配置

设置

Manifest 配置

将所需权限添加到 AndroidManifest.xml:

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

运行时权限

对于 Android 6.0(API 级别 23)及更高版本,必须在运行时请求麦克风权限:

import android.Manifest
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
private fun requestMicrophonePermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
// Show explanation to the user
showPermissionExplanationDialog()
} else {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.RECORD_AUDIO),
MICROPHONE_PERMISSION_REQUEST_CODE
)
}
}
}

使用

在 Application 类或主 Activity 中初始化 ElevenLabs SDK:

使用以下任一方式启动对话会话:

  • 公开智能体:传入 agentId
  • 私有智能体:传入由后端提供的 conversationToken(切勿向客户端暴露 API 密钥)。
import io.elevenlabs.ConversationClient
import io.elevenlabs.ConversationConfig
import io.elevenlabs.ConversationSession
import io.elevenlabs.ClientTool
import io.elevenlabs.ClientToolResult
// Start a public agent session (token generated for you)
val config = ConversationConfig(
agentId = "<your_public_agent_id>", // OR conversationToken = "<token>"
userId = "your-user-id",
// Optional callbacks
onConnect = { conversationId ->
// Called when the conversation is connected and returns the conversation ID. You can access conversationId via session.getId() too
},
onMessage = { source, messageJson ->
// Raw JSON messages from data channel; useful for logging/telemetry
},
onModeChange = { mode ->
// "speaking" | "listening" — drive UI indicators
},
onStatusChange = { status ->
// "connected" | "connecting" | "disconnected"
},
onCanSendFeedbackChange = { canSend ->
// Enable/disable thumbs up/down buttons for feedback reporting
},
onUnhandledClientToolCall = { call ->
// Agent requested a client tool not registered on the device
},
onVadScore = { score ->
// Voice Activity Detection score, range from 0 to 1 where higher values indicate higher confidence of speech
},
onAudioAlignment = { alignment ->
// Character-level timing data for synchronized text display
val chars = alignment["chars"] as? List<*>
val startTimes = alignment["char_start_times_ms"] as? List<*>
val durations = alignment["char_durations_ms"] as? List<*>
Log.d("ExampleApp", "Audio alignment: $chars")
},
// List of client tools the agent can invoke
clientTools = mapOf(
"logMessage" to object : ClientTool {
override suspend fun execute(parameters: Map<String, Any>): ClientToolResult {
val message = parameters["message"] as? String
Log.d("ExampleApp", "[INFO] Client Tool Log: $message")
return ClientToolResult.success("Message logged successfully")
}
}
),
)
// In an Activity context
val session: ConversationSession = ConversationClient.startSession(config, this)

请注意,ElevenAgents 需要麦克风访问权限。建议在对话开始前,先在应用 UI 中说明并请求权限,尤其是在需要运行时权限的 Android 6.0 及更高版本上。

如果服务器上某个工具配置了 expects_response=false,请从 execute 返回 null, 以跳过向智能体发送工具结果。

公开与私有智能体

  • 公开智能体(无需身份验证):在 ConversationConfig 中使用 agentId 初始化。SDK 会向 ElevenLabs 请求对话令牌,无需在设备上使用 API 密钥。
  • 私有智能体(需身份验证):在 ConversationConfig 中使用 conversationToken 初始化。服务器使用 ElevenLabs API 密钥向 ElevenLabs 请求对话令牌。
切勿将 API 密钥嵌入客户端。它们很容易被提取并遭恶意使用。

客户端工具

注册客户端工具,让智能体能够调用设备上的本地功能。

val config = ConversationConfig(
agentId = "<public_agent>",
clientTools = mapOf(
"logMessage" to object : io.elevenlabs.ClientTool {
override suspend fun execute(parameters: Map<String, Any>): io.elevenlabs.ClientToolResult? {
val message = parameters["message"] as? String ?: return io.elevenlabs.ClientToolResult.failure("Missing 'message'")
android.util.Log.d("ClientTool", "Log: $message")
return null // No response needed for fire-and-forget tools
}
}
)
)

当智能体发出 client_tool_call 时,SDK 会执行匹配的工具,并以 client_tool_result 响应。如果工具未注册,将调用 onUnhandledClientToolCall,并向智能体返回失败结果(如果预期有响应)。

回调概览

  • onConnect:建立 WebRTC 连接时调用。返回对话 ID。
  • onMessage:收到新消息时调用。可能是用户语音的临时或最终转录文本、LLM 生成的回复或调试消息。提供来源("ai" 或 "user")及原始 JSON 消息。
  • onModeChange:对话模式改变时调用。可用于指示智能体正在说话("speaking")还是正在聆听("listening")。
  • onStatusChange:对话状态改变时调用("connected"、"connecting" 或 "disconnected")。
  • onCanSendFeedbackChange:发送反馈的能力改变时调用。启用/禁用反馈按钮。
  • onUnhandledClientToolCall:智能体请求设备上未注册的客户端工具时调用。
  • onVadScore:语音活动检测分数改变时调用。范围为 0 到 1,值越高表示检测到语音的置信度越高。
  • onAudioAlignment:收到音频对齐数据时调用,为智能体语音提供字符级时间信息。

并非所有客户端事件都会默认对智能体启用。如果已启用回调但未收到事件,请确认 ElevenLabs 智能体已启用相应事件。 可在 ElevenLabs 控制台中智能体设置的“Advanced”标签页进行配置。

方法

startSession

startSession 方法会初始化 WebRTC 连接,并开始通过麦克风与 ElevenLabs Agents 智能体交流。

公开智能体

对于公开智能体(即未启用身份验证的智能体),只需提供 agentId。可在 ElevenLabs UI 中获取智能体 ID。

val session = ConversationClient.startSession(
config = ConversationConfig(
agentId = "your-agent-id"
),
context = this
)
私有智能体

对于私有智能体,必须传入通过 ElevenLabs API 获取的 conversationToken。生成此令牌需要 ElevenLabs API 密钥。

conversationToken 的有效期为 10 分钟。
// Server-side token generation (Node.js example)
app.get("/conversation-token", yourAuthMiddleware, async (req, res) => {
const response = await fetch(
`https://api.elevenlabs.io/v1/convai/conversation/token?agent_id=${process.env.AGENT_ID}`,
{
headers: {
// Requesting a conversation token requires your ElevenLabs API key
// Do NOT expose your API key to the client!
"xi-api-key": process.env.ELEVENLABS_API_KEY,
},
}
);
if (!response.ok) {
return res.status(500).send("Failed to get conversation token");
}
const body = await response.json();
res.send(body.token);
});

然后,将令牌传给 startSession 方法。请注意,私有智能体只需提供 conversationToken。

// Get conversation token from your server
val conversationToken = fetchConversationTokenFromServer()
// For private agents, pass in the conversation token
val session = ConversationClient.startSession(
config = ConversationConfig(
conversationToken = conversationToken
),
context = this
)

还可选择传入用户 ID,以便在对话中识别用户。这可以是自有的客户标识符。该 ID 会包含在发送到服务器的对话初始化数据中。

val session = ConversationClient.startSession(
config = ConversationConfig(
agentId = "your-agent-id",
userId = "your-user-id"
),
context = this
)

endSession

用于手动结束对话的方法。该方法会断开连接并结束对话。

session.endSession()

sendUserMessage

在活跃对话期间向智能体发送文本消息。这会触发智能体回复。

session.sendUserMessage("Hello, how can you help me?")

sendContextualUpdate

向智能体发送不会触发回复的上下文信息。

session.sendContextualUpdate(
"User navigated to the profile page. Consider this for next response."
)

sendFeedback

针对对话质量提供反馈。这有助于提升智能体表现。在允许反馈时,使用 onCanSendFeedbackChange 启用点赞/点踩 UI。

// Positive feedback
session.sendFeedback(true)
// Negative feedback
session.sendFeedback(false)

sendUserActivity

通知智能体用户活动,防止被打断。适用于用户正在操作应用且智能体应暂停说话的场景,例如用户在聊天中输入文字时。

收到此信号后,智能体会暂停说话约 2 秒。

session.sendUserActivity()

getId

获取对话 ID。

val conversationId = session.getId()
Log.d("Conversation", "Conversation ID: $conversationId")
// e.g., "conv_123"

静音/取消静音

session.toggleMute()
session.setMicMuted(true) // mute
session.setMicMuted(false) // unmute

观察 session.isMuted,以在 UI 标签中切换“静音”和“取消静音”。

属性

status

获取当前对话状态。

val status = session.status
Log.d("Conversation", "Current status: $status")
// Values: DISCONNECTED, CONNECTING, CONNECTED

ProGuard / R8

如果使用压缩/混淆,请确保保留 Gson 模型和 LiveKit。示例规则如下(请按需调整):

-keep class io.elevenlabs.** { *; }
-keep class io.livekit.** { *; }
-keepattributes *Annotation*

故障排除

  • 确保已在运行时授予麦克风权限
  • 如果重连卡住,请确认应用调用了 session.endSession(),并且在重连前启动了新的会话实例
  • 对于模拟器,请确认音频输入/输出路由正常;实体设备通常更可靠

实现示例

实现示例请参阅 ElevenLabs Android SDK 仓库中的示例应用。该应用演示了:

  • 一键连接/断开连接
  • 说话/聆听状态指示器
  • 带 UI 启用/禁用功能的反馈按钮
  • 通过 sendUserActivity() 实现的输入状态指示器
  • 从输入框发送上下文消息和用户消息
  • 麦克风静音/取消静音按钮