• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Getting Started with GCM
2page.tags="cloud","push","messaging"
3@jd:body
4
5<div id="qv-wrapper">
6<div id="qv">
7
8
9<h2>In this document</h2>
10
11<ol class="toc">
12<li><a href="#create-proj">Creating a Google API Project</a></li>
13<li><a href="#gcm-service">Enabling the GCM Service</a></li>
14<li><a href="#access-key">Obtaining an API Key</a></li>
15<li><a href="#client">Writing a Client App</a></li>
16<li><a href="#server">Writing the Server Code</a></li>
17</ol>
18
19<h2>See Also</h2>
20
21<ol class="toc">
22<li><a href="https://code.google.com/apis/console">Google APIs Console page</a></li>
23<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
24</ol>
25
26</div>
27</div>
28
29<p>The sections below guide you through the process of setting up a GCM
30implementation.
31Before you start, make sure to <a href="/google/play-services/setup.html">set up
32the Google Play Services SDK</a>. You need this SDK to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> methods.</p>
33
34<p>Note that a full GCM implementation requires a server-side implementation, in addition to the client implementation in your app. This document offers a complete example that includes both the client and server.</p>
35
36
37<h2 id="create-proj">Creating a Google API project</h2>
38<p>To create a Google API project:</p>
39<ol>
40  <li>Open the <a href="https://code.google.com/apis/console">Google APIs Console page</a>.
41  </li>
42  <li>If you haven't created an API project yet, this page will prompt you to do so:
43  <p><img src="{@docRoot}images/gcm/gcm-create-api-proj.png" class="screenshot" /></p>
44<p class="note"><strong>Note:</strong> If you already have existing projects, the first page you see will be the <strong>Dashboard</strong> page. From there you can create a new project by opening the project drop-down menu (upper left corner) and choosing <strong>Other projects > Create</strong>.</p></li>
45  <li> Click <strong>Create project</strong>.
46    Your browser URL will change to something like:</li>
47
48<pre> https://code.google.com/apis/console/#project:<strong>4815162342</strong></pre>
49
50  <li> Take note of the value after <code>#project:</code> (4815162342 in this example). This is your project number, and it will be used later on as the GCM sender ID.</li>
51
52</ol>
53<h2 id="gcm-service">Enabling the GCM Service</h2>
54<p>To enable the GCM service:</p>
55<ol>
56  <li> In the main Google APIs Console page, select <strong>Services</strong>.</li>
57  <li>Turn the <strong>Google Cloud Messaging</strong> toggle to ON.</li>
58  <li>In the Terms of Service page, accept the terms.
59  </li>
60</ol>
61<h2 id="access-key">Obtaining an API Key</h2>
62<p>To obtain an API  key:</p>
63<ol>
64  <li> In the main Google APIs Console page, select <strong>API Access</strong>. You will see a screen that resembles the following:</li><br />
65
66
67<img src="{@docRoot}images/gcm/gcm-api-access.png" style="width:400px;padding:4px;margin-bottom:0em;">
68
69
70  <li>Click  <strong>Create new Server key</strong>. Either a server key or a browser key should work. The advantage to using a server key is that it allows you to whitelist IP addresses. The following screen appears:</li><br />
71
72
73<img src="{@docRoot}images/gcm/gcm-config-server-key.png" style="width:400px;padding:4px;margin-bottom:0em;">
74
75
76  <li>Click <strong>Create</strong>:</li><br />
77
78
79<img src="{@docRoot}images/gcm/gcm-api-key.png" style="width:400px;padding:4px;margin-bottom:0em;">
80
81
82
83</ol>
84<p> Take note of the <strong>API key</strong> value (<code>YourKeyWillBeShownHere</code>) in this example, as it will be used later on.</p>
85<p class="note"><strong>Note:</strong> If you need to rotate the key, click  <strong>Generate new key</strong>. 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 <strong>Delete key</strong>.</p>
86
87<p>The following sections walk you through the steps of creating client and server-side code.</p>
88
89<h2 id="client">Writing a Client App</h2>
90
91<p>This section walks you through the steps involved in writing a client-side application&mdash;that is, the GCM-enabled application that runs on an Android device. This client sample is designed to work in conjunction with the server code shown in <a href="#server">Writing the Server Code</a>, below.</p>
92
93
94
95<h3 id="manifest">Step 1: Edit Your App's Manifest</h3>
96<ul>
97  <li>The <code>com.google.android.c2dm.permission.RECEIVE</code> permission so the Android application can register and receive messages.</li>
98  <li>The <code>android.permission.INTERNET</code> permission so the Android application can send the registration ID to the 3rd party server.</li>
99  <li>The <code>android.permission.GET_ACCOUNTS</code> permission as GCM requires a Google account (necessary only if if the device is running a version lower than Android 4.0.4)</li>
100  <li>The <code>android.permission.WAKE_LOCK</code> permission so the application can keep the processor from sleeping when a message is received. Optional&mdash;use only if the app wants to keep the device from sleeping.</li>
101  <li>An <code>applicationPackage + &quot;.permission.C2D_MESSAGE&quot;</code> permission to prevent other Android applications from registering and receiving the Android application's
102messages. The permission name must exactly match this pattern&mdash;otherwise the Android application will not receive the messages.</li>
103   <li>A receiver for <code>com.google.android.c2dm.intent.RECEIVE</code>, with the category set
104as <code>applicationPackage</code>. The receiver should require the <code>com.google.android.c2dm.SEND</code> permission, so that only the GCM
105Framework can send a message to it. Note that the receiving
106of messages is implemented as an <a href="{@docRoot}guide/components/intents-filters.html">intent</a>.</li>
107  <li>An intent service to handle the intents received by the broadcast receiver. Optional.</li>
108  <li>If the GCM feature is critical to the Android application's function, be sure to
109set <code>android:minSdkVersion=&quot;8&quot;</code> in the manifest. This
110ensures that the Android application cannot be installed in an environment in which it
111could not run properly. </li>
112</ul>
113
114<p>Here are excerpts from a manifest that supports GCM:</p>
115
116<pre class="prettyprint pretty-xml">
117&lt;manifest package="com.example.gcm" ...&gt;
118
119    &lt;uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/&gt;
120    &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
121    &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
122    &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
123    &lt;uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /&gt;
124
125    &lt;permission android:name="com.example.gcm.permission.C2D_MESSAGE"
126        android:protectionLevel="signature" /&gt;
127    &lt;uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" /&gt;
128
129    &lt;application ...&gt;
130        &lt;receiver
131            android:name=".MyBroadcastReceiver"
132            android:permission="com.google.android.c2dm.permission.SEND" &gt;
133            &lt;intent-filter&gt;
134                &lt;action android:name="com.google.android.c2dm.intent.RECEIVE" /&gt;
135                &lt;category android:name="com.example.gcm" /&gt;
136            &lt;/intent-filter&gt;
137        &lt;/receiver&gt;
138        &lt;service android:name=".MyIntentService" /&gt;
139    &lt;/application&gt;
140
141&lt;/manifest&gt;
142</pre>
143
144
145<h3 id="register">Step 2: Register for GCM</h3>
146
147<p>An Android application running on a mobile device registers to receive messages by calling
148the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> method
149<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html#register">{@code register(senderID...)}</a>.
150This method registers the application for GCM and returns the registration ID. This streamlined approach replaces the previous
151GCM registration process. See the example below for details.</p>
152
153<h3 id="app"> Step 3: Write Your Application</h3>
154
155<p>Finally, write your application. GCM offers a variety of ways to get the job done:</p>
156
157<ul>
158  <li>For your messaging server, you can either use the new <a href="ccs.html">GCM Cloud Connection Server</a> (CCS), the older <a href="gcm.html">GCM HTTP server</a>, or both in tandem. For more discussion, see see <a href="server.html">GCM Server</a>.</li>
159  <li>To write your client application (that is, the GCM-enabled app that runs on an Android device), use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs as shown below. Don't forget to set up your project to use the Google Play services SDK as described in <a href="/google/play-services/setup.html">Setup Google Play Services SDK</a>.</li>
160</ul>
161</li>
162
163</ul>
164
165<h4 id="example">Example</h4>
166
167<p>Here is a sample client application that illustrates how to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. The sample consists of a main activity ({@code DemoActivity}) and a broadcast receiver ({@code GcmBroadcastReceiver}). You can use this client sample code in conjunction with the server code shown in <a href="#server">Writing the Server Code</a>.</p>
168
169<p>Note the following:</p>
170
171<ul>
172  <li>The sample primarily illustrates two things: registration, and upstream messaging. Upstream messaging only applies to apps that are running against a <a href="ccs.html">CCS</a> server; HTTP-based servers don't support upstream messaging.</li>
173  <li>The <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> registration APIs replace the old registration process, which was based on the now-obsolete client helper library. While the old registration process still works, we encourage you to use the newer <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> registration APIs, regardless of your underlying server.</li>
174</ul>
175
176<h5>Registering</h5>
177<p>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:</p>
178
179<pre>/**
180 * Main UI for the demo app.
181 */
182public class DemoActivity extends Activity {
183
184    public static final String EXTRA_MESSAGE = "message";
185    public static final String PROPERTY_REG_ID = "registration_id";
186    private static final String PROPERTY_APP_VERSION = "appVersion";
187    private static final String PROPERTY_ON_SERVER_EXPIRATION_TIME =
188            "onServerExpirationTimeMs";
189    /**
190     * Default lifespan (7 days) of a reservation until it is considered expired.
191     */
192    public static final long REGISTRATION_EXPIRY_TIME_MS = 1000 * 3600 * 24 * 7;
193
194    /**
195     * Substitute you own sender ID here.
196     */
197    String SENDER_ID = "Your-Sender-ID";
198
199    /**
200     * Tag used on log messages.
201     */
202    static final String TAG = "GCMDemo";
203
204    TextView mDisplay;
205    GoogleCloudMessaging gcm;
206    AtomicInteger msgId = new AtomicInteger();
207    SharedPreferences prefs;
208    Context context;
209
210    String regid;
211
212    &#64;Override
213    public void onCreate(Bundle savedInstanceState) {
214        super.onCreate(savedInstanceState);
215
216        setContentView(R.layout.main);
217        mDisplay = (TextView) findViewById(R.id.display);
218
219        context = getApplicationContext();
220        regid = getRegistrationId(context);
221
222        if (regid.length() == 0) {
223            registerBackground();
224        }
225        gcm = GoogleCloudMessaging.getInstance(this);
226    }
227...
228}</pre>
229
230<p>The app calls {@code getRegistrationId()} to see whether there is an existing registration ID stored in shared preferences:</p>
231
232<pre>/**
233 * Gets the current registration id for application on GCM service.
234 * &lt;p&gt;
235 * If result is empty, the registration has failed.
236 *
237 * &#64;return registration id, or empty string if the registration is not
238 *         complete.
239 */
240private String getRegistrationId(Context context) {
241    final SharedPreferences prefs = getGCMPreferences(context);
242    String registrationId = prefs.getString(PROPERTY_REG_ID, "");
243    if (registrationId.length() == 0) {
244        Log.v(TAG, "Registration not found.");
245        return "";
246    }
247    // check if app was updated; if so, it must clear registration id to
248    // avoid a race condition if GCM sends a message
249    int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
250    int currentVersion = getAppVersion(context);
251    if (registeredVersion != currentVersion || isRegistrationExpired()) {
252        Log.v(TAG, "App version changed or registration expired.");
253        return "";
254    }
255    return registrationId;
256}
257
258...
259
260/**
261 * &#64;return Application's {&#64;code SharedPreferences}.
262 */
263private SharedPreferences getGCMPreferences(Context context) {
264    return getSharedPreferences(DemoActivity.class.getSimpleName(),
265            Context.MODE_PRIVATE);
266}</pre>
267
268<p>If the registration ID doesn't exist, or the app was updated, or the registration ID has expired, {@code getRegistrationId()} returns an empty string to indicate that the app needs to get a new regID. {@code getRegistrationId()} calls the following methods to check the app version and whether the regID has expired:</p>
269
270<pre>/**
271 * &#64;return Application's version code from the {&#64;code PackageManager}.
272 */
273private static int getAppVersion(Context context) {
274    try {
275        PackageInfo packageInfo = context.getPackageManager()
276                .getPackageInfo(context.getPackageName(), 0);
277        return packageInfo.versionCode;
278    } catch (NameNotFoundException e) {
279        // should never happen
280        throw new RuntimeException("Could not get package name: " + e);
281    }
282}
283
284/**
285 * Checks if the registration has expired.
286 *
287 * &lt;p&gt;To avoid the scenario where the device sends the registration to the
288 * server but the server loses it, the app developer may choose to re-register
289 * after REGISTRATION_EXPIRY_TIME_MS.
290 *
291 * &#64;return true if the registration has expired.
292 */
293private boolean isRegistrationExpired() {
294    final SharedPreferences prefs = getGCMPreferences(context);
295    // checks if the information is not stale
296    long expirationTime =
297            prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1);
298    return System.currentTimeMillis() > expirationTime;
299}</pre>
300
301
302<p>If there isn't a valid existing registration ID, {@code DemoActivity} calls the following {@code registerBackground()} method to register. 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:</p>
303
304<pre>
305/**
306 * Registers the application with GCM servers asynchronously.
307 * &lt;p&gt;
308 * Stores the registration id, app versionCode, and expiration time in the
309 * application's shared preferences.
310 */
311private void registerBackground() {
312    new AsyncTask<Void, Void, String>() {
313        &#64;Override
314        protected String doInBackground(Void... params) {
315            String msg = "";
316            try {
317                if (gcm == null) {
318                    gcm = GoogleCloudMessaging.getInstance(context);
319                }
320                regid = gcm.register(SENDER_ID);
321                msg = "Device registered, registration id=" + regid;
322
323                // You should send the registration ID to your server over HTTP,
324                // so it can use GCM/HTTP or CCS to send messages to your app.
325
326                // For this demo: we don't need to send it because the device
327                // will send upstream messages to a server that echo back the message
328                // using the 'from' address in the message.
329
330                // Save the regid - no need to register again.
331                setRegistrationId(context, regid);
332            } catch (IOException ex) {
333                msg = "Error :" + ex.getMessage();
334            }
335            return msg;
336        }
337
338        &#64;Override
339        protected void onPostExecute(String msg) {
340            mDisplay.append(msg + "\n");
341        }
342    }.execute(null, null, null);
343}</pre>
344
345<p>After registering, the app calls {@code setRegistrationId()} to store the registration ID in shared preferences for future use:</p>
346
347<pre>/**
348 * Stores the registration id, app versionCode, and expiration time in the
349 * application's {&#64;code SharedPreferences}.
350 *
351 * &#64;param context application's context.
352 * &#64;param regId registration id
353 */
354private void setRegistrationId(Context context, String regId) {
355    final SharedPreferences prefs = getGCMPreferences(context);
356    int appVersion = getAppVersion(context);
357    Log.v(TAG, "Saving regId on app version " + appVersion);
358    SharedPreferences.Editor editor = prefs.edit();
359    editor.putString(PROPERTY_REG_ID, regId);
360    editor.putInt(PROPERTY_APP_VERSION, appVersion);
361    long expirationTime = System.currentTimeMillis() + REGISTRATION_EXPIRY_TIME_MS;
362
363    Log.v(TAG, "Setting registration expiry time to " +
364            new Timestamp(expirationTime));
365    editor.putLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, expirationTime);
366    editor.commit();
367}</pre>
368
369<h5>Sending a message</h5>
370<p>When the user clicks the app's <strong>Send</strong> button, the app sends an upstream message using the new <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. In order to receive the upstream message, your server should be connected to CCS. You can use the code shown in <a href="#server">Writing the Server Code</a> as a sample XMPP client to connect to CCS.</p>
371
372<pre>public void onClick(final View view) {
373    if (view == findViewById(R.id.send)) {
374        new AsyncTask<Void, Void, String>() {
375            &#64;Override
376            protected String doInBackground(Void... params) {
377                String msg = "";
378                try {
379                    Bundle data = new Bundle();
380                    data.putString("hello", "World");
381                    String id = Integer.toString(msgId.incrementAndGet());
382                    gcm.send(SENDER_ID + "&#64;gcm.googleapis.com", id, data);
383                    msg = "Sent message";
384                } catch (IOException ex) {
385                    msg = "Error :" + ex.getMessage();
386                }
387                return msg;
388            }
389
390            &#64;Override
391            protected void onPostExecute(String msg) {
392                mDisplay.append(msg + "\n");
393            }
394        }.execute(null, null, null);
395    } else if (view == findViewById(R.id.clear)) {
396        mDisplay.setText("");
397    }
398}</pre>
399
400<p>As described above in <a href="#manifest">Step 1</a>, the app includes a broadcast receiver for the <code>com.google.android.c2dm.intent.RECEIVE</code> 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:</p>
401
402<pre>/**
403 * Handling of GCM messages.
404 */
405public class GcmBroadcastReceiver extends BroadcastReceiver {
406    static final String TAG = "GCMDemo";
407    public static final int NOTIFICATION_ID = 1;
408    private NotificationManager mNotificationManager;
409    NotificationCompat.Builder builder;
410    Context ctx;
411    &#64;Override
412    public void onReceive(Context context, Intent intent) {
413        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
414        ctx = context;
415        String messageType = gcm.getMessageType(intent);
416        if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
417            sendNotification("Send error: " + intent.getExtras().toString());
418        } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
419            sendNotification("Deleted messages on server: " +
420                    intent.getExtras().toString());
421        } else {
422            sendNotification("Received: " + intent.getExtras().toString());
423        }
424        setResultCode(Activity.RESULT_OK);
425    }
426
427    // Put the GCM message into a notification and post it.
428    private void sendNotification(String msg) {
429        mNotificationManager = (NotificationManager)
430                ctx.getSystemService(Context.NOTIFICATION_SERVICE);
431
432        PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
433                new Intent(ctx, DemoActivity.class), 0);
434
435        NotificationCompat.Builder mBuilder =
436                new NotificationCompat.Builder(ctx)
437        .setSmallIcon(R.drawable.ic_stat_gcm)
438        .setContentTitle("GCM Notification")
439        .setStyle(new NotificationCompat.BigTextStyle()
440        .bigText(msg))
441        .setContentText(msg);
442
443        mBuilder.setContentIntent(contentIntent);
444        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
445    }
446}</pre>
447
448<h2 id="server">Writing the Server Code</h2>
449
450<p>Here is an example of a CCS server written in Python. You can use this in conjunction with the sample client code shown above. This sample echo server sends an initial message, and for every upstream message received, it sends a dummy response back to the application that sent the upstream message. This example illustrates how to connect,
451send, and receive GCM messages using XMPP. It shouldn't be used as-is
452on a production deployment. For examples of HTTP-based servers, see <a href="server.html">GCM Server</a>.</p>
453
454<pre>
455#!/usr/bin/python
456import sys, json, xmpp, random, string
457
458SERVER = 'gcm.googleapis.com'
459PORT = 5235
460USERNAME = ''
461PASSWORD = ''
462REGISTRATION_ID = ''
463
464unacked_messages_quota = 1000
465send_queue = []
466
467# Return a random alphanumerical id
468def random_id():
469  rid = ''
470  for x in range(8): rid += random.choice(string.ascii_letters + string.digits)
471  return rid
472
473def message_callback(session, message):
474  global unacked_messages_quota
475  gcm = message.getTags('gcm')
476  if gcm:
477    gcm_json = gcm[0].getData()
478    msg = json.loads(gcm_json)
479    if not msg.has_key('message_type'):
480      # Acknowledge the incoming message immediately.
481      send({'to': msg['from'],
482            'message_type': 'ack',
483            'message_id': msg['message_id']})
484      # Queue a response back to the server.
485      if msg.has_key('from'):
486        # Send a dummy echo response back to the app that sent the upstream message.
487        send_queue.append({'to': msg['from'],
488                           'message_id': random_id(),
489                           'data': {'pong': 1}})
490    elif msg['message_type'] == 'ack' or msg['message_type'] == 'nack':
491      unacked_messages_quota += 1
492
493def send(json_dict):
494  template = (&quot;&lt;message&gt;&lt;gcm xmlns='google:mobile:data'&gt;{1}&lt;/gcm&gt;&lt;/message&gt;&quot;)
495  client.send(xmpp.protocol.Message(
496      node=template.format(client.Bind.bound[0], json.dumps(json_dict))))
497
498def flush_queued_messages():
499  global unacked_messages_quota
500  while len(send_queue) and unacked_messages_quota &gt; 0:
501    send(send_queue.pop(0))
502    unacked_messages_quota -= 1
503
504client = xmpp.Client('gcm.googleapis.com', debug=['socket'])
505client.connect(server=(SERVER,PORT), secure=1, use_srv=False)
506auth = client.auth(USERNAME, PASSWORD)
507if not auth:
508  print 'Authentication failed!'
509  sys.exit(1)
510
511client.RegisterHandler('message', message_callback)
512
513send_queue.append({'to': REGISTRATION_ID,
514                   'message_id': 'reg_id',
515                   'data': {'message_destination': 'RegId',
516                            'message_id': random_id()}})
517
518while True:
519  client.Process(1)
520  flush_queued_messages()</pre>
521
522
523
524