Google Cloud Messaging for Android(GCM)を利用するためのメモ。
メモ:
- 最大4kbのペイロード・データのメッセージを送出可能
- Android2.2以上かつGooglePlayStoreがインストールされた端末が必要
- Android3.0以前の端末ではGoogleアカウントがセットアップされている必要がある
- GCMはGoogle Play serviceに組み込まれた(com.google.android.gms.gcm)
- 従来のAPI群は非推奨に(com.google.android.gcm)
- GoogleCloudMessaging(API)の利用にはGoogle Play services version 3.1以上が必要
- メッセージ送信時に対象デバイスがオフラインであってもGCMはこれをキューイング/ストア>再送する機能を持つ
- 3rdPartyサーバはexponential backoffの方式を組み込み、GCMサーバと通信すること
- GCMメッセージはアプリ固有のPermission付きBroadcastIntent経由で通知される
- GCMメッセージを受信すると対象アプリが起動されるため、メッセージ監視のためにアプリ起動し続ける必要はない
- メッセージ処理はWakeLockを取得してService上で実行するが吉
- GCMメッセージを受信したくない場合はunregisterも可能
- Genymotionを使用する場合のBackendサーバアドレスは10.0.3.2
GCM基本フロー
- アプリケーションはGCMを有効化するための登録を行う
- 3rdPartyサーバはデバイス向けメッセージをGCMに送信
- アプリケーションはGCMからメッセージを受信する
準備するもの
- Google API Projectの作成Google Developers Console
- Project Numberを控える(GCM sender IDとして使用.)
- API \& auth.からGoogle Cloud Messaging for Androidを有効化.
- GCMのServer Keyを作成しAPI Key取得(3rdPartyサーバとGCMサーバ間認証で使用)参考:Obtaining an API Key
3rdPartyサーバの作成
GCMサーバ(GCM connection server)とやりとりするサーバを作成する必要があります。
Implementing GCM Server
App Engine Backend with GCM
試験用途であればApp Engine Backend with Google Cloud Messagingで手軽にGCMバックエンドを作成できます。
利用するには新規ModuleとしてBackendモジュールを作成します(AndroidStudio0.8.2以降)。
Backendモジュールの作成から実行までの詳細手順は下記を参考。
“App Engine Backend with Google Cloud Messaging” Template
Backendモジュール導入に必要な作業は次の通りです。
- 取得済みGCMのAPI Keyを登録
- build.gradleの編集
- Backendサーバへのデバイス登録処理の実装
GCM API Keyを登録
Backendモジュールを作成したらGCMのAPI Keyを登録します。
API Keyは<backend>/src/main/webapp/WEB-INF/appengine-web.xmlに定義されているので、
これを取得済みのものに置き換えます。
<property name="gcm.api.key" value="YOUR_KEY_HERE"/>
YOUR_KEY_HEREを取得済みのAPI Keyに置換。
<property name="gcm.api.key" value="AIza..."/>
これでAPI Keyの登録は完了です。
build.gradleの編集
(この作業はAndroidStudio v0.8.2より後のバージョンでは不要になるかもしれません)
AndroidStudio v0.8.2でBackendモジュールとメインとなるappモジュールを関連づけすると、
ビルドで問題(preDexLibraryタスクでOutOfMemoryやIllegalArgumentException)が発生します。
これを回避するためにappからappengine-endpoints(-deps)ライブラリのコンパイル指定をコメントアウトします。
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:19.0.+'
compile 'com.google.android.gms:play-services:5.0.77'
// appengine-endpoints(-deps)はBackendモジュールに含まれているため、appモジュールでの個別指定は不要
// compile 'com.google.appengine:appengine-endpoints:1.9.1'
// compile 'com.google.appengine:appengine-endpoints-deps:1.9.1'
compile project(path: ':gcmbackend', configuration: 'android-endpoints')
}
Backendサーバへのデバイス登録処理の実装
下記のGcmRegistrationAsyncTaskクラスを取り込みます。
2.2. Registering devices with Google Cloud Messaging backend
GcmRegistrationAsyncTaskに定義されているSENDER_IDを自分のもの(GCM APIのProject Number)に置換します。
また、BackendサーバのURIを必要に応じて変更します。
- Android Emulatorを使用している場合:
http://10.0.2.2:8080/_ah/api/(変更なし) - Genymotionを使用している場合:
http://10.0.3.2:8080/_ah/api/
Android Emulatorにおける10.0.2.2はホストループバックインターフェイスのエイリアスです(localhost)。
Genymotionでは10.0.3.2がこれにあたります。
全ての作業が終わったらBackendモジュールを実行し、ローカルサーバを起動します.
localhost:8080でGCMを送信するフォームが表示されます。
適当なActivityからGcmRegistrationAsyncTaskのexecuteを実行するとBackendサーバに端末のRegistrationIDが登録されます。
RegistrationID登録後にGCM送信フォームからテキストを送信すると端末にPush通知が届きます。
Androidアプリケーションの作成
GCMクライアントとなるAndroidアプリケーションを作成する場合はGoogleCloudMessaging APIの使用が推奨されています。
Google Play Serviceのセットアップ
アプリケーションの作成にはGoogle Play Serviceを使用します。
アプリケーションはGoogle Play ServiceのResourceにアクセスするため、単純に.jarを参照するだけでは動作しません。
AndroidStudioの場合はbuild.gradleのdependencyセクションに次を追記します。
dependencies {
compile "com.google.android.gms:play-services:3.1.+"
}
GCMを使用するにはGoogle Play Service3.1以上である必要があります。
AndroidManifest.xmlの編集
次のPermissionを追加します。
com.google.android.c2dm.permission.RECEIVE: GCMサービスへの登録とメッセージ受信に必要android.permission.INTERNET: 3rdPartyサーバへのRegistrationIDの登録に必要android.permission.WAKE_LOCK: (optional)メッセージ受信時のWakeLock取得に必要YourApplicationPackage + ".permission.C2D_MESSAGE": 他アプリからGCMへ登録されることやメッセージを横取りされるのを防ぐのに必要com.google.android.c2dm.intent.RECEIVE: categoryに自アプリのパッケージ名を指定する。GCMメッセージ受信に必要android.permission.GET_ACCOUNTS: GCMに必要なGoogleアカウント情報取得に必要(Android4.0.4以前で必要)
a<!-- AndroidManifest.xml --> <manifest package="com.example"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <!-- Android4.0.4以前をサポートする場合に必要 --> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <!-- YourApplicationPackage + ".permission.C2D_MESSAGE" --> <permission android:name="com.example.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.example.permission.C2D_MESSAGE" />
GCMの有効化
アプリケーションが初めてGCMを利用する前にGoogleCloudMessaging(API)のregister()メソッドを使ってGCMサービスへ登録する必要があります。
このメソッドはRegistrationIDを返します。参考:GoogleCloudMessaging
GCMへサービス登録する前にGoogle Play Serviceの状態をチェックします。
Google Play Serviceが古いバージョンである場合、Google Play Serviceの更新をユーザに促します。
アプリ起動中にGoogle Play Serviceがダウングレードされるケース等を考慮して、バージョンチェックはonResume()で行います。
@Override
protected void onResume() {
super.onResume();
try {
PlayServiceUtil.updatePlayServiceIfNeeded(this, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
MyActivity.this.finish();
}
});
} catch (PlayServiceUtil.PlayServiceException e) {
// Play Serviceが使用できない致命的状態
Log.e(TAG, "Play Service is not available.");
this.finish();
}
}
public static void updatePlayServiceIfNeeded(Activity activity, DialogInterface.OnCancelListener cancelListener) throws PlayServiceException {
final int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity);
switch (status) {
case ConnectionResult.SUCCESS:
return;
case ConnectionResult.SERVICE_DISABLED:
case ConnectionResult.SERVICE_INVALID:
case ConnectionResult.SERVICE_MISSING:
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, activity, 0);
if (cancelListener != null) {
dialog.setOnCancelListener(cancelListener);
}
dialog.show();
return;
default:
throw new PlayServiceException("Play Service is not available. status=" + status);
}
}
メッセージ送信
3rdPartyサーバ(以降”サーバ”)がメッセージ送信する時のシーケンス
- サーバはGCMにメッセージを送信
- GCMサーバは送信対象のデバイスがオフラインであればメッセージをキューイング/ストアする
- GCMサーバは送信対象のデバイスがオンラインになればメッセージを送信する
- デバイスはメッセージを受信すると配送すべきアプリケーションに向けてメッセージをブロードキャストする。
配送されるのはアプリ固有のPermissionが設定されたBroadcastIntent。 - メッセージ処理が些末なものでない場合はPowerManager.WakeLockを取得してService上で実行する
メッセージ受信
デバイスがGCMメッセージを受信した時のシーケンス
- システムは、受信したメッセージからKey/Valueペアを展開
- システムは、com.google.android.c2dm.intent.RECEIVEのIntentとextraにKey/Valueデータを載せてアプリケーションに連携
- アプリケーションはIntentからKey/Valueを展開してデータを受け取る
参考サイト:
1. Google Cloud Messaging -android developers-