Firebase Cloud Messaging (FCM) is the new version of GCM. It inherits the reliable and scalable GCM infrastructure, plus new features! See the FAQ to learn more. If you are integrating messaging in a new app, start with FCM. GCM users are strongly recommended to upgrade to FCM, in order to benefit from new FCM features today and in the future.

Deprecated: Obtaining Registration Tokens with gcm.register()

Registration state sync handling

There are two scenarios that require special care when using register():

  • Client app update
  • Backup and restore

Client app update: When a client app is updated, it should invalidate its existing registrationID, as it is not guaranteed to work with the new version. The recommended way is to store the current app version when a registration ID is stored. When the client app starts, compare the stored value with the current app version. If they do not match, invalidate the stored data and start the registration process again.

Backup and restore: You should not save the registration ID when a client app is backed up. This is because the registration ID could become invalid by the time the client app is restored, which would put the client app in an invalid state (that is, the app thinks it is registered, but GCM does not store that registration ID anymore—thus the app will no longer get messages). The best practice is to initiate the registration process as if the app has been installed for the first time.

Receiving messages from multi-senders

To receive messages from multi-senders, a client app calls register() with all the app server’s senderIDs, separated by commas.

Implementing register() in a client app

In the following snippet the onCreate() method in the sample app's main activity checks to see if the app is already registered with GCM and with the server:

/**
 * Main UI for the demo app.
 */
public class DemoActivity extends Activity {

    public static final String EXTRA_MESSAGE = "message";
    public static final String PROPERTY_REG_ID = "registration_id";
    private static final String PROPERTY_APP_VERSION = "appVersion";
    private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

    /**
     * Substitute you own sender ID here. This is the project number you got
     * from the API Console.
     */
    String SENDER_ID = "Your-Sender-ID";

    /**
     * Tag used on log messages.
     */
    static final String TAG = "GCMDemo";

    TextView mDisplay;
    GoogleCloudMessaging gcm;
    AtomicInteger msgId = new AtomicInteger();
    SharedPreferences prefs;
    Context context;

    String regid;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        mDisplay = (TextView) findViewById(R.id.display);

        context = getApplicationContext();

        // Check device for Play Services APK. If check succeeds, proceed with
        //  GCM registration.
        if (checkPlayServices()) {
            gcm = GoogleCloudMessaging.getInstance(this);
            regid = getRegistrationId(context);

            if (regid.isEmpty()) {
                registerInBackground();
            }
        } else {
            Log.i(TAG, "No valid Google Play Services APK found.");
        }
    }
...
}

The app calls getRegistrationId() to see whether there is an existing registration token stored in shared preferences:

/**
 * Gets the current registration token for application on GCM service.
 * <p>
 * If result is empty, the app needs to register.
 *
 * @return registration token, or empty string if there is no existing
 *         registration token.
 */
private String getRegistrationId(Context context) {
    final SharedPreferences prefs = getGCMPreferences(context);
    String registrationId = prefs.getString(PROPERTY_REG_ID, "");
    if (registrationId.isEmpty()) {
        Log.i(TAG, "Registration not found.");
        return "";
    }
    // Check if app was updated; if so, it must clear the registration ID
    // since the existing registration ID is not guaranteed to work with
    // the new app version.
    int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
    int currentVersion = getAppVersion(context);
    if (registeredVersion != currentVersion) {
        Log.i(TAG, "App version changed.");
        return "";
    }
    return registrationId;
}
...
/**
 * @return Application's {@code SharedPreferences}.
 */
private SharedPreferences getGCMPreferences(Context context) {
    // This sample app persists the registration ID in shared preferences, but
    // how you store the registration ID in your app is up to you.
    return getSharedPreferences(DemoActivity.class.getSimpleName(),
            Context.MODE_PRIVATE);
}

If the registration ID doesn't exist or the app was updated, getRegistrationId() returns an empty string to indicate that the app needs to get a new registration ID. getRegistrationId() calls the following method to check the app version:

/**
 * @return Application's version code from the {@code PackageManager}.
 */
private static int getAppVersion(Context context) {
    try {
        PackageInfo packageInfo = context.getPackageManager()
                .getPackageInfo(context.getPackageName(), 0);
        return packageInfo.versionCode;
    } catch (NameNotFoundException e) {
        // should never happen
        throw new RuntimeException("Could not get package name: " + e);
    }
}

If there isn't a valid existing registration ID, DemoActivity calls the following registerInBackground() method to register. Note that because the GCM methods register() and unregister() are blocking, this has to take place on a background thread. This sample uses AsyncTask to accomplish this:

/**
 * Registers the application with GCM connection servers asynchronously.
 * <p>
 * Stores the registration ID and app versionCode in the application's
 * shared preferences.
 */
private void registerInBackground() {
    new AsyncTask() {
        @Override
        protected String doInBackground(Void... params) {
            String msg = "";
            try {
                if (gcm == null) {
                    gcm = GoogleCloudMessaging.getInstance(context);
                }
                regid = gcm.register(SENDER_ID);
                msg = "Device registered, registration ID=" + regid;

                // 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.
                // The request to your server should be authenticated if your app
                // is using accounts.
                sendRegistrationIdToBackend();

                // For this demo: we don't need to send it because the device
                // will send upstream messages to a server that echo back the
                // message using the 'from' address in the message.

                // Persist the registration ID - no need to register again.
                storeRegistrationId(context, regid);
            } catch (IOException ex) {
                msg = "Error :" + ex.getMessage();
                // 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.
            }
            return msg;
        }

        @Override
        protected void onPostExecute(String msg) {
            mDisplay.append(msg + "\n");
        }
    }.execute(null, null, null);
    ...
}

Once you've received your registration ID, send it to your server:

/**
 * Sends the registration ID to your server over HTTP, so it can use GCM/HTTP
 * or CCS to send messages to your app. Not needed for this demo since the
 * device sends upstream messages to a server that echoes back the message
 * using the 'from' address in the message.
 */
private void sendRegistrationIdToBackend() {
    // Your implementation here.
}

After registering, the app calls storeRegistrationId() to store the registration ID in shared preferences for future use. This is just one way of persisting a registration ID. You might choose to use a different approach in your app:

/**
 * Stores the registration ID and app versionCode in the application's
 * {@code SharedPreferences}.
 *
 * @param context application's context.
 * @param regId registration ID
 */
private void storeRegistrationId(Context context, String regId) {
    final SharedPreferences prefs = getGCMPreferences(context);
    int appVersion = getAppVersion(context);
    Log.i(TAG, "Saving regId on app version " + appVersion);
    SharedPreferences.Editor editor = prefs.edit();
    editor.putString(PROPERTY_REG_ID, regId);
    editor.putInt(PROPERTY_APP_VERSION, appVersion);
    editor.commit();
}

Unregistration

A client app can unregister with GCM using unregister(). This unregisters all the registration tokens that the client app has with GCM. This can be used to stop the client app from receiving any messages.

Note that it might take a while for the registration ID be completely removed from GCM. Thus it is possible that messages get a valid message ID as a response, even though the message will not be delivered to the client app. Eventually, the registration ID will be removed and the server will get a NotRegistered error, without any further action being required from the app server (this scenario happens frequently while an app is being developed and tested).

Handle registration errors

An Android app must register with GCM connection servers and get a registration ID before it can receive messages. A given registration ID is not guaranteed to last indefinitely, so the first thing your app should always do is check to make sure it has a valid registration ID (as shown in the code snippets above).

In addition to confirming that it has a valid registration ID, your app should be prepared to handle the registration error TOO_MANY_REGISTRATIONS. This error indicates that the device has too many apps registered with GCM. The error only occurs in cases where there are extreme numbers of apps, so it should not affect the average user. The remedy is to prompt the user to delete some of the other client apps from the device to make room for the new one.

Send feedback about...

Cloud Messaging
Cloud Messaging