From 51c25abec7936ae9d17db73fca317d252548a393 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 5 Dec 2018 17:35:27 +0100 Subject: [PATCH] Issue #2266 / Defensive code for notifications issues --- CHANGES.rst | 3 +- .../java/im/vector/push/fcm/FcmHelper.java | 58 ++++++++++++++++--- .../im/vector/activity/SplashActivity.java | 24 +++++++- .../main/java/im/vector/push/PushManager.java | 6 ++ vector/src/main/res/values/strings.xml | 1 + 5 files changed, 79 insertions(+), 13 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 29f4218bd6..a3716b8504 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,12 +10,13 @@ Features: Improvements: - Show userId below display name in member detail screen (#2756) - Clicking on a user and a room avatar opens a new screen with animation to view the avatar in full screen, with zoom capabilities (#2455) + - Added Troubleshoot Notification settings page Other changes: - Bugfix: - - + - Defensive code for notifications issues + check play services as per FCM recommendation (#2266) Translations: - diff --git a/vector/src/app/java/im/vector/push/fcm/FcmHelper.java b/vector/src/app/java/im/vector/push/fcm/FcmHelper.java index 2a6d73df67..e376f4e407 100755 --- a/vector/src/app/java/im/vector/push/fcm/FcmHelper.java +++ b/vector/src/app/java/im/vector/push/fcm/FcmHelper.java @@ -18,18 +18,25 @@ package im.vector.push.fcm; import android.app.Activity; +import android.app.Dialog; import android.content.Context; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; +import android.widget.Toast; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; +import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.InstanceIdResult; import org.matrix.androidsdk.util.Log; +import im.vector.R; + /** * This class store the FCM token in SharedPrefs and ensure this token is retrieved. * It has an alter ego in the fdroid variant. @@ -70,16 +77,49 @@ public static void storeFcmToken(@NonNull Context context, */ public static void ensureFcmTokenIsRetrieved(final Activity activity) { if (TextUtils.isEmpty(getFcmToken(activity))) { - try { - FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(activity, new OnSuccessListener() { - @Override - public void onSuccess(InstanceIdResult instanceIdResult) { - storeFcmToken(activity, instanceIdResult.getToken()); - } - }); - } catch (Exception e) { - Log.e(LOG_TAG, "## ensureFcmTokenIsRetrieved() : failed " + e.getMessage(), e); + + + //vfe: according to firebase doc + //'app should always check the device for a compatible Google Play services APK before accessing Google Play services features' + if (checkPlayServices(activity)) { + try { + FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(activity, new OnSuccessListener() { + @Override + public void onSuccess(InstanceIdResult instanceIdResult) { + storeFcmToken(activity, instanceIdResult.getToken()); + } + }) + .addOnFailureListener(activity, new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Log.e(LOG_TAG, "## ensureFcmTokenIsRetrieved() : failed " + e.getMessage(), e); + } + }); + } catch (Throwable e) { + Log.e(LOG_TAG, "## ensureFcmTokenIsRetrieved() : failed " + e.getMessage(), e); + } + } else { + Toast.makeText(activity, R.string.no_valid_google_play_services_apk, Toast.LENGTH_SHORT).show(); + Log.e(LOG_TAG, "No valid Google Play Services found. Cannot use FCM."); + } + } + } + + /** + * Check the device to make sure it has the Google Play Services APK. If + * it doesn't, display a dialog that allows users to download the APK from + * the Google Play Store or enable it in the device's system settings. + */ + private static boolean checkPlayServices(Activity activity) { + GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); + int resultCode = apiAvailability.isGooglePlayServicesAvailable(activity); + if (resultCode != ConnectionResult.SUCCESS) { + if (apiAvailability.isUserResolvableError(resultCode)) { + apiAvailability.getErrorDialog(activity, resultCode, 9000 /*hey does the magic number*/) + .show(); } + return false; } + return true; } } diff --git a/vector/src/main/java/im/vector/activity/SplashActivity.java b/vector/src/main/java/im/vector/activity/SplashActivity.java index 86ec636e18..41b7c8e907 100755 --- a/vector/src/main/java/im/vector/activity/SplashActivity.java +++ b/vector/src/main/java/im/vector/activity/SplashActivity.java @@ -45,6 +45,7 @@ import im.vector.VectorApp; import im.vector.analytics.TrackingEvent; import im.vector.push.PushManager; +import im.vector.push.fcm.FcmHelper; import im.vector.receiver.VectorUniversalLinkReceiver; import im.vector.services.EventStreamService; import im.vector.util.PreferencesManager; @@ -321,10 +322,27 @@ public void onInitialSyncComplete(String toToken) { // trigger the push registration if required PushManager pushManager = Matrix.getInstance(getApplicationContext()).getPushManager(); - if (!pushManager.isFcmRegistered()) { - pushManager.checkRegistrations(); + if (pushManager.isFcmRegistered()) { + + //Issue #2266 It might be possible that the FCMHelper saved token is different + //than the push manager saved token, and that the pushManager is not aware. + //And as per current code the pushMgr saved token is sent at each startup (resume?) + //So anyway, might be a good thing to check that it is synced? + //Very defensive code but, ya know :/ + String fcmToken = FcmHelper.getFcmToken(this); + String pushMgrSavedToken = pushManager.getCurrentRegistrationToken(); + + boolean savedTokenAreDifferent = pushMgrSavedToken == null ? fcmToken != null : !pushMgrSavedToken.equals(fcmToken); + if (savedTokenAreDifferent) { + Log.e(LOG_TAG, "SAVED NOTIFICATION TOKEN NOT IN SYNC"); + pushManager.resetFCMRegistration(fcmToken); + } else { + pushManager.forceSessionsRegistration(null); + } + + } else { - pushManager.forceSessionsRegistration(null); + pushManager.checkRegistrations(); } boolean noUpdate; diff --git a/vector/src/main/java/im/vector/push/PushManager.java b/vector/src/main/java/im/vector/push/PushManager.java index 53eee4ed5d..eac3b970a1 100755 --- a/vector/src/main/java/im/vector/push/PushManager.java +++ b/vector/src/main/java/im/vector/push/PushManager.java @@ -320,11 +320,17 @@ public void onNetworkError(Exception e) { @Override public void onMatrixError(MatrixError e) { Log.d(LOG_TAG, "resetFCMRegistration : un-registration failed."); + //we can assume that it may have succeeded anyway + setAndStoreRegistrationState(RegistrationState.FCM_REGISTERED); + resetFCMRegistration(newToken); } @Override public void onUnexpectedError(Exception e) { Log.d(LOG_TAG, "resetFCMRegistration : un-registration failed."); + //we can assume that it may have succeeded anyway + setAndStoreRegistrationState(RegistrationState.FCM_REGISTERED); + resetFCMRegistration(newToken); } }); } else { diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 5447d8e1bb..cd4aaf3dc2 100755 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1094,5 +1094,6 @@ %1$s: %2$s +%d %d+ + No valid Google Play Services APK found. Notifications won\'t work properly