如何在Unity中集成并使用Android平台的LiveKit SDK?
LiveKit Android SDK 集成到Unity的完整方案
一、集成准备
- 导入AAR文件
将livekit.aar放入Unity项目的Assets/Plugins/Android目录下。若LiveKit依赖其他第三方库(如okhttp、WebRTC相关组件),需将对应AAR一并导入,避免编译时出现缺失依赖报错。 - 配置Android权限
在Unity的Player Settings > Android > Publishing Settings中勾选Custom Main Manifest,然后在生成的AndroidManifest.xml中添加必要权限:<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - Gradle配置补充
打开Assets/Plugins/Android/mainTemplate.gradle,在仓库列表中添加Maven Central(若AAR未包含全部依赖):repositories { mavenCentral() }
二、代码修正与正确调用逻辑
你的现有代码存在三处核心问题:LiveKit的connect是异步挂起函数,无法通过yield return直接获取结果;音视频轨道创建缺少必要参数;未处理异步操作的回调结果。以下是修正后的完整实现:
1. 回调代理类(处理LiveKit异步事件)
先创建AndroidJavaProxy实现Room的回调监听:
public class RoomListener : AndroidJavaProxy { private Action onConnected; private Action<string> onDisconnected; private Action<string> onError; public RoomListener(Action connectedCallback, Action<string> disconnectedCallback, Action<string> errorCallback) : base("io.livekit.android.room.RoomListener") { onConnected = connectedCallback; onDisconnected = disconnectedCallback; onError = errorCallback; } // 对应RoomListener的onConnected方法 public void onConnected() { onConnected?.Invoke(); } // 对应RoomListener的onDisconnected方法 public void onDisconnected(string reason) { onDisconnected?.Invoke(reason); } // 对应RoomListener的onError方法 public void onError(string error) { onError?.Invoke(error); } }
2. 核心连接与音视频发布逻辑
private AndroidJavaObject room; private string liveKitServerUrl = "你的LiveKit服务器地址"; private void Start() { // 获取Unity当前Activity AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); // 创建Room实例 AndroidJavaClass liveKitClass = new AndroidJavaClass("io.livekit.android.LiveKit"); room = liveKitClass.CallStatic<AndroidJavaObject>("create", currentActivity); // 设置Room事件监听器 RoomListener roomListener = new RoomListener( OnRoomConnected, OnRoomDisconnected, OnRoomError ); room.Call("addListener", roomListener); // 请求摄像头与麦克风权限 RequestRequiredPermissions(); } // 请求必要权限 private void RequestRequiredPermissions() { #if UNITY_ANDROID if (!Permission.HasUserAuthorizedPermission(Permission.Camera) || !Permission.HasUserAuthorizedPermission(Permission.Microphone)) { Permission.RequestUserPermissions(new string[] { Permission.Camera, Permission.Microphone }); Invoke("ConnectToRoom", 2f); // 等待权限申请结果 } else { ConnectToRoom(); } #endif } // 连接到LiveKit房间 private void ConnectToRoom() { string token = PlayerPrefs.GetString("stream-token", ""); if (string.IsNullOrEmpty(token)) { Debug.LogError("Token不能为空!"); return; } // 异步连接,结果通过RoomListener回调 room.Call("connect", liveKitServerUrl, token); } // 连接成功回调 private void OnRoomConnected() { Debug.Log("成功连接到LiveKit房间"); AndroidJavaObject localParticipant = room.Call<AndroidJavaObject>("localParticipant"); if (localParticipant == null) return; // 创建并发布视频轨道(指定后置摄像头) AndroidJavaObject videoOptions = new AndroidJavaObject("io.livekit.android.video.LocalVideoTrackOptions$Builder") .Call<AndroidJavaObject>("setPosition", 1) // CameraPosition.BACK对应int值1 .Call<AndroidJavaObject>("build"); AndroidJavaObject videoTrack = localParticipant.Call<AndroidJavaObject>("createVideoTrack", "video-track", videoOptions); localParticipant.Call("publishVideoTrack", videoTrack); // 创建并发布音频轨道 AndroidJavaObject audioOptions = new AndroidJavaObject("io.livekit.android.audio.LocalAudioTrackOptions$Builder") .Call<AndroidJavaObject>("build"); AndroidJavaObject audioTrack = localParticipant.Call<AndroidJavaObject>("createAudioTrack", "audio-track", audioOptions); localParticipant.Call("publishAudioTrack", audioTrack); // 启用摄像头与麦克风 localParticipant.Call("setCameraEnabled", true); localParticipant.Call("setMicrophoneEnabled", true); } // 断开连接回调 private void OnRoomDisconnected(string reason) { Debug.Log($"断开房间连接:{reason}"); } // 错误回调 private void OnRoomError(string error) { Debug.LogError($"房间操作错误:{error}"); }
三、关键注意事项
- 权限优先级:必须先获取用户授权的摄像头、麦克风权限,否则音视频轨道创建会直接失败。
- 异步逻辑处理:LiveKit所有核心操作均为异步,必须通过
RoomListener监听结果,不能用同步代码的方式等待返回值。 - 参数一致性:创建轨道时的ID、配置参数需与Android原生代码保持一致(如摄像头位置的int枚举值:BACK=1,FRONT=0)。
- 依赖完整性:确认所有LiveKit依赖的第三方库已导入Unity,否则会出现
ClassNotFoundException或方法找不到的报错。
内容的提问来源于stack exchange,提问作者Norman Atomic
相关产品推荐
相关产品推荐

