7

To get the current activity in Unity without Firebase Cloud Messaging, the following code works:

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

However, Firebase Cloud Messaging extends the default Unity Activity. So I changed my AndroidJavaClass as such:

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

However, I now get the following error in my 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.access$300(Unknown Source:0)
08-01 15:51:31.838 20323 20375 E Unity   :      at com.unity3d.player.UnityPlayer$e$1.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

I do not understand why. It says that currentActivity does not even exist in the superclass, but if I understand Firebase Cloud Messaging correctly, then it should still exist in the super class. I have also tried replacing currentActivity with things such as UnityPlayerActivity, MessagingUnityPlayerActivity, mypackage, and com.mypackage - but same error. Referencing com.unity3d.player.UnityPlayer in my AndroidJavaClass while using Firebase Cloud Messaging has problems of its own: https://gamedev.stackexchange.com/questions/183734/how-can-i-use-an-inherited-activity-in-c

In case it is relevant, here is my 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>

How can I get my current activity while using Firebase Cloud Messaging? Why does the code not work as shown?

Evorlor
  • 7,263
  • 17
  • 70
  • 141

2 Answers2

3

This should behave as expected if you change the class back to "com.unity3d.player.UnityPlayer".

The issue is that static methods behave a little differently in Java than standard methods. If you see the Java documentation for the JNI.

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

Note that this would be contrary to what you may infer from the standard Java documentation (ex: Are static methods inherited in Java?).

Patrick Martin
  • 2,993
  • 1
  • 13
  • 11
  • I don't believe that is the case here. The results of doing such can be seen here: https://gamedev.stackexchange.com/questions/183734/how-can-i-use-an-inherited-activity-in-c – Evorlor Aug 04 '20 at 22:40
  • Let me know if you've tried it already, but _that_ issue looks like an issue with AndroidJavaObject. They should probably use AndroidJNI directly to get the method id from their subclass since it might be assuming that the return value of `currentActivity` is a `UnityActivity` rather than the firebase messaging one. When I get time, I'll have to compose a good answer there too! – Patrick Martin Aug 05 '20 at 19:37
  • I am not quite following. Can you elaborate? How would I need to change my code? Or are you saying this is a bug with Firebase? – Evorlor Aug 06 '20 at 16:37
  • If you answer the other question instead, I am just as happy to throw a bounty on there :) – Evorlor Aug 06 '20 at 17:27
  • I'm surprised if the solution isn't `var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");`. _If_ that does work, I think the issue you linked (https://gamedev.stackexchange.com/questions/183734/how-can-i-use-an-inherited-activity-in-c) is that `AndroidJavaObject` uses `AndroidJNI` under the hood. `unityPlayer.GetStatic("currentActivity");` probably calls `AndroidJNI.GetStaticMethodID` under the hood with a `"com.google.firebase.MessagingUnityPlayerActivity"` rather than `""com.unity3d.player.UnityPlayer""`. LMK what you find! – Patrick Martin Aug 06 '20 at 17:31
  • I'm not after the bounty, I'm just in Firebase DevRel! I feel bad that I haven't checked the gamedev stack exchange in a bit. – Patrick Martin Aug 06 '20 at 17:32
  • (actually, I think I'm wrong on the final effect in that one - so ignore that) – Patrick Martin Aug 06 '20 at 17:45
  • I think I understand. Is there anything I can replace `unityPlayer.GetStatic("currentActivity")` with, so that it references `"com.unity3d.player.UnityPlayer`? – Evorlor Aug 06 '20 at 17:55
  • You are absolutely correct. My mistake was elsewhere. @0BFE1A8 helped me figure it out, so I awarded them the bounty. But this was the best answer to my (poorly asked) question. Thank you! – Evorlor Aug 07 '20 at 02:15
2

To get current unity activity with Firebase Cloud Messaging plugin installed you need to run this code:

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"));

My android manifest:

<?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>
Hamid Yusifli
  • 9,688
  • 2
  • 24
  • 48
  • What the heck?? The color -16777216 was my problem all along. How did you come up with that number? I was using 0x00000000, which is black without Firebase Cloud Messaging, but becomes white with it. What the heck?? – Evorlor Aug 07 '20 at 01:21
  • Please post an answer on my other question, so I can give you credit there. I am going to accept the other answer here as correct, since it better answers the (poorly asked) question. But I will issue you the bounty. – Evorlor Aug 07 '20 at 01:22
  • Your help was worth every penny of that bounty! Thank you!! But how did you come up with -16777216 as the color code for black? – Evorlor Aug 07 '20 at 02:20
  • 1
    @Evorlor thank you, you're welcome! It's android [Color constants](https://developer.android.com/reference/android/graphics/Color#constants_1). BLACK `Constant Value: -16777216 (0xff000000)` TRANSPARENT `Constant Value: 0 (0x00000000)` I don't know why they lead differently with and without a plugin on your device. They work the same way on my samsung device. The difference between the original and firebase manifest in this line of code: `android:theme="@style/UnityThemeSelector"`. – Hamid Yusifli Aug 07 '20 at 12:42