Skip to content

Commit 62182c9

Browse files
authored
Fix works with agent rpg and android and Unity 6, better confirm with meet (#361)
1 parent 91abae5 commit 62182c9

1 file changed

Lines changed: 25 additions & 16 deletions

File tree

Runtime/Scripts/Internal/FFI/FFIClient.cs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,12 @@ static void GetMainContext()
136136

137137
#if UNITY_ANDROID && !UNITY_EDITOR
138138
/// <summary>
139-
/// Get the Android application context as a raw jobject pointer.
140-
/// This is passed to the native library for WebRTC audio initialization.
139+
/// Get the Android application context.
140+
/// Passed to the native library (as a raw jobject) for WebRTC audio initialization,
141+
/// and to the managed ContextUtils fallback in InitializeSdk.
141142
/// </summary>
142-
/// <returns>IntPtr to the application context jobject, or IntPtr.Zero on failure</returns>
143-
private static IntPtr GetAndroidApplicationContext()
143+
/// <returns>The application context, or null on failure. Caller owns disposal.</returns>
144+
private static AndroidJavaObject GetAndroidApplicationContext()
144145
{
145146
try
146147
{
@@ -151,7 +152,7 @@ private static IntPtr GetAndroidApplicationContext()
151152
if (currentActivity == null)
152153
{
153154
Utils.Error("FFIServer - Failed to get Unity currentActivity");
154-
return IntPtr.Zero;
155+
return null;
155156
}
156157

157158
// Get the application context from the activity
@@ -160,18 +161,15 @@ private static IntPtr GetAndroidApplicationContext()
160161
if (applicationContext == null)
161162
{
162163
Utils.Error("FFIServer - Failed to get Android applicationContext");
163-
return IntPtr.Zero;
164+
return null;
164165
}
165166

166-
// Get the raw jobject pointer
167-
// Note: We don't dispose the applicationContext here because we're passing
168-
// the raw pointer to native code. The native code will create its own global ref.
169-
return applicationContext.GetRawObject();
167+
return applicationContext;
170168
}
171169
catch (System.Exception e)
172170
{
173171
Utils.Error($"FFIServer - Failed to get Android application context: {e.Message}");
174-
return IntPtr.Zero;
172+
return null;
175173
}
176174
}
177175
#endif
@@ -194,15 +192,26 @@ private static void InitializeSdk()
194192
try
195193
{
196194
IntPtr javaVmPtr = AndroidJNI.GetJavaVM();
197-
IntPtr contextPtr = GetAndroidApplicationContext();
195+
using var applicationContext = GetAndroidApplicationContext();
198196

199-
if (javaVmPtr != IntPtr.Zero && contextPtr != IntPtr.Zero)
197+
if (javaVmPtr != IntPtr.Zero && applicationContext != null)
200198
{
201-
bool contextInitialized = NativeMethods.LiveKitInitializeAndroidContext(javaVmPtr, contextPtr);
199+
// Disposing applicationContext after these calls is safe: the native side only
200+
// uses the jobject within the call, and Java's ContextUtils holds the Context
201+
// in a static field of its own.
202+
bool contextInitialized = NativeMethods.LiveKitInitializeAndroidContext(
203+
javaVmPtr, applicationContext.GetRawObject());
202204
if (!contextInitialized)
203205
{
204-
// JVM init still succeeded; only PlatformAudio won't work
205-
Utils.Error("FFIServer - Android context init failed; PlatformAudio will not work");
206+
// The native init looks up ContextUtils with JNIEnv::FindClass, which fails
207+
// on Unity's main thread: it is a native thread with no Java frames, so
208+
// FindClass falls back to the system class loader, which cannot see APK
209+
// classes. Initialize the shaded ContextUtils through Unity's interop
210+
// instead — it resolves classes via the application class loader. Without
211+
// this, the first audio device use NPEs and WebRTC aborts the process.
212+
using var contextUtils = new AndroidJavaClass("livekit.org.webrtc.ContextUtils");
213+
contextUtils.CallStatic("initialize", applicationContext);
214+
Utils.Info("FFIServer - ContextUtils initialized via managed fallback");
206215
}
207216
}
208217
else

0 commit comments

Comments
 (0)