Skip to content

Commit da8c8d8

Browse files
authored
Merge pull request #1599 from OneSignal/fix/fcm_correct_types_of_errors_handling
[Fix] FCM register retrying and correct types of errors handling
2 parents 6dd61b7 + 7b7b6dd commit da8c8d8

File tree

4 files changed

+61
-17
lines changed

4 files changed

+61
-17
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,4 +654,17 @@ static boolean shouldLogMissingAppIdError(@Nullable String appId) {
654654
static int getRandomDelay(int minDelay, int maxDelay) {
655655
return new Random().nextInt(maxDelay + 1 - minDelay) + minDelay;
656656
}
657+
658+
@NonNull
659+
static Throwable getRootCauseThrowable(@NonNull Throwable subjectThrowable) {
660+
Throwable throwable = subjectThrowable;
661+
while (throwable.getCause() != null && throwable.getCause() != throwable) {
662+
throwable = throwable.getCause();
663+
}
664+
return throwable;
665+
}
666+
667+
static String getRootCauseMessage(@NonNull Throwable throwable) {
668+
return getRootCauseThrowable(throwable).getMessage();
669+
}
657670
}

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

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,34 +99,60 @@ private boolean attemptRegistration(String senderId, int currentRetry) {
9999
registeredHandler.complete(registrationId, UserState.PUSH_STATUS_SUBSCRIBED);
100100
return true;
101101
} catch (IOException e) {
102-
if (!"SERVICE_NOT_AVAILABLE".equals(e.getMessage())) {
103-
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Error Getting " + getProviderName() + " Token", e);
104-
if (!firedCallback)
105-
registeredHandler.complete(null, UserState.PUSH_STATUS_FIREBASE_FCM_ERROR_IOEXCEPTION);
106-
return true;
107-
}
108-
else {
102+
int pushStatus = pushStatusFromThrowable(e);
103+
String exceptionMessage = OSUtils.getRootCauseMessage(e);
104+
boolean retryingKnownToWorkSometimes =
105+
"SERVICE_NOT_AVAILABLE".equals(exceptionMessage) ||
106+
"AUTHENTICATION_FAILED".equals(exceptionMessage);
107+
108+
if (retryingKnownToWorkSometimes) {
109+
// Wrapping with new Exception so the current line is included in the stack trace.
110+
Exception exception = new Exception(e);
109111
if (currentRetry >= (REGISTRATION_RETRY_COUNT - 1))
110-
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Retry count of " + REGISTRATION_RETRY_COUNT + " exceed! Could not get a " + getProviderName() + " Token.", e);
112+
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Retry count of " + REGISTRATION_RETRY_COUNT + " exceed! Could not get a " + getProviderName() + " Token.", exception);
111113
else {
112-
OneSignal.Log(OneSignal.LOG_LEVEL.INFO, "'Google Play services' returned SERVICE_NOT_AVAILABLE error. Current retry count: " + currentRetry, e);
114+
OneSignal.Log(OneSignal.LOG_LEVEL.INFO, "'Google Play services' returned " + exceptionMessage + " error. Current retry count: " + currentRetry, exception);
113115
if (currentRetry == 2) {
114116
// Retry 3 times before firing a null response and continuing a few more times.
115-
registeredHandler.complete(null, UserState.PUSH_STATUS_FIREBASE_FCM_ERROR_SERVICE_NOT_AVAILABLE);
117+
registeredHandler.complete(null, pushStatus);
116118
firedCallback = true;
117119
return true;
118120
}
119121
}
120122
}
123+
else {
124+
// Wrapping with new Exception so the current line is included in the stack trace.
125+
Exception exception = new Exception(e);
126+
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Error Getting " + getProviderName() + " Token", exception);
127+
if (!firedCallback)
128+
registeredHandler.complete(null, pushStatus);
129+
return true;
130+
}
121131
} catch (Throwable t) {
122-
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Unknown error getting " + getProviderName() + " Token", t);
123-
registeredHandler.complete(null, UserState.PUSH_STATUS_FIREBASE_FCM_ERROR_MISC_EXCEPTION);
132+
// Wrapping with new Exception so the current line is included in the stack trace.
133+
Exception exception = new Exception(t);
134+
int pushStatus = pushStatusFromThrowable(t);
135+
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Unknown error getting " + getProviderName() + " Token", exception);
136+
registeredHandler.complete(null, pushStatus);
124137
return true;
125138
}
126139

127140
return false;
128141
}
129142

143+
static private int pushStatusFromThrowable(Throwable throwable) {
144+
String exceptionMessage = OSUtils.getRootCauseMessage(throwable);
145+
if (throwable instanceof IOException) {
146+
if ("SERVICE_NOT_AVAILABLE".equals(exceptionMessage))
147+
return UserState.PUSH_STATUS_FIREBASE_FCM_ERROR_IOEXCEPTION_SERVICE_NOT_AVAILABLE;
148+
else if ("AUTHENTICATION_FAILED".equals(exceptionMessage))
149+
return UserState.PUSH_STATUS_FIREBASE_FCM_ERROR_IOEXCEPTION_AUTHENTICATION_FAILED;
150+
else
151+
return UserState.PUSH_STATUS_FIREBASE_FCM_ERROR_IOEXCEPTION_OTHER;
152+
}
153+
return UserState.PUSH_STATUS_FIREBASE_FCM_ERROR_MISC_EXCEPTION;
154+
}
155+
130156
private boolean isValidProjectNumber(String senderId, PushRegistrator.RegisteredHandler callback) {
131157
boolean isProjectNumberValidFormat;
132158
try {

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ String getProviderName() {
103103

104104
@WorkerThread
105105
@Override
106-
String getToken(String senderId) throws ExecutionException, InterruptedException, IOException {
106+
String getToken(String senderId) throws Exception {
107107
initFirebaseApp(senderId);
108108

109109
try {
@@ -151,14 +151,18 @@ private String getTokenWithClassFirebaseInstanceId(String senderId) throws IOExc
151151
}
152152

153153
@WorkerThread
154-
private String getTokenWithClassFirebaseMessaging() throws ExecutionException, InterruptedException {
154+
private String getTokenWithClassFirebaseMessaging() throws Exception {
155155
// We use firebaseApp.get(FirebaseMessaging.class) instead of FirebaseMessaging.getInstance()
156156
// as the latter uses the default Firebase app. We need to use a custom Firebase app as
157157
// the senderId is provided at runtime.
158158
FirebaseMessaging fcmInstance = firebaseApp.get(FirebaseMessaging.class);
159159
// FirebaseMessaging.getToken API was introduced in firebase-messaging:21.0.0
160160
Task<String> tokenTask = fcmInstance.getToken();
161-
return Tasks.await(tokenTask);
161+
try {
162+
return Tasks.await(tokenTask);
163+
} catch (ExecutionException e) {
164+
throw tokenTask.getException();
165+
}
162166
}
163167

164168
private void initFirebaseApp(String senderId) {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ abstract class UserState {
4040
static final int PUSH_STATUS_INVALID_FCM_SENDER_ID = -6;
4141
static final int PUSH_STATUS_OUTDATED_GOOGLE_PLAY_SERVICES_APP = -7;
4242
static final int PUSH_STATUS_FIREBASE_FCM_INIT_ERROR = -8;
43-
static final int PUSH_STATUS_FIREBASE_FCM_ERROR_SERVICE_NOT_AVAILABLE = -9;
43+
static final int PUSH_STATUS_FIREBASE_FCM_ERROR_IOEXCEPTION_SERVICE_NOT_AVAILABLE = -9;
4444
// -10 is a server side detection only from FCM that the app is no longer installed
45-
static final int PUSH_STATUS_FIREBASE_FCM_ERROR_IOEXCEPTION = -11;
45+
static final int PUSH_STATUS_FIREBASE_FCM_ERROR_IOEXCEPTION_OTHER = -11;
4646
static final int PUSH_STATUS_FIREBASE_FCM_ERROR_MISC_EXCEPTION = -12;
4747
// -13 to -24 reserved for other platforms
4848
public static final int PUSH_STATUS_HMS_TOKEN_TIMEOUT = -25;
@@ -51,6 +51,7 @@ abstract class UserState {
5151
public static final int PUSH_STATUS_HMS_ARGUMENTS_INVALID = -26;
5252
public static final int PUSH_STATUS_HMS_API_EXCEPTION_OTHER = -27;
5353
public static final int PUSH_STATUS_MISSING_HMS_PUSHKIT_LIBRARY = -28;
54+
public static final int PUSH_STATUS_FIREBASE_FCM_ERROR_IOEXCEPTION_AUTHENTICATION_FAILED = -29;
5455

5556
private static final String[] LOCATION_FIELDS = new String[] { "lat", "long", "loc_acc", "loc_type", "loc_bg", "loc_time_stamp" };
5657
private static final Set<String> LOCATION_FIELDS_SET = new HashSet<>(Arrays.asList(LOCATION_FIELDS));

0 commit comments

Comments
 (0)