GCM(Google Cloud Messaging for Android)は、
開発者がサーバからAndroidデバイス上のAndroidアプリケーションに対して、
データを送信できるようにする仕組みです。
Developers Consoleの準備
Developers Consoleにて、アプリケーションを登録してAPI実行に必要なKey情報を取得します。
1.任意のアプリケーションを作成する
アプリケーションを作成すると、APIコンソールのDashboardにProject Number
が表示されます。
この数字は、後ほど作成するGCM受信アプリにて、登録ID(registration ID)取得の際に必要になるので覚えておきます。
2.GCMの設定を有効にする
APIs & auth
を選択し、表示されるリストの中からGoogle Cloud Messaging for Android
を探してONにします。
3. API Keyを発行する
API Keyを作成するには、左メニューのAPIs & auth
> credential
ボタンを押下し、
Public API access
領域にあるCREATE NEW KEY
ボタンを押下します 。
以下のように作成するキーを選択するダイアログが表示されるます。
今回は、Pushの確認テストとしてサーバーからリクエストを送るため、Server key
を選択します。
Server key
ボタンを押下すると、アクセスを許可するIPアドレスを設定するためのダイアログが表示されるので、
アクセスを許可するグローバルIPを入力します。
処理が正常に完了すると下記のようにAPI keyが発行されます。
このKeyを使用して、サーバー側からのGCMのメッセージを送信します。(後述)
Androidアプリの準備
GCMを受信するためのAndroidアプリケーションを実装します。
1.GSM用のライブラリをeclipseにimportする
Android SDK Manager
を起動し、Extras
配下のGoogle Play services
を選択し、
importします。
importが完了すると<ANDROID_HOME>/extras/google/google_play_services/libproject/
配下に、google-play-services_lib
というディレクトリがDLされているので、
これをAndroid Project From Exting Code形式でeclipseにimportします。
次に、GCMを受信する為のプロジェクトを新規で作成し、
Projectを選択 > 右クリックでPropertiesを選択 > Androidから、
先ほど、eclipseにimportしたライブラリプロジェクトを追加します。
これで、Android プロジェクトでGCMクラスを使用するための準備は完了です。
2. GCM受信の準備
GCMの通知を受け取るためのReceiverクラスを実装します。
GCMの受信処理中に端末がスリープしないように、ReceiverクラスはWakefulBroadcastReceiver
を継承しています。
WakefulBroadcastReceiver
は、処理を実行している間は、デバイスがスリープしないことが保証できる特殊なReceiverクラスです。
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { public GcmBroadcastReceiver() { super(); } @Override public void onReceive(Context context, Intent intent) { // GCMを受信 メッセージ受信用のサービスを起動する ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName()); startWakefulService(context, (intent.setComponent(comp))); setResultCode(Activity.RESULT_OK); } }
Receiverクラスが受け取ったGCMのインテントを処理するServiceクラスを作成します。
public class GcmIntentService extends IntentService { private static final String TAG = "GcmIntentService"; // 引数なしのコンストラクタを作成しないと例外で落ちてしまった public GcmIntentService() { super(GcmIntentService.class.getName()); } public GcmIntentService(String name) { super(name); } @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); // intentからGCMのメッセージを取得する GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); String messageType = gcm.getMessageType(intent); // GCMのメッセージをタイプ別にフィルタリングする。 // 将来的に拡張されることを考慮し、存在しないタイプを無視するようにする if (!extras.isEmpty()) { if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) { // エラー Log.d(TAG,"messageType: " + messageType + ",send error:" + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) { // サーバー側でメッセージを削除された Log.d(TAG,"messageType: " + messageType + ",message deleted:" + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) { // メッセージ受信 Log.d(TAG,"messageType: " + messageType + ",received message:" + extras.toString()); } } // 処理の終了をReceiverに通知し、ロックを解放する GcmBroadcastReceiver.completeWakefulIntent(intent); } }
3. AndroidManifestを更新する
GCMを受け取るためのPermissionおよび、
上記で実装したメッセージ受信するReceiverクラス、
メッセージを処理するServiceクラスの定義をAndroidManifest
に記載します。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test.gcmtest" android:versionCode="1" android:versionName="1.0" > ・・・ <!-- Permissionの宣言 --> <permission android:name="com.test.gcmtest.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.test.gcmtest.permission.C2D_MESSAGE" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="android.permission.WAKE_LOCK"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > ・・・ <!-- Receiverクラスの宣言 --> <receiver android:name=".GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="com.test.gcmtest" /> </intent-filter> </receiver> <!-- Serviceクラスの宣言 --> <service android:name="com.test.gcmtest.GcmIntentService" /> </application> ・・・
これで、受信側の準備は完了です。
3. GCM送信の準備
次に、サーバーからGCMを送信するために必要なregistration_id
を取得するクラスを実装します。
下記サンプルでは、Activity起動時に非同期でregist処理を行っています。
onPostExecute()
で取得できる文字列がregistration_id
です。
※
gcm.register()
の引数に渡すIDには、Developer Consolに表示されていたProject Number
を指定します。
public class MainActivity extends Activity { private GoogleCloudMessaging gcm; private Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = getApplicationContext(); // GCMクラスを作成して非同期でregist処理を行う。 gcm = GoogleCloudMessaging.getInstance(this); registerInBackground(); } private void registerInBackground() { new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { String msg = ""; try { if (gcm == null) { gcm = GoogleCloudMessaging.getInstance(context); } String regid = gcm.register("<app_id>"); msg = regid; Log.d("tag", "Device registered, registration ID=" + msg); } catch (IOException ex) { msg = "Error :" + ex.getMessage(); } return msg; } @Override protected void onPostExecute(String msg) { // registration IDを取得 // 従来であれば、ここから送信サーバーへregistration IDを送信するような流れになる Log.d("tag", msg); } }.execute(null, null, null); } }
GCMのテスト送信
最後に、サーバーからのGCMテスト送信を行います。
下記、curlコマンドでは、
Developers Consoleの準備
手順で取得したAPI Key
と上記で取得したregistration ID
を使って、
作成したAndroidアプリへ”Hello”という文字列を送信しています。
curl --header "Authorization: key=<API Key>" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"<registration ID>\"],\"data\":{\"message\":\"Hello\"}}"
参考
http://zatomiya.blogspot.jp/2013/05/androidnotification.html
http://dev.classmethod.jp/smartphone/android/gcm/
http://developer.android.com/google/gcm/gs.html
http://developer.android.com/google/gcm/client.html