|
33 | 33 | import android.util.Base64;
|
34 | 34 |
|
35 | 35 | import android.support.annotation.NonNull;
|
| 36 | +import android.support.annotation.WorkerThread; |
36 | 37 |
|
| 38 | +import com.google.android.gms.tasks.Task; |
| 39 | +import com.google.android.gms.tasks.Tasks; |
37 | 40 | import com.google.firebase.FirebaseApp;
|
38 | 41 | import com.google.firebase.FirebaseOptions;
|
39 | 42 | import com.google.firebase.iid.FirebaseInstanceId;
|
40 | 43 | import com.google.firebase.iid.FirebaseInstanceIdService;
|
41 | 44 | import com.google.firebase.messaging.FirebaseMessaging;
|
42 | 45 |
|
| 46 | +import java.io.IOException; |
| 47 | +import java.lang.reflect.InvocationTargetException; |
| 48 | +import java.lang.reflect.Method; |
| 49 | +import java.util.concurrent.ExecutionException; |
| 50 | + |
43 | 51 | // TODO: 4.0.0 - Switch to using <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
|
44 | 52 | // Note: Starting with Firebase Messaging 17.1.0 onNewToken in FirebaseMessagingService should be
|
45 | 53 | // used instead.
|
46 |
| - |
47 | 54 | class PushRegistratorFCM extends PushRegistratorAbstractGoogle {
|
48 | 55 |
|
49 | 56 | // project_info.project_id
|
@@ -88,13 +95,59 @@ String getProviderName() {
|
88 | 95 | return "FCM";
|
89 | 96 | }
|
90 | 97 |
|
| 98 | + @WorkerThread |
91 | 99 | @Override
|
92 |
| - String getToken(String senderId) throws Throwable { |
| 100 | + String getToken(String senderId) throws ExecutionException, InterruptedException, IOException { |
93 | 101 | initFirebaseApp(senderId);
|
| 102 | + |
| 103 | + try { |
| 104 | + return getTokenWithClassFirebaseMessaging(); |
| 105 | + } catch (Error e) { |
| 106 | + // Class or method will be missing at runtime if firebase-message older than 21.0.0 is used. |
| 107 | + OneSignal.Log( |
| 108 | + OneSignal.LOG_LEVEL.INFO, |
| 109 | + "FirebaseMessaging.getToken not found, attempting to use FirebaseInstanceId.getToken" |
| 110 | + ); |
| 111 | + } |
| 112 | + |
| 113 | + // Fallback for firebase-message versions older than 21.0.0 |
| 114 | + return getTokenWithClassFirebaseInstanceId(senderId); |
| 115 | + } |
| 116 | + |
| 117 | + @WorkerThread |
| 118 | + private String getTokenWithClassFirebaseInstanceId(String senderId) throws IOException { |
94 | 119 | FirebaseInstanceId instanceId = FirebaseInstanceId.getInstance(firebaseApp);
|
95 | 120 | return instanceId.getToken(senderId, FirebaseMessaging.INSTANCE_ID_SCOPE);
|
96 | 121 | }
|
97 | 122 |
|
| 123 | + @WorkerThread |
| 124 | + private String getTokenWithClassFirebaseMessaging() throws ExecutionException, InterruptedException { |
| 125 | + // We use firebaseApp.get(FirebaseMessaging.class) instead of FirebaseMessaging.getInstance() |
| 126 | + // as the latter uses the default Firebase app. We need to use a custom Firebase app as |
| 127 | + // the senderId is provided at runtime. |
| 128 | + FirebaseMessaging firebaseMessagingInstance = firebaseApp.get(FirebaseMessaging.class); |
| 129 | + |
| 130 | + if (firebaseMessagingInstance == null) { |
| 131 | + throw new Error("firebaseMessagingInstance is null"); |
| 132 | + } |
| 133 | + |
| 134 | + Exception exception; |
| 135 | + // FirebaseMessaging.getToken API was introduced in firebase-messaging:21.0.0 |
| 136 | + try { |
| 137 | + Method getTokenMethod = firebaseMessagingInstance.getClass().getMethod("getToken"); |
| 138 | + Object tokenTask = getTokenMethod.invoke(firebaseMessagingInstance); |
| 139 | + return Tasks.await((Task<String>)tokenTask); |
| 140 | + } catch (NoSuchMethodException e) { |
| 141 | + exception = e; |
| 142 | + } catch (IllegalAccessException e) { |
| 143 | + exception = e; |
| 144 | + } catch (InvocationTargetException e) { |
| 145 | + exception = e; |
| 146 | + } |
| 147 | + |
| 148 | + throw new Error("Reflection error on FirebaseMessaging.getToken()", exception); |
| 149 | + } |
| 150 | + |
98 | 151 | private void initFirebaseApp(String senderId) {
|
99 | 152 | if (firebaseApp != null)
|
100 | 153 | return;
|
|
0 commit comments