<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