Skip to content

Commit 9f5436f

Browse files
authored
Generate the Messaging activity, and support GameActivity (#656)
* Generate the Messaging activity * Update packaging export files * Add asmdef file * Generate without a template file * Update FirebaseMessagingActivityGenerator.cs * Remove old files * Leave the file if the contents are the same * Address feedback
1 parent 4ebf774 commit 9f5436f

File tree

8 files changed

+221
-99
lines changed

8 files changed

+221
-99
lines changed

docs/readme.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,10 @@ Release Notes
7171
-------------
7272
### Upcoming
7373
- Changes
74-
- Messaging (Android): Provide the custom MessagingUnityPlayerActivity
74+
- Messaging (Android): Generate the custom MessagingUnityPlayerActivity
7575
as a Java file instead of precompiling it. This is to better support
76-
changes with the UnityPlayerActivity in the Unity 2023 editor.
76+
changes with the UnityPlayerActivity, and GameActivity options, in
77+
the Unity 2023 editor.
7778

7879
### 10.6.0
7980
- Changes

messaging/CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,14 @@ endif()
9090
if (ANDROID)
9191
# Add the additional Messaging files needed for Android
9292
unity_pack_file(
93-
"activity/com/google/firebase/MessagingUnityPlayerActivity.java"
93+
"activity/FirebaseMessagingActivityGenerator.cs"
9494
PACK_PATH
95-
"Firebase/Plugins/Android/"
95+
"Firebase/Editor/Messaging/"
96+
)
97+
unity_pack_file(
98+
"activity/FirebaseMessagingActivityGenerator.asmdef"
99+
PACK_PATH
100+
"Firebase/Editor/Messaging/"
96101
)
97102
# Get the Messaging Java AAR file from the C++ SDK.
98103
add_custom_target(
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "FirebaseMessagingActivityGenerator",
3+
"rootNamespace": "",
4+
"references": [],
5+
"includePlatforms": [
6+
"Editor"
7+
],
8+
"excludePlatforms": [],
9+
"allowUnsafeCode": false,
10+
"overrideReferences": false,
11+
"precompiledReferences": [],
12+
"autoReferenced": true,
13+
"defineConstraints": [],
14+
"versionDefines": [],
15+
"noEngineReferences": false
16+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
using System.IO;
17+
using System.Linq;
18+
using UnityEngine;
19+
using UnityEditor;
20+
using UnityEditor.Build;
21+
using UnityEditor.Build.Reporting;
22+
23+
namespace Firebase.Messaging.Editor {
24+
25+
// Handles the generation of the MessagingUnityPlayerActivity java file.
26+
// Note this regenerates the file every time an Android build occurs,
27+
// but local changes can be preserved by using the PreserveTag below.
28+
// This is needed because the source code needs to be present to work across
29+
// different Unity versions, due to changes in mUnityPlayer.
30+
// It also adjusts the base class of the file based on if GameActivity is being
31+
// used (a new feature in Unity 2023).
32+
public class FirebaseMessagingActivityGenerator : IPreprocessBuildWithReport {
33+
// TODO: Ideally this should use a template file, the tricky part is locating
34+
// the template file when it is either in the Assets path, or the Packages path.
35+
// There are some similar cases in EDM4U, so a solution might be to use that.
36+
private readonly string[] ActivityClassContents = new string[]{
37+
"/*",
38+
" * This file is generated by the FirebaseMessagingActivityGenerator script.",
39+
" * Refer to that script for more information.",
40+
" */",
41+
"",
42+
"package com.google.firebase;",
43+
"",
44+
"import android.content.Intent;",
45+
"import android.os.Bundle;",
46+
"import com.google.firebase.messaging.MessageForwardingService;",
47+
"import com.unity3d.player.{0};",
48+
"",
49+
"/**",
50+
" * MessagingUnityPlayerActivity is a {0} that updates its intent when new intents",
51+
" * are sent to it.",
52+
" *",
53+
" * This is a workaround for a known issue that prevents Firebase Cloud Messaging from responding to",
54+
" * data payloads when both a data and notification payload are sent to the app while it is in the",
55+
" * background.",
56+
" */",
57+
"public class MessagingUnityPlayerActivity extends {0} {{",
58+
" // The key in the intent's extras that maps to the incoming message's message ID. Only sent by",
59+
" // the server, GmsCore sends EXTRA_MESSAGE_ID_KEY below. Server can't send that as it would get",
60+
" // stripped by the client.",
61+
" private static final String EXTRA_MESSAGE_ID_KEY_SERVER = \"message_id\";",
62+
"",
63+
" // An alternate key value in the intent's extras that also maps to the incoming message's message",
64+
" // ID. Used by upstream, and set by GmsCore.",
65+
" private static final String EXTRA_MESSAGE_ID_KEY = \"google.message_id\";",
66+
"",
67+
" // The key in the intent's extras that maps to the incoming message's sender value.",
68+
" private static final String EXTRA_FROM = \"google.message_id\";",
69+
"",
70+
" /**",
71+
" * Workaround for when a message is sent containing both a Data and Notification payload.",
72+
" *",
73+
" * <p>When the app is in the background, if a message with both a data and notification payload is",
74+
" * received the data payload is stored on the Intent passed to onNewIntent. By default, that",
75+
" * intent does not get set as the Intent that started the app, so when the app comes back online",
76+
" * it doesn't see a new FCM message to respond to. As a workaround, we override onNewIntent so",
77+
" * that it sends the intent to the MessageForwardingService which forwards the message to the",
78+
" * FirebaseMessagingService which in turn sends the message to the application.",
79+
" */",
80+
" @Override",
81+
" protected void onNewIntent(Intent intent) {{",
82+
" super.onNewIntent(intent);",
83+
"",
84+
" // If we do not have a 'from' field this intent was not a message and should not be handled. It",
85+
" // probably means this intent was fired by tapping on the app icon.",
86+
" Bundle extras = intent.getExtras();",
87+
" if (extras == null) {{",
88+
" return;",
89+
" }}",
90+
" String from = extras.getString(EXTRA_FROM);",
91+
" String messageId = extras.getString(EXTRA_MESSAGE_ID_KEY);",
92+
" if (messageId == null) {{",
93+
" messageId = extras.getString(EXTRA_MESSAGE_ID_KEY_SERVER);",
94+
" }}",
95+
" if (from != null && messageId != null) {{",
96+
" Intent message = new Intent(this, MessageForwardingService.class);",
97+
" message.setAction(MessageForwardingService.ACTION_REMOTE_INTENT);",
98+
" message.putExtras(intent);",
99+
" message.setData(intent.getData());",
100+
" MessageForwardingService.enqueueWork(this, message);",
101+
" }}",
102+
" setIntent(intent);",
103+
" }}",
104+
"",
105+
" /**",
106+
" * Dispose of the mUnityPlayer when restarting the app.",
107+
" *",
108+
" * <p>This ensures that when the app starts up again it does not start with stale data.",
109+
" */",
110+
" @Override",
111+
" protected void onCreate(Bundle savedInstanceState) {{",
112+
" if (mUnityPlayer != null) {{",
113+
" mUnityPlayer.quit();",
114+
" mUnityPlayer = null;",
115+
" }}",
116+
" super.onCreate(savedInstanceState);",
117+
" }}",
118+
"}}"
119+
};
120+
private readonly string BaseActivityClass = "UnityPlayerActivity";
121+
private readonly string BaseGameActivityClass = "UnityPlayerGameActivity";
122+
123+
private readonly string GeneratedFileTag = "FirebaseMessagingActivityGenerated";
124+
// If this tag is present on the generated file, it will not be replaced.
125+
private readonly string PreserveTag = "FirebasePreserve";
126+
127+
private readonly string OutputPath = Path.Combine("Plugins", "Android");
128+
private readonly string OutputFilename = "MessagingUnityPlayerActivity.java";
129+
130+
public int callbackOrder { get { return 0; } }
131+
public void OnPreprocessBuild(BuildReport report) {
132+
// Only run this logic when building for Android.
133+
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.Android) {
134+
return;
135+
}
136+
137+
// Determine what the contents of the generated file should be.
138+
string baseClass = BaseActivityClass;
139+
#if UNITY_2023_1_OR_NEWER
140+
// If using the new GameActivity logic, we want to generate with that base class.
141+
if (PlayerSettings.Android.applicationEntry.HasFlag(AndroidApplicationEntry.GameActivity)) {
142+
baseClass = BaseGameActivityClass;
143+
}
144+
#endif
145+
string fileContents = System.String.Format(System.String.Join("\n", ActivityClassContents), baseClass);
146+
147+
// Check if the file has already been generated.
148+
string[] oldAssetGuids = AssetDatabase.FindAssets("l:" + GeneratedFileTag);
149+
if (oldAssetGuids != null && oldAssetGuids.Length > 0) {
150+
if (oldAssetGuids.Length != 1) {
151+
Debug.LogWarning("FirebaseMessagingActivityEditor found multiple generated files with the label: " +
152+
GeneratedFileTag + " \n" +
153+
"No changes will be made, but this can potentially cause problems on Android with duplicate classes.\n" +
154+
"Please check for duplicate classes, and remove any unnecessary uses of the label.");
155+
return;
156+
}
157+
string oldAssetPath = AssetDatabase.GUIDToAssetPath(oldAssetGuids[0]);
158+
Object oldAsset = AssetDatabase.LoadMainAssetAtPath(oldAssetPath);
159+
if (oldAsset != null) {
160+
string oldAssetFullPath = Path.Combine(Application.dataPath, "..", oldAssetPath);
161+
string oldFileContents = System.IO.File.ReadAllText(oldAssetFullPath);
162+
// If the old file matches what we would generate, exit early.
163+
if (oldFileContents == fileContents) {
164+
return;
165+
}
166+
// If the generated file has been tagged to be preserved, don't change it.
167+
string[] labelList = AssetDatabase.GetLabels(oldAsset);
168+
if (labelList.Contains(PreserveTag)) {
169+
return;
170+
}
171+
// Delete the old asset.
172+
Debug.Log("Changes detected, regenerating " + oldAssetPath + "\n" +
173+
"To preserve local changes to that file, add the label: " + PreserveTag);
174+
AssetDatabase.DeleteAsset(oldAssetPath);
175+
}
176+
}
177+
178+
// Generate the new file.
179+
string newAssetFullDirectory = Path.Combine(Application.dataPath, OutputPath);
180+
System.IO.Directory.CreateDirectory(newAssetFullDirectory);
181+
System.IO.File.WriteAllText(Path.Combine(newAssetFullDirectory, OutputFilename), fileContents);
182+
string newAssetLocalPath = Path.Combine("Assets", OutputPath, OutputFilename);
183+
AssetDatabase.ImportAsset(newAssetLocalPath);
184+
Object newAsset = AssetDatabase.LoadMainAssetAtPath(newAssetLocalPath);
185+
AssetDatabase.SetLabels(newAsset, new[]{GeneratedFileTag});
186+
}
187+
}
188+
189+
} // namespace Firebase.Messaging.Editor

messaging/activity/com/google/firebase/MessagingUnityPlayerActivity.java

Lines changed: 0 additions & 93 deletions
This file was deleted.

unity_packer/debug_single_export_json/messaging.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@
282282
"importer": "DefaultImporter",
283283
"paths": [
284284
"Firebase/Editor/MessagingDependencies.xml",
285+
"Firebase/Editor/Messaging/FirebaseMessagingActivityGenerator.asmdef",
286+
"Firebase/Editor/Messaging/FirebaseMessagingActivityGenerator.cs",
285287
"Firebase/m2repository/com/google/firebase/firebase-messaging-unity/"
286288
]
287289
},
@@ -301,7 +303,6 @@
301303
"platforms": ["Android"],
302304
"cpu": "AnyCPU",
303305
"paths": [
304-
"Firebase/Plugins/Android/MessagingUnityPlayerActivity.java",
305306
"Firebase/Plugins/Android/firebase-messaging-cpp.aar"
306307
]
307308
},

unity_packer/exports.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,8 @@
731731
"importer": "DefaultImporter",
732732
"paths": [
733733
"Firebase/Editor/MessagingDependencies.xml",
734+
"Firebase/Editor/Messaging/FirebaseMessagingActivityGenerator.asmdef",
735+
"Firebase/Editor/Messaging/FirebaseMessagingActivityGenerator.cs",
734736
"Firebase/m2repository/com/google/firebase/firebase-messaging-unity/"
735737
]
736738
},
@@ -747,7 +749,6 @@
747749
"platforms": ["Android"],
748750
"cpu": "AnyCPU",
749751
"paths": [
750-
"Firebase/Plugins/Android/MessagingUnityPlayerActivity.java",
751752
"Firebase/Plugins/Android/firebase-messaging-cpp.aar"
752753
]
753754
},

unity_packer/guids.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@
530530
"Firebase/Editor/FirebaseMessaging_version-10.6.0_manifest.txt": "0992fabc0ba8451ba12ebc0ff86d8952",
531531
"Firebase/Editor/FirebaseRemoteConfig_version-10.6.0_manifest.txt": "bd609ed590784691960483599ff2bf00",
532532
"Firebase/Editor/FirebaseStorage_version-10.6.0_manifest.txt": "7fc8962be9e2405aba8fef4093514b8c",
533+
"Firebase/Editor/Messaging/FirebaseMessagingActivityGenerator.asmdef": "23dad9d59a474cb6a052bb9322271ae3",
534+
"Firebase/Editor/Messaging/FirebaseMessagingActivityGenerator.cs": "38cf8316372e4943aee735c624262e05",
533535
"Firebase/Plugins/x86_64/FirebaseCppApp-10_6_0.bundle": "ddb54d0bdc3444589f5a78560cb74a11",
534536
"Firebase/Plugins/x86_64/FirebaseCppApp-10_6_0.dll": "f87e7bd2dcf0465da8ea618bcbe52973",
535537
"Firebase/Plugins/x86_64/FirebaseCppApp-10_6_0.so": "117087a4ebb144a1a75007f8fc5d6822",

0 commit comments

Comments
 (0)