Skip to content

Commit

Permalink
Merge pull request #1340 from OneSignal/fix/firebase-messaging-22.0.0…
Browse files Browse the repository at this point in the history
…_compat

Fix Compatibility with FCM (Firebase Messaging) 22.0.0
  • Loading branch information
jkasten2 authored May 23, 2021
2 parents db53d20 + 12f2340 commit 7fab2f4
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 5 deletions.
2 changes: 1 addition & 1 deletion OneSignalSDK/onesignal/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ext {

androidXVersion = '[1.0.0, 1.99.99]'
androidWorkVersion = '[2.0.0, 2.99.99]'
firebaseMessagingVersion = '[19.0.0, 21.99.99]'
firebaseMessagingVersion = '[19.0.0, 22.99.99]'
googleGMSVersion = '[17.0.0, 17.99.99]'
}

Expand Down
5 changes: 5 additions & 0 deletions OneSignalSDK/onesignal/consumer-proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
void disconnect();
}

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,19 @@
import android.util.Base64;

import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;

import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.FirebaseMessaging;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutionException;

class PushRegistratorFCM extends PushRegistratorAbstractGoogle {

// project_info.project_id
Expand All @@ -54,11 +61,64 @@ String getProviderName() {
return "FCM";
}

@WorkerThread
@Override
String getToken(String senderId) throws Throwable {
String getToken(String senderId) throws ExecutionException, InterruptedException, IOException {
initFirebaseApp(senderId);
FirebaseInstanceId instanceId = FirebaseInstanceId.getInstance(firebaseApp);
return instanceId.getToken(senderId, FirebaseMessaging.INSTANCE_ID_SCOPE);

try {
return getTokenWithClassFirebaseMessaging();
} catch (NoClassDefFoundError | NoSuchMethodError e) {
// Class or method wil be missing at runtime if firebase-message older than 21.0.0 is used.
OneSignal.Log(
OneSignal.LOG_LEVEL.INFO,
"FirebaseMessaging.getToken not found, attempting to use FirebaseInstanceId.getToken"
);
}

// Fallback for firebase-message versions older than 21.0.0
return getTokenWithClassFirebaseInstanceId(senderId);
}

// This method is only used if firebase-message older than 21.0.0 is in the app
// We are using reflection here so we can compile with firebase-message:22.0.0 and newer
// - This version of Firebase has completely removed FirebaseInstanceId
@Deprecated
@WorkerThread
private String getTokenWithClassFirebaseInstanceId(String senderId) throws IOException {
// The following code is equivalent to:
// FirebaseInstanceId instanceId = FirebaseInstanceId.getInstance(firebaseApp);
// return instanceId.getToken(senderId, FirebaseMessaging.INSTANCE_ID_SCOPE);
Exception exception;
try {
Class<?> FirebaseInstanceIdClass = Class.forName("com.google.firebase.iid.FirebaseInstanceId");
Method getInstanceMethod = FirebaseInstanceIdClass.getMethod("getInstance", FirebaseApp.class);
Object instanceId = getInstanceMethod.invoke(null, firebaseApp);
Method getTokenMethod = instanceId.getClass().getMethod("getToken", String.class, String.class);
Object token = getTokenMethod.invoke(instanceId, senderId, "FCM");
return (String) token;
} catch (ClassNotFoundException e) {
exception = e;
} catch (NoSuchMethodException e) {
exception = e;
} catch (IllegalAccessException e) {
exception = e;
} catch (InvocationTargetException e) {
exception = e;
}

throw new Error("Reflection error on FirebaseInstanceId.getInstance(firebaseApp).getToken(senderId, FirebaseMessaging.INSTANCE_ID_SCOPE)", exception);
}

@WorkerThread
private String getTokenWithClassFirebaseMessaging() throws ExecutionException, InterruptedException {
// We use firebaseApp.get(FirebaseMessaging.class) instead of FirebaseMessaging.getInstance()
// as the latter uses the default Firebase app. We need to use a custom Firebase app as
// the senderId is provided at runtime.
FirebaseMessaging fcmInstance = firebaseApp.get(FirebaseMessaging.class);
// FirebaseMessaging.getToken API was introduced in firebase-messaging:21.0.0
Task<String> tokenTask = fcmInstance.getToken();
return Tasks.await(tokenTask);
}

private void initFirebaseApp(String senderId) {
Expand Down

0 comments on commit 7fab2f4

Please sign in to comment.