page.title=Getting Started with GCM page.tags="cloud","push","messaging" @jd:body
The sections below guide you through the process of setting up a GCM implementation. Before you start, make sure to set up the Google Play Services SDK. You need this SDK to use the {@code GoogleCloudMessaging} methods. Strictly speaking, the only thing you absolutely need this API for is upstream (device-to-cloud) messaging, but it also offers a streamlined registration API that is recommended.
To create a Google API project:
Note: If you already have existing projects, the first page you see will be the Dashboard page. From there you can create a new project by opening the project drop-down menu (upper left corner) and choosing Other projects > Create.
https://code.google.com/apis/console/#project:4815162342
#project:
(4815162342 in this example). This is your project number, and it will be used later on as the GCM sender ID.To enable the GCM service:
To obtain an API key:
Take note of the API key value (YourKeyWillBeShownHere
) in this example, as it will be used later on.
Note: If you need to rotate the key, click Generate new key. A new key will be created while the old one will still be active for up to 24 hours. If you want to get rid of the old key immediately (for example, if you feel it was compromised), click Delete key.
This section describes the steps involved in writing an Android application that uses GCM.
com.google.android.c2dm.permission.RECEIVE
permission so the Android application can register and receive messages.android.permission.INTERNET
permission so the Android application can send the registration ID to the 3rd party server.android.permission.GET_ACCOUNTS
permission as GCM requires a Google account (necessary only if if the device is running a version lower than Android 4.0.4)android.permission.WAKE_LOCK
permission so the application can keep the processor from sleeping when a message is received. Optional—use only if the app wants to keep the device from sleeping.applicationPackage + ".permission.C2D_MESSAGE
permission to prevent other Android applications from registering and receiving the Android application's
messages. The permission name must exactly match this pattern—otherwise the Android application will not receive the messages.com.google.android.c2dm.intent.RECEIVE
, with the category set
as applicationPackage
. The receiver should require the com.google.android.c2dm.SEND
permission, so that only the GCM
Framework can send a message to it. Note that the receiving
of messages is implemented as an intent.android:minSdkVersion="8"
in the manifest. This
ensures that the Android application cannot be installed in an environment in which it
could not run properly. Here are excerpts from a manifest that supports GCM:
<manifest package="com.example.gcm" ...> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <permission android:name="com.example.gcm.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" /> <application ...> <receiver android:name=".MyBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="com.example.gcm" /> </intent-filter> </receiver> <service android:name=".MyIntentService" /> </application> </manifest>
An Android application running on a mobile device registers to receive messages by calling the {@code GoogleCloudMessaging} method {@code register(senderID...)}. This method registers the application for GCM and returns the registration ID. This streamlined approach replaces the previous GCM registration process.
Finally, write your application. GCM offers a variety of ways to get the job done:
Here is a sample application that illustrates how to use the {@code GoogleCloudMessaging} APIs. In this example, the sender is a CCS echo server. The sample consists of a main Activity ({@code DemoActivity}) and a broadcast receiver ({@code GcmBroadcastReceiver}).
An Android application needs to register with GCM servers before it can receive messages. So in its {@code onCreate()} method, {@code DemoActivity} checks to see whether the app is registered with GCM and with the server:
public class DemoActivity extends Activity { public static final String EXTRA_MESSAGE = "message"; public static final String PROPERTY_REG_ID = "registration_id"; /** * You can use your own project ID instead. This sender is a test CCS * echo server. */ String GCM_SENDER_ID = "Your-Sender-ID"; // Tag for log messages. static final String TAG = "GCMDemo"; TextView mDisplay; GoogleCloudMessaging gcm; AtomicInteger msgId = new AtomicInteger(); SharedPreferences prefs; String regid; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make sure the app is registered with GCM and with the server prefs = getSharedPreferences(DemoActivity.class.getSimpleName(), Context.MODE_PRIVATE); setContentView(R.layout.main); mDisplay = (TextView) findViewById(R.id.display); regid = prefs.getString(PROPERTY_REG_ID, null); // If there is no registration ID, the app isn't registered. // Call registerBackground() to register it. if (regid == null) { registerBackground(); } gcm = GoogleCloudMessaging.getInstance(this); }
If the app isn't registered, {@code DemoActivity} calls the following {@code registerBackground()} method to register it. Note that because GCM methods are blocking, this has to take place on a background thread. This sample uses {@link android.os.AsyncTask} to accomplish this:
private void registerBackground() { new AsyncTask() { @Override protected String doInBackground(Void... params) { String msg = ""; try { regid = gcm.register(GCM_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. // For this demo: we don't need to send it because the device // will send upstream messages to a server that will echo back // the message using the 'from' address in the message. // Save the regid for future use - no need to register again. SharedPreferences.Editor editor = prefs.edit(); editor.putString(PROPERTY_REG_ID, regid); editor.commit(); } catch (IOException ex) { msg = "Error :" + ex.getMessage(); } return msg; } // Once registration is done, display the registration status // string in the Activity's UI. @Override protected void onPostExecute(String msg) { mDisplay.append(msg + "\n"); } }.execute(null, null, null); }
When the user clicks the app's Echo button, the app generates the necessary XMPP stanza for the message, which it sends to the echo server:
public void onClick(final View view) { if (view == findViewById(R.id.send)) { new AsyncTask() { @Override protected String doInBackground(Void... params) { String msg = ""; try { Bundle data = new Bundle(); // data is a key-value pair. data.putString("hello", "world"); String id = Integer.toString(msgId.incrementAndGet()); gcm.send(GCM_SENDER_ID + "@gcm.googleapis.com", id, data); msg = "Sending message"; } catch (IOException ex) { msg = "Error :" + ex.getMessage(); } return msg; } @Override protected void onPostExecute(String msg) { // Displays the text "Sending message" mDisplay.append(msg + "\n"); } }.execute(null, null, null); } }
As described above in Step 1, the app includes a broadcast receiver for the com.google.android.c2dm.intent.RECEIVE
intent. This is the mechanism GCM uses to deliver messages. When {@code onClick()} calls {@code gcm.send()}, it triggers the broadcast receiver's {@code onReceive()} method, which has the responsibility of handling the GCM message. In this sample the receiver's {@code onReceive()} method calls {@code sendNotification()} to put the message into a notification:
public class GcmBroadcastReceiver extends BroadcastReceiver { static final String TAG = "GCMDemo"; public static final int NOTIFICATION_ID = 1; private NotificationManager mNotificationManager; NotificationCompat.Builder builder; Context ctx; @Override public void onReceive(Context context, Intent intent) { GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); ctx = context; String messageType = gcm.getMessageType(intent); if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) { sendNotification("Send error: " + intent.getExtras().toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) { sendNotification("Deleted messages on server: " + intent.getExtras().toString()); } else { sendNotification("Received: " + intent.getExtras().toString()); } setResultCode(Activity.RESULT_OK); } // Put the GCM message into a notification and post it. private void sendNotification(String msg) { mNotificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0, new Intent(ctx, DemoActivity.class), 0); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctx) .setSmallIcon(R.drawable.ic_stat_notification) .setContentTitle("GCM Notification") .setStyle(new NotificationCompat.BigTextStyle() .bigText(msg)) .setContentText(msg); mBuilder.setContentIntent(contentIntent); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } }