Unity Java Kotlin 交互
从Unity调用同伴对象内的Android Kotlin函数
这是一篇转载文章,为了记录Unity
调用Kotlin
的写法,原文地址:
https://www.5axxw.com/questions/content/dis5k1
我的科特林班
class MyAnalytics internal constructor(
private val MyAnalyticsConfiguration: MyAnalyticsConfiguration
) : MyAnalyticsLogger {
.
.
.
override fun logEvent(eventRequest: Event?) {
// some code in here
}
companion object {
@JvmStatic
fun factory(
context: Context,
MyAnalyticsConfiguration: MyAnalyticsConfiguration = MyAnalyticsConfiguration()
) : MyAnalytics {
val eventExecutor = MyWorkManager(
workManager = WorkManager.getInstance(context.applicationContext),
MyAnalyticsConfiguration = MyAnalyticsConfiguration
)
return MyAnalytics(
MyAnalyticsConfiguration
)
}
}
}
我希望能够从我的Unity
代码访问factory
函数。
在科特林我可以这样做:
MyAnalytics.factory(
context = requireActivity()
)
但我怎么能在Unity
中做到这一点呢?这是我尝试过的。
AndroidJavaClass UnityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject UnityPlayerActivity = UnityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject myAnalytics = new AndroidJavaObject("com.test.analytics.MyAnalytics");
AndroidJavaObject analyticsObject = myAnalytics.Call<AndroidJavaObject>("factory", UnityPlayerActivity); //Also tried with 'CallStatic'; no result, same error
我收到的错误是:
AndroidJavaException:java.lang.NoSuchMethodError:
类Ljava.lang.Object中没有name='factory'signature='(Landroid.app.Application;)Ljava/lang/Object;'的静态方法;
12-1014:00:21.883 13537 13674 E Unity:java.lang.NoSuchMethodError:
类Ljava.lang.Object中没有name='factory'signature='(Landroid.app.Application;)Ljava/lang/Object;'的静态方法;
12-1014:00:21.883 13537 13674 E Unity:atcom.unity3d.player.ReflectionHelper.getMethodID(Unknown资料来源:162)
12-1014:00:21.883 13537 13674 E Unity:在com.unity3d.player.UnityPlayer.nativeRender(Native方法)
12-1014:00:21.883 13537 13674 E Unity:在com.unity3d.player.UnityPlayer.access$300(Unknown来源:0){10237@1027@1367}统一资料来源:95)
12-1014:00:21.883 13537 13674 E Unity:在android.os.Handler.dispatchMessage(Handler.java:103)
12-1014:00:21.883 13537 13674 E Unity:在android.os.Looper.loop(Looper.java:214)
12-1014:00:21.883 13537 13674 E Unity:在com.unity3d.player.UnityPlayer$e.run(Unknown资料来源:20)
查看反编译代码
为了理解实现中的问题,您需要将Kotlin代码反编译为Java代码,并基于Java代码而不是Kotlin实现Unity部分。
让我们举一个Kotlin代码的简单示例,它将打印日志,仅此而已:
class MyKotlinClass(val name: String = "DEFAULT NAME") {
fun callNormalFunc() {
Log.d("UNITY", "callNormalFunc from Kotlin code")
}
companion object {
@JvmStatic
fun callStaticCompanionFunc(): MyKotlinClass {
Log.d("UNITY", "callStaticCompanionFunc from Kotlin code")
return MyKotlinClass("NEW NAME")
}
}
}
反编译的Java代码如下:
public final class MyKotlinClass {
@NotNull
private final String name;
@NotNull
public static final MyKotlinClass.Companion Companion = new MyKotlinClass.Companion((DefaultConstructorMarker)null);
public final void callNormalFunc() {
Log.d("UNITY", "callNormalFunc from Kotlin code");
}
@NotNull
public final String getName() {
return this.name;
}
public MyKotlinClass(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
super();
this.name = name;
}
// $FF: synthetic method
public MyKotlinClass(String var1, int var2, DefaultConstructorMarker var3) {
if ((var2 & 1) != 0) {
var1 = "DEFAULT NAME";
}
this(var1);
}
public MyKotlinClass() {
this((String)null, 1, (DefaultConstructorMarker)null);
}
@JvmStatic
@NotNull
public static final MyKotlinClass callStaticCompanionFunc() {
return Companion.callStaticCompanionFunc();
}
public static final class Companion {
@JvmStatic
@NotNull
public final MyKotlinClass callStaticCompanionFunc() {
Log.d("UNITY", "callStaticCompanionFunc from Kotlin code");
return new MyKotlinClass("NEW NAME");
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
从反编译的代码中我们可以看到,实际上我们可以用两种方式调用标记为@JvmStatic的函数。第一个直接来自我们的对象,第二个使用Companion对象。
Unity调用的方式
使用此调用的Unity代码如下所示:
public class KotlinCallScript : MonoBehaviour {
private AndroidJavaObject _object;
private AndroidJavaClass _staticClass;
// Start is called before the first frame update
private void Start () {
_object = new AndroidJavaObject ("com.hardartcore.kotlin.MyKotlinClass");
_staticClass = new AndroidJavaClass ("com.hardartcore.kotlin.MyKotlinClass");
var defaultName = _object.Call<string> ("getName");
Debug.Log ("START GET DEFAUL NAME: " + defaultName);
}
public void CallNormalFunction () {
_object.Call ("callNormalFunc");
}
public void CallStaticFunction () {
var companionObject = _staticClass.GetStatic<AndroidJavaObject> ("Companion");
var newName = companionObject.Call<AndroidJavaObject> ("callStaticCompanionFunc").Call<string> ("getName");
Debug.Log ("CALL STATIC FUNCTION NEW NAME: " + newName);
}
public void CallSecondWay () {
var kotlinObject = _object.CallStatic<AndroidJavaObject> ("callStaticCompanionFunc");
var newName = kotlinObject.Call<string> ("getName");
Debug.Log ("CALL SECOND WAY NEW NAME: " + newName);
}
}
你会选择哪种方式取决于你!