在 Unity 中使用 Firebase 云消息传递时如何获取当前 activity?

How can I get the current activity while using Firebase Cloud Messaging in Unity?

要在不使用 Firebase 云消息传递的情况下在 Unity 中获取当前 activity,以下代码有效:

var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

但是,Firebase Cloud Messaging 扩展了默认的 Unity Activity。所以我改变了我的AndroidJavaClass

var unityPlayer = new AndroidJavaClass("com.google.firebase.MessagingUnityPlayerActivity");
var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

但是,我现在在 logcat 中收到以下错误:

08-01 15:51:31.838 20323 20375 E Unity   : AndroidJavaException: java.lang.NoSuchFieldError: no "Ljava/lang/Object;" field "currentActivity" in class "Lcom/google/firebase/MessagingUnityPlayerActivity;" or its superclasses
08-01 15:51:31.838 20323 20375 E Unity   : java.lang.NoSuchFieldError: no "Ljava/lang/Object;" field "currentActivity" in class "Lcom/google/firebase/MessagingUnityPlayerActivity;" or its superclasses
08-01 15:51:31.838 20323 20375 E Unity   :      at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
08-01 15:51:31.838 20323 20375 E Unity   :      at com.unity3d.player.UnityPlayer.access0(Unknown Source:0)
08-01 15:51:31.838 20323 20375 E Unity   :      at com.unity3d.player.UnityPlayer$e.handleMessage(Unknown Source:83)
08-01 15:51:31.838 20323 20375 E Unity   :      at android.os.Handler.dispatchMessage(Handler.java:103)
08-01 15:51:31.838 20323 20375 E Unity   :      at android.os.Looper.loop(Looper.java:214)
08-01 15:51:31.838 20323 20375 E Unity   :      at com.unity3d.player.UnityPlayer$e.run(Unknown Source:20)
08-01 15:51:31.838 20323 20375 E Unity   :   at UnityEngine.AndroidJNISafe.CheckException () [0x00000] in <00000000000000000000000000000000>:0
08-01 15:51:31.838 20323 20375 E Unity   :   at UnityEngine.AndroidJNISafe.GetStaticFieldID (System.IntPtr clazz, System.String name, System.String sig) [0x00000] in <00000000000000000000000000000000>:0
08-01 15:51:31.838 20323 20375 E Unity   :   at UnityEngine._AndroidJNIHelper.GetFieldID (System.IntPtr jc

我不明白为什么。它说 currentActivity 甚至不存在于超级 class 中,但如果我正确理解 Firebase 云消息传递,那么它应该仍然存在于超级 class 中。我还尝试用 UnityPlayerActivityMessagingUnityPlayerActivitymypackagecom.mypackage 等内容替换 currentActivity - 但同样的错误。在使用 Firebase 云消息传递时在我的 AndroidJavaClass 中引用 com.unity3d.player.UnityPlayer 有其自身的问题:https://gamedev.stackexchange.com/questions/183734/how-can-i-use-an-inherited-activity-in-c

如果相关,这是我的 AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.mypackage" android:versionCode="1" android:versionName="1.0">
  <application android:label="@string/app_name" android:icon="@drawable/app_icon">
    <!-- The MessagingUnityPlayerActivity is a class that extends
         UnityPlayerActivity to work around a known issue when receiving
         notification data payloads in the background. -->
    <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/notification_icon" />
    <activity android:name="com.google.firebase.MessagingUnityPlayerActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    </activity>
    <service android:name="com.google.firebase.messaging.MessageForwardingService" android:exported="false" />
  </application>
</manifest>

如何在使用 Firebase 云消息传递时获取当前 activity?为什么代码不像显示的那样工作?

如果您将 class 改回 "com.unity3d.player.UnityPlayer",这应该会按预期运行。

问题是静态方法在 Java 中的行为与标准方法略有不同。如果您看到 Java documentation for the JNI.

The method ID must be derived from clazz, not from one of its superclasses.

请注意,这与您从标准 Java 文档(例如:Are static methods inherited in Java?)中推断的内容相反。

要安装 Firebase Cloud Messaging 插件以获得当前的统一性 activity,您需要 运行 此代码:

var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
// Get current activity name, in my case it returns "com.google.firebase.MessagingUnityPlayerActivity"
Debug.Log(activity.Call<AndroidJavaObject>("getClass").Call<string>("getCanonicalName"));

我的 android 清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.unity3d.player" android:versionCode="1" android:versionName="1.0">
  <application android:label="@string/app_name" android:icon="@mipmap/app_icon">
    <!-- The MessagingUnityPlayerActivity is a class that extends
         UnityPlayerActivity to work around a known issue when receiving
         notification data payloads in the background. -->
    <activity android:name="com.google.firebase.MessagingUnityPlayerActivity" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="false">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
      <meta-data android:name="android.notch_support" android:value="true" />
    </activity>
    <service android:name="com.google.firebase.messaging.MessageForwardingService" android:exported="false" />
    <meta-data android:name="unity.splash-mode" android:value="0" />
    <meta-data android:name="unity.splash-enable" android:value="True" />
    <meta-data android:name="notch.config" android:value="portrait|landscape" />
    <meta-data android:name="unity.build-id" android:value="" />
  </application>
  <uses-feature android:glEsVersion="0x00030000" />
  <uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>