You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Unity中集成并使用Android平台的LiveKit SDK?

LiveKit Android SDK 集成到Unity的完整方案

一、集成准备

  1. 导入AAR文件
    将livekit.aar放入Unity项目的Assets/Plugins/Android目录下。若LiveKit依赖其他第三方库(如okhttp、WebRTC相关组件),需将对应AAR一并导入,避免编译时出现缺失依赖报错。
  2. 配置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" />
    
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 13:29:57