- Home /
The question is answered, right answer was accepted
JNI Exception using Android Plugin
Hi,
I'm trying to integrate the DeployGate SDK into my unity game for android. Here's what it says on their website:
If your project has an Application class specified in in your AndroidManifest.xml, open that class and add following line into onCreate() function: DeployGate.install(this);
https://deploygate.com/docs/sdk
So I downloaded the deploygatesdk.jar, copied it to /Assets/Plugins/Android, and used it on startup (C# MonoBehaviour called DeployGate.cs) like this:
void Start () {
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject app = activity.Call<AndroidJavaObject>("getApplicationContext");
AndroidJavaClass dg = new AndroidJavaClass("com.deploygate.sdk.DeployGate");
dg.CallStatic("install", app);
}
When I start the game on android, LogCat reports these Errors:
04-14 01:51:14.389: I/Unity(17702): ExecutionEngineException: JNI Exception
04-14 01:51:14.389: I/Unity(17702): at UnityEngine.AndroidJavaObject._CallStatic (System.String methodName, System.Object[] args) [0x00000] in <filename unknown>:0
04-14 01:51:14.389: I/Unity(17702): at UnityEngine.AndroidJavaObject.CallStatic (System.String methodName, System.Object[] args) [0x00000] in <filename unknown>:0
04-14 01:51:14.389: I/Unity(17702): at DeployGate.Start () [0x00034] in D:\Unity\TestGame\Assets\Scripts\DeployGate.cs:15
04-14 01:51:14.389: I/Unity(17702):
04-14 01:51:14.389: I/Unity(17702): (Filename: D Line: 0)
D:\Unity\TestGame\Assets\Scripts\DeployGate.cs:15 is the project path on my windows PC. This is weird. Any idea how to resolve this Exception?
EDIT: I activated debug-checkjni in adb and this exception might be more of a help:
04-14 10:22:25.826: W/System.err(28435): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-14 10:22:25.846: W/System.err(28435): at android.os.Handler.<init>(Handler.java:197)
04-14 10:22:25.846: W/System.err(28435): at android.os.Handler.<init>(Handler.java:111)
04-14 10:22:25.846: W/System.err(28435): at com.deploygate.sdk.DeployGate.<init>(DeployGate.java:207)
04-14 10:22:25.846: W/System.err(28435): at com.deploygate.sdk.DeployGate.install(DeployGate.java:467)
04-14 10:22:25.846: W/System.err(28435): at com.deploygate.sdk.DeployGate.install(DeployGate.java:441)
04-14 10:22:25.846: W/System.err(28435): at com.deploygate.sdk.DeployGate.install(DeployGate.java:418)
04-14 10:22:25.846: W/System.err(28435): at com.deploygate.sdk.DeployGate.install(DeployGate.java:369)
04-14 10:22:25.846: W/System.err(28435): at com.deploygate.sdk.DeployGate.install(DeployGate.java:349)
04-14 10:22:25.846: W/System.err(28435): at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
04-14 10:22:25.846: W/System.err(28435): at com.unity3d.player.UnityPlayer.onDrawFrame(Unknown Source)
04-14 10:22:25.846: W/System.err(28435): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
04-14 10:22:25.846: W/System.err(28435): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
According to Google it has to run on the uithread to work. Do I have to edit the jar file to achieve that?
Answer by Kabbs · Apr 14, 2013 at 10:36 AM
Ok, I'm gonna solve this myself. Here's how I did it:
public static class DeployGate {
private static AndroidJavaClass deployGate = null;
public static void Install() {
// Get Android context
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject app = activity.Call<AndroidJavaObject>("getApplicationContext");
// Install DeployGate, make sure it will not called twice in your app
deployGate = new AndroidJavaClass("com.deploygate.sdk.DeployGate");
activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
deployGate.CallStatic("install", app);
}));
}
}
So
activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
deployGate.CallStatic("install", app);
}));
makes the call run on the uithread, additionally, I made everything static since DeployGate should only be installed once and should be persistent through level changes (but that didn't have anything to do with my errors). So it's not a MonoBehaviour anymore, instead I call it like this:
DeployGate.Install();
I hope this'll help someone who stumbles upon this with the same problem. Here's the whole class with a few basic methods:
using UnityEngine;
using System.Collections;
public static class DeployGate {
private static AndroidJavaClass deployGate = null;
public static void Install() {
// Get Android context
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject app = activity.Call<AndroidJavaObject>("getApplicationContext");
// Install DeployGate, make sure it will not called twice in your app
deployGate = new AndroidJavaClass("com.deploygate.sdk.DeployGate");
activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
deployGate.CallStatic("install", app);
}));
}
public static void LogError(string text) {
deployGate.CallStatic("logError", text);
}
public static void LogWarn(string text) {
deployGate.CallStatic("logWarn", text);
}
public static void LogDebug(string text) {
deployGate.CallStatic("logDebug", text);
}
public static void LogInfo(string text) {
deployGate.CallStatic("logInfo", text);
}
public static void LogVerbose(string text) {
deployGate.CallStatic("logVerbose", text);
}
}
I am not using deployGate rather a custom Android SD$$anonymous$$. This worked thanks.
Follow this Question
Related Questions
What is the difference between AndroidJavaClass.Call and AndroidJavaObject.Call 2 Answers
Getting native Android String constants via JNI broken in Unity 2019.2.0? 3 Answers
Getting byte[] or ByteBuffer[] from native Java 1 Answer
Passing AndroidJavaObject to C++ method using JNI 0 Answers
JNI - local reference table overflow 0 Answers