package yuku.alkitab.base.sync; import android.os.Build; import android.support.annotation.Nullable; import android.util.Log; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.gcm.GoogleCloudMessaging; import yuku.afw.storage.Preferences; import yuku.alkitab.base.App; import yuku.alkitab.base.storage.NoBackupSharedPreferences; import yuku.alkitab.base.storage.Prefkey; import yuku.alkitab.base.util.Background; import java.io.IOException; import java.util.concurrent.ConcurrentLinkedQueue; public class Gcm { static final String TAG = Gcm.class.getSimpleName(); public static final String SENDER_ID = "596544549791"; public static final String GCM_MESSAGE_KEY_source_installation_id = "source_installation_id"; public static final String GCM_MESSAGE_KEY_encoded_data = "encoded_data"; public interface Listener { /** * Called only when we get a NEW registration id */ void onNewRegistrationId(String registrationId); } private static final ConcurrentLinkedQueue<Listener> listeners = new ConcurrentLinkedQueue<>(); private static boolean checkPlayServices() { final GoogleApiAvailability gaa = GoogleApiAvailability.getInstance(); final int statusCode = gaa.isGooglePlayServicesAvailable(App.context); if (statusCode != ConnectionResult.SUCCESS) { if (gaa.isUserResolvableError(statusCode) && thisIsPlayDevice()) { gaa.showErrorNotification(App.context, statusCode); } else { Log.i(TAG, "This device is not supported."); } return false; } return true; } private static boolean thisIsPlayDevice() { if ("Amazon".equals(Build.MANUFACTURER) && Build.MODEL != null && (Build.MODEL.startsWith("KF") || Build.MODEL.startsWith("Kindle"))) { return false; } if ("qnx".equals(System.getProperty("os.name"))) { return false; } if ("Genymotion".equals(Build.MANUFACTURER)) { return false; } return true; } /** * @param listener to be called if a new registration id is obtained in the background * @return a registration id that is currently stored if any, null otherwise. */ @Nullable public static String renewGcmRegistrationIdIfNeeded(@Nullable final Listener listener) { if (!checkPlayServices()) { Log.i(TAG, "No valid Google Play Services APK found."); return null; } final String registrationId = getStoredRegistrationId(); if (registrationId != null) { return registrationId; } if (listener != null) listeners.add(listener); registerInBackground(); return null; } /** * Returns the GCM registration id, only if it is stored and the app version when the * registration was obtained is still the same as the current one. * * @return null if not available. */ @Nullable private static String getStoredRegistrationId() { final String registrationId = readGcmRegistrationId(); if (registrationId == null) { Log.i(TAG, "Registration not found."); return null; } // Check if app was updated; if so, it must clear the registration ID // since the existing regID is not guaranteed to work with the new // app version. final int registeredVersionCode = Preferences.getInt(Prefkey.gcm_last_app_version_code, Integer.MIN_VALUE); final int currentVersionCode = App.getVersionCode(); if (registeredVersionCode != currentVersionCode) { Log.i(TAG, "App version changed from " + registeredVersionCode + " to " + currentVersionCode); return null; } return registrationId; } private static String readGcmRegistrationId() { final NoBackupSharedPreferences nbsp = NoBackupSharedPreferences.get(); String res = Preferences.getString(Prefkey.gcm_registration_id, null); if (res == null) { res = nbsp.getString(Prefkey.gcm_registration_id.name()); } else { // we need to remove it from the backed up folder and move it to the nonbacked up folder Preferences.remove(Prefkey.gcm_registration_id); nbsp.setString(Prefkey.gcm_registration_id.name(), res); } return res; } private static void registerInBackground() { Background.run(() -> { try { final GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(App.context); final String registrationId = gcm.register(SENDER_ID); Log.i(TAG, "Device registered, registration ID=" + registrationId); // You should send the registration ID to your server over HTTP, // so it can use GCM/HTTP or CCS to send messages to your app. while (true) { final Listener listener = listeners.poll(); if (listener == null) break; listener.onNewRegistrationId(registrationId); } // Persist the regID - no need to register again. Preferences.setInt(Prefkey.gcm_last_app_version_code, App.getVersionCode()); writeGcmRegistrationId(registrationId); } catch (IOException ex) { // If there is an error, don't just keep trying to register. // Require the user to click a button again, or perform exponential back-off. Log.e(TAG, "Error :" + ex.getMessage(), ex); } }); } private static void writeGcmRegistrationId(final String registrationId) { Preferences.remove(Prefkey.gcm_registration_id); NoBackupSharedPreferences.get().setString(Prefkey.gcm_registration_id.name(), registrationId); } }