Skip to content

Commit 7b7b6dd

Browse files
committed
Corrected reporting of FCM exceptions
Since we moved to FCM's newer Task API we did not correctly unwrap the nested root causes to parse the root error message. Correct this along with some refactoring to make this easier to read and to support another error type. Also accounted for AUTHENTICATION_FAILED which we didn't handle before. This can happen if you boot an Android Studio emulator for the first time right after creating it and run your app. We should retry as it only takes a short amount of time for the emulator to initialize with Google's servers.
1 parent 35208c7 commit 7b7b6dd

File tree

3 files changed

+54
-14
lines changed

3 files changed

+54
-14
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/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)