Skip to content

Commit 7fab2f4

Browse files
authored
Merge pull request #1340 from OneSignal/fix/firebase-messaging-22.0.0_compat
Fix Compatibility with FCM (Firebase Messaging) 22.0.0
2 parents db53d20 + 12f2340 commit 7fab2f4

File tree

3 files changed

+70
-5
lines changed

3 files changed

+70
-5
lines changed

OneSignalSDK/onesignal/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ext {
55

66
androidXVersion = '[1.0.0, 1.99.99]'
77
androidWorkVersion = '[2.0.0, 2.99.99]'
8-
firebaseMessagingVersion = '[19.0.0, 21.99.99]'
8+
firebaseMessagingVersion = '[19.0.0, 22.99.99]'
99
googleGMSVersion = '[17.0.0, 17.99.99]'
1010
}
1111

OneSignalSDK/onesignal/consumer-proguard-rules.pro

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
void disconnect();
77
}
88

9+
# Need to keep as these 2 methods are called with reflection from com.onesignal.PushRegistratorFCM
10+
-keep class com.google.firebase.iid.FirebaseInstanceId {
11+
static com.google.firebase.iid.FirebaseInstanceId getInstance(com.google.firebase.FirebaseApp);
12+
java.lang.String getToken(java.lang.String, java.lang.String);
13+
}
914

1015
-keep class com.onesignal.ActivityLifecycleListenerCompat** {*;}
1116

OneSignalSDK/onesignal/src/main/java/com/onesignal/PushRegistratorFCM.java

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,19 @@
3030
import android.util.Base64;
3131

3232
import androidx.annotation.NonNull;
33+
import androidx.annotation.WorkerThread;
3334

35+
import com.google.android.gms.tasks.Task;
36+
import com.google.android.gms.tasks.Tasks;
3437
import com.google.firebase.FirebaseApp;
3538
import com.google.firebase.FirebaseOptions;
36-
import com.google.firebase.iid.FirebaseInstanceId;
3739
import com.google.firebase.messaging.FirebaseMessaging;
3840

41+
import java.io.IOException;
42+
import java.lang.reflect.InvocationTargetException;
43+
import java.lang.reflect.Method;
44+
import java.util.concurrent.ExecutionException;
45+
3946
class PushRegistratorFCM extends PushRegistratorAbstractGoogle {
4047

4148
// project_info.project_id
@@ -54,11 +61,64 @@ String getProviderName() {
5461
return "FCM";
5562
}
5663

64+
@WorkerThread
5765
@Override
58-
String getToken(String senderId) throws Throwable {
66+
String getToken(String senderId) throws ExecutionException, InterruptedException, IOException {
5967
initFirebaseApp(senderId);
60-
FirebaseInstanceId instanceId = FirebaseInstanceId.getInstance(firebaseApp);
61-
return instanceId.getToken(senderId, FirebaseMessaging.INSTANCE_ID_SCOPE);
68+
69+
try {
70+
return getTokenWithClassFirebaseMessaging();
71+
} catch (NoClassDefFoundError | NoSuchMethodError e) {
72+
// Class or method wil be missing at runtime if firebase-message older than 21.0.0 is used.
73+
OneSignal.Log(
74+
OneSignal.LOG_LEVEL.INFO,
75+
"FirebaseMessaging.getToken not found, attempting to use FirebaseInstanceId.getToken"
76+
);
77+
}
78+
79+
// Fallback for firebase-message versions older than 21.0.0
80+
return getTokenWithClassFirebaseInstanceId(senderId);
81+
}
82+
83+
// This method is only used if firebase-message older than 21.0.0 is in the app
84+
// We are using reflection here so we can compile with firebase-message:22.0.0 and newer
85+
// - This version of Firebase has completely removed FirebaseInstanceId
86+
@Deprecated
87+
@WorkerThread
88+
private String getTokenWithClassFirebaseInstanceId(String senderId) throws IOException {
89+
// The following code is equivalent to:
90+
// FirebaseInstanceId instanceId = FirebaseInstanceId.getInstance(firebaseApp);
91+
// return instanceId.getToken(senderId, FirebaseMessaging.INSTANCE_ID_SCOPE);
92+
Exception exception;
93+
try {
94+
Class<?> FirebaseInstanceIdClass = Class.forName("com.google.firebase.iid.FirebaseInstanceId");
95+
Method getInstanceMethod = FirebaseInstanceIdClass.getMethod("getInstance", FirebaseApp.class);
96+
Object instanceId = getInstanceMethod.invoke(null, firebaseApp);
97+
Method getTokenMethod = instanceId.getClass().getMethod("getToken", String.class, String.class);
98+
Object token = getTokenMethod.invoke(instanceId, senderId, "FCM");
99+
return (String) token;
100+
} catch (ClassNotFoundException e) {
101+
exception = e;
102+
} catch (NoSuchMethodException e) {
103+
exception = e;
104+
} catch (IllegalAccessException e) {
105+
exception = e;
106+
} catch (InvocationTargetException e) {
107+
exception = e;
108+
}
109+
110+
throw new Error("Reflection error on FirebaseInstanceId.getInstance(firebaseApp).getToken(senderId, FirebaseMessaging.INSTANCE_ID_SCOPE)", exception);
111+
}
112+
113+
@WorkerThread
114+
private String getTokenWithClassFirebaseMessaging() throws ExecutionException, InterruptedException {
115+
// We use firebaseApp.get(FirebaseMessaging.class) instead of FirebaseMessaging.getInstance()
116+
// as the latter uses the default Firebase app. We need to use a custom Firebase app as
117+
// the senderId is provided at runtime.
118+
FirebaseMessaging fcmInstance = firebaseApp.get(FirebaseMessaging.class);
119+
// FirebaseMessaging.getToken API was introduced in firebase-messaging:21.0.0
120+
Task<String> tokenTask = fcmInstance.getToken();
121+
return Tasks.await(tokenTask);
62122
}
63123

64124
private void initFirebaseApp(String senderId) {

0 commit comments

Comments
 (0)