Unity: вызов функции Android Kotlin внутри объекта-компаньона из Unity

Я нативный разработчик и новичок в Unity. Я пытаюсь использовать свои сильные стороны, кодируя на Kotlin, а затем используя свой код в качестве плагина в Unity. Одна проблема, с которой я сталкиваюсь, заключается в том, что я не могу понять, как ссылаться на функцию, которая находится внутри объекта-компаньона.

Вот мой класс Котлина

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
            )
        }
    }
}

Я хочу иметь доступ к функции factory из моего кода Unity.

В Котлине я могу сделать так,

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: нет статического метода с именем = 'фабрика' подпись = '(Landroid.app.Application;) Ljava/lang/Object;' в классе Ljava.lang.Object; 12-10 14:00:21.883 13537 13674 E Unity: java.lang.NoSuchMethodError: нет статического метода с именем = 'фабрика' подпись = '(Landroid.app.Application;) Ljava/lang/Object;' в классе Ljava.lang.Object; 12-10 14:00:21.883 13537 13674 E Unity: в com.unity3d.player.ReflectionHelper.getMethodID (неизвестный источник: 162) 12-10 14:00:21.883 13537 13674 E Unity: в com.unity3d.player.UnityPlayer.nativeRender (собственный метод) 12-10 14:00:21.883 13537 13674 E Unity: на com.unity3d.player.UnityPlayer.access$300(Неизвестный источник:0) 12-10 14:00:21.883 13537 13674 E Unity: в com.unity3d.player.UnityPlayer$e$1.handleMessage(Неизвестный источник: 95) 12-10 14:00:21.883 13537 13674 E Unity: в android.os.Handler.dispatchMessage(Handler.java:103) 12-10 14:00:21.883 13537 13674 E Unity: на android.os.Looper.loop(Looper.java:214) 12-10 14:00:21.883 13537 13674 E Unity: в com.unity3d.player.UnityPlayer$e.run(Неизвестный источник: 20)

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
1 419
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы понять, что не так с вашей реализацией, вам нужно декомпилировать ваш код Kotlin в код Java и реализовать часть Unity на основе кода Java, а не 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, двумя способами. Сначала непосредственно из нашего объекта, а затем с помощью объекта Companion.

Код 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, опубликовать его здесь, чтобы мы могли понять, почему он не работает.

Другие вопросы по теме