i am new to android and unity both. i want to write native wrapper and use in unity. to start with i have created simple framework in android (kotlin).
here is how kotlin code looks like:
class PluginInstance {
fun initWithApp(id: String, name: String, completionBlock: (Boolean) -> Void) {
if(id == "123" || name == "test") {
completionBlock(true)
} else {
completionBlock(false)
}
}
fun Add(i: Int, j: Int): Int {
println("received data from unity: "+ i + " and " + j)
return i * j
}
}
i am able to call 'add' function from unity to android.
here is what c# code looks like:
public class PluginInit : MonoBehaviour
{
AndroidJavaClass unityClass;
AndroidJavaObject unityActivity;
AndroidJavaObject _pluginInstance;
void initializePlugIn(string pluginName)
{
unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
_pluginInstance = new AndroidJavaObject(pluginName);
if (_pluginInstance == null)
{
UnityEngine.Debug.Log("Plugin instance error");
}
unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
_pluginInstance.CallStatic("receivedUnityActivity", unityActivity);
}
public void Add()
{
if(_pluginInstance != null)
{
var result = _pluginInstance.Call<int>("Add", 50, 60);
UnityEngine.Debug.Log("Add result from unity: " + result);
}
}
[MonoPInvokeCallback(typeof(Action<bool>))]
public static void completionBlock(bool status)
{
UnityEngine.Debug.Log("completionBlock status is: " + status);
}
public void initApp()
{
if (_pluginInstance != null)
{
_pluginInstance.Call("initWithApp", "123", "test", "completionBlock");
}
}
// Start is called before the first frame update
void Start()
{
initializePlugIn("com.voidstudio.unityplugin.PluginInstance");
}
// Update is called once per frame
void Update()
{
}
}
but not able to call 'initWithApp', getting below error:
StackTrace "java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/jvm/functions/Function1;\n\tat java.lang.reflect.Executable.getParameterTypesInternal(Native Method)\n\tat java.lang.reflect.Method.getParameterTypes(Method.java:186)\n\tat java.lang.Class.getDeclaredMethods(Class.java:1884)\n\tat com.unity3d.player.ReflectionHelper.getMethodID(Unknown Source:89)\n\tat com.unity3d.player.UnityPlayer.nativeRender(Native Method)\n\tat com.unity3d.player.UnityPlayer.access$300(Unknown Source:0)\n\tat com.unity3d.player.UnityPlayer$e$1.handleMessage(Unknown Source:95)\n\tat android.os.Handler.dispatchMessage(Handler.java:103)\n\tat android.os.Looper.loop(Looper.java:224)\n\tat com.unity3d.player.UnityPlayer$e.run(Unknown Source:20)\nCaused by: java.lang.ClassNotFoundException: Didn\'t find class \"kotlin.jvm.functions.Function1\" on path: DexPathList[[zip file \"/data/app/com.DefaultCompany.UnityTutorials1-fuYm25syH1tjvIopLqYbig==/base.apk\"],nativeLibraryDirectories=[/data/app/com.DefaultCompa… string
next i came across 'AndroidJavaProxy' in unity: i tried to implement as below, getting error though:
Kotlin side code:
package com.voidstudio.unityplugin
import android.app.Activity;
import android.widget.Toast;
interface PluginCallback {
fun onfinish(status: Boolean)
}
class PluginInstance {
fun initWithApp(id: String, name: String, callback: PluginCallback) {
if(id == "123" || name == "test") {
callback.onfinish(true);
} else {
callback.onfinish(false);
}
}
fun Add(i: Int, j: Int): Int {
println("received data from unity: "+ i + " and " + j)
return i * j
}
fun Toast(message: String?) {
Toast.makeText(unityActivity, message, Toast.LENGTH_SHORT).show()
}
companion object {
private var unityActivity: Activity? = null
fun receivedUnityActivity(tActivity: Activity?) {
unityActivity = tActivity
}
}
}
and C# side code:
public class AndroidPluginCallback : AndroidJavaProxy
{
public AndroidPluginCallback() : base("com.voidstudio.unityplugin.PluginCallback") { }
public void onfinish(bool status)
{
UnityEngine.Debug.Log("ENTER callback onFinish: " + status);
}
}
public class PluginInit : MonoBehaviour
{
AndroidJavaClass unityClass;
AndroidJavaObject unityActivity;
AndroidJavaObject _pluginInstance;
void initializePlugIn(string pluginName)
{
unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
_pluginInstance = new AndroidJavaObject(pluginName);
if (_pluginInstance == null)
{
UnityEngine.Debug.Log("Plugin instance error");
}
unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
_pluginInstance.CallStatic("receivedUnityActivity", unityActivity);
}
public void Add()
{
if(_pluginInstance != null)
{
var result = _pluginInstance.Call<int>("Add", 50, 60);
UnityEngine.Debug.Log("Add result from unity: " + result);
}
}
public void initApp()
{
if (_pluginInstance != null)
{
_pluginInstance.Call("initWithApp", "123", "test", new AndroidPluginCallback());
}
}
// Start is called before the first frame update
void Start()
{
initializePlugIn("com.voidstudio.unityplugin.PluginInstance");
}
// Update is called once per frame
void Update()
{
}
}
getting below error:
2022-09-15 20:03:21.464 28784-28947/com.DefaultCompany.UnityTutorials1 E/Unity: AndroidJavaException: java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/jvm/internal/Intrinsics;
java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/jvm/internal/Intrinsics;
at com.voidstudio.unityplugin.PluginInstance.initWithApp(Unknown Source:2)
at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
at com.unity3d.player.UnityPlayer.access$300(Unknown Source:0)
at com.unity3d.player.UnityPlayer$e$1.handleMessage(Unknown Source:95)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:224)
at com.unity3d.player.UnityPlayer$e.run(Unknown Source:20)
Caused by: java.lang.ClassNotFoundException: Didn't find class "kotlin.jvm.internal.Intrinsics" on path: DexPathList[[zip file "/data/app/com.DefaultCompany.UnityTutorials1-uQ0GB_qPkh_IKsYm1Ljl2g==/base.apk"],nativeLibraryDirectories=[/data/app/com.DefaultCompany.UnityTutorials1-uQ0GB_qPkh_IKsYm1Ljl2g==/lib/arm, /data/app/com.DefaultCompany.UnityTutorials1-uQ0GB_qPkh_IKsYm1Ljl2g==/base.ap