<uses-permission android:name="android.permission.INTERNET" /> Everything is clear, we don’t need GCM without Internet access. <uses-permission android:name="android.permission.GET_ACCOUNTS" /> GCM requires access to Google account <uses-permission android:name="android.permission.WAKE_LOCK"/> On this occasion, there was even a dispute in the previous topic, but none of the participants decided to look at the source code. Documentation is silent on this moment, and only says that you may want to grab PowerManager.WakeLock . So, if you use the standard GCM library, then you will have to add such permission.setClassName() ) in the name of our service extending GCMBaseIntentService , then we capture WakeLock with the PowerManager.PARTIAL_WAKE_LOCK flag (we don’t let only the CPU fall asleep, the screen and so on sleep peacefully), start Intent as a service, on exit from the onHandleIntent service, release WakeLock . java.lang.SecurityException: Neither user 10110 nor current process has android.permission.WAKE_LOCK. <permission android:name="{ }.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="{ }.permission.C2D_MESSAGE" /> We create our own permission and request it ourselves. We do this so that no one except us can receive our messages.minSdkVersion to 16 or higher (Jelly Bean and later versions), then you don’t need this permission (after 2 years, I hope, you can omit it). <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> Actually permission to register in GCM and receive messages. final String regId = GCMRegistrar.getRegistrationId(this); if (regId.equals("")) { // Automatically registers application on startup. GCMRegistrar.register(this, SENDER_ID); } import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.preference.PreferenceManager; public final class ApplicationVersionHelper { public static final String APP_VERSION_PREFS = "application_version"; public static boolean isApplicationVersionCodeEqualsSavedApplicationVersionCode(Context context) { return getApplicationVersionCode(context) == getApplicationVersionCodeFromPreferences(context); } public static int getApplicationVersionCode(Context context) { PackageManager pm = context.getPackageManager(); PackageInfo packageInfo; int applicationVersion = 1; try { packageInfo = pm.getPackageInfo(context.getPackageName(), 0); applicationVersion = packageInfo.versionCode; } catch (NameNotFoundException ignored) { } return applicationVersion; } public static int getApplicationVersionCodeFromPreferences(Context context) { return context.getSharedPreferences(APP_VERSION_PREFS, Context.MODE_PRIVATE).getInt("application_version_code", 0); } public static void putCurrentPackageVersionInPreferences(Context context) { context.getSharedPreferences(APP_VERSION_PREFS, Context.MODE_PRIVATE).edit().putInt("application_version_code", getApplicationVersionCode(context)).commit(); } } PreferenceManager.getDefaultSharedPreferences , but through the named settings file. For what this is done, I will explain later.putCurrentPackageVersionInPreferences after successful registration in GCM and on our service, and the registration verification code turns into: final String regId = GCMRegistrar.getRegistrationId(this); if (regId.equals("") || !isApplicationVersionCodeEqualsSavedApplicationVersionCode(this)) { // Automatically registers application on startup. GCMRegistrar.register(this, SENDER_ID); } ApplicationVersionHelper.APP_VERSION_PREFS constant when backing up. So the named settings file came in handy :) Then isApplicationVersionCodeEqualsSavedApplicationVersionCode will return false when recovering the data and we will send a request for registration.GCMIntentService (class inherited from GCMBaseIntentService ) protected void onRegistered(Context context, String registrationId) this method is called after successful registration in GCM, from here we need to transfer registrationId to our server protected void onUnregistered(Context context, String registrationId) This method is called after a successful cancellation of registration in GCM, we also transfer registrationId to our server for exclusion from mailing (many applications will never use this feature) protected void onMessage(Context context, Intent intent) receiving a message from GCM, if there is a payload (payload), then the data lies in the intent protected void onDeletedMessages(Context context, int total) Receive notification from GCM about deleted messages, what it is and with what they are, see here - http://developer.android.com/intl/ru/guide/google/gcm/adv.html#payload public void onError(Context context, String errorId) unrecoverable error while retrieving data, errorId error code protected boolean onRecoverableError(Context context, String errorId) recoverable error when receiving data in errorId error code. If we return true , then let us make another attempt, if false , then we will stop trying. I recommend returning super.onRecoverableError(context, errorId); in this method super.onRecoverableError(context, errorId); @Override protected void onDestroy() { if (registerTask != null) { registerTask.cancel(true); } try { CMRegistrar.onDestroy(this); } catch(Exception ignored) { } super.onDestroy(); } registerTask here - asynchronous task ( AsyncTask ).Source: https://habr.com/ru/post/147739/
All Articles