繁体   English   中英

Unity:调用 Android Kotlin Function Inside Companion Z497031794414A552435F90151C

[英]Unity: Call Android Kotlin Function Inside Companion Object from Unity

我是一名本地开发人员,并且是 Unity 的新手。 我试图通过在 Kotlin 中编码,然后在 Unity 中将我的代码用作插件来发挥我的优势。 我遇到的一个问题是,我无法弄清楚如何引用一个 function,它位于配套的 object 内部。

这是我的 Kotlin class

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 function。

在 Kotlin 我可以这样做,

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: no static 方法 name='factory' signature='(Landroid.app.Application;)Ljava/lang/Object;' 在 class Ljava.lang.Object; 12-10 14:00:21.883 13537 13674 E Unity: java.lang.NoSuchMethodError: no static method with name='factory' signature='/Objectlang.Application.;) 在 class Ljava.lang.Object; 12-10 14:00:21.883 13537 13674 E Unity: at com.unity3d.player.ReflectionHelper.getMethodID(Unknown Source:162) 12-10 14:00:21.883 13537 13674 E Unity: at com.unity3d.player.UnityPlayer 。 com.unity3d.player.UnityPlayer$e$1.handleMessage(Unknown Source:95) 12-10 14:00:21.883 13537 13674 E Unity: at android.os.Handler.dispatchMessage(Handler.java:103) 12-10 14统一:00:21.883 13537 13674 E 统一:在 android.os.Looper.loop(Looper.java:214) 12-10 14:0330:21.883 E2yy34:21.883 12-10 6D9A2D102C5FE6AD1C50DA4BEC50Z.unity3d.player.UnityPlayer$e.run(来源不明:20)

In order to understand what's wrong with your implementation actually you need to decompile your Kotlin code to Java code and implement the Unity part based on the Java code, not Kotlin .

让我们举一个简单的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的function。 首先直接来自我们的 object,其次使用Companion object。

使用此调用的 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);
    }

}

这取决于您喜欢哪种方式。

我的建议是查看您反编译的 Java 代码,将其发布在这里,以便我们了解它为什么不起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM