今回移行する機会があったので、備忘録もかねて記しておきます。お気づきの点等あればご指摘いただけると幸いです。
2.0ベース実装は前任が担当で、自分にその経験があった訳でもないので、影響範囲の調査からスタートしました。
結論から言うと簡単でした。実装で言えば1人で2時間程度。
3.0では、TopicsやDevice Groupsといった2.0にはない送信方法もありますが、今回これらは使わず、以前からある普通の、registration ID単位での送信を使ってます。
Android側
ざっくり手順です。
- build.gradle等の設定
- 独自のBroadcastReceiver実装を廃止し、代わりにcom.google.android.gms.gcm.GcmReceiverに受信処理を委譲。
- IntentServiceを拡張していたクラスを、GcmListenerServiceの拡張クラスに置き換え。
- トークン更新にまつわるサービスを2つ実装(Googleドキュメントで言うMyInstanceIDListenerServiceとRegistrationIntentService)
実装
マニフェストはこんな感じになりました。
<!-- 上の1の部分 -->
<receiver
- android:name="com.example.android.service.GcmBroadcastReceiver"
android:name="com.example.android.service.GcmBroadcastReceiver" + android:name="com.google.android.gms.gcm.GcmReceiver"
+ android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
- <category android:name="com.example.android.permission.C2D_MESSAGE" />
+ <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
+ <category android:name="com.example.android" />
</intent-filter>
</receiver>
<!-- 同2の部分 -->
- <service android:name="com.example.android.service.GcmIntentService" />
+ <service
+ android:name="com.example.android.service.MyGcmListenerService"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
+ </intent-filter>
+ </service>
+ <!-- 同3 -->
+ <service
+ android:name="com.example.android.service.MyInstanceIDListenerService"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="com.google.android.gms.iid.InstanceID"/>
+ </intent-filter>
+ </service>
以下、個別クラスの実装について書きます。
1. build.gradle周りの設定
基本、参照に記したGoogleドキュメントの通りに設定すればよいです。
プロジェクトルートのbulid.gradleにplay-servicesのclasspassを設定
classpath 'com.google.gms:google-services:1.5.0-beta2'
app/build.gradleに以下をそれぞれ設定
- plugin。これは、playserivceにまつわるAndroid Studioの便利機能を有効にするためのものっぽいので、それらが不要なら付けなくてよさそうです(確認してない)。
apply plugin: 'com.google.gms.google-services'
- play-serviceのライブラリの依存関係を記述。
dependencies {
compile "com.google.android.gms:play-services:8.3.0"
}
2. 独自のBroadcastReceiverの廃止
GCM受信を担っていたBroadcastReceiverは削除します。
com.google.android.gms.gcm.GcmReceiver
については、アプリ側で必要な実装はありません。
3. IntentServiceを拡張していたクラスを、GcmListenerServiceの拡張クラスに置き換える
これまでは、2.で消し去ったBroadcastReceiverからIntentServiceを起動し、onHandleIntent()
にてノーティフィケーションバーに通知を出すなどの処理をしていたと思いますが、この、onHandleIntent()の処理をまるごと、GcmListenerServiceのonMessageReceived()
に移せばOKです。
変わるところと言えば、onHandleIntent()
で渡ってきていたIntentの変わりに、onMessageReceived()
ではBundleが渡ってくるので、IntentからBundleを抜き出す処理が無くなることぐらいです。
4. MyInstanceIDListenerServiceとRegistrationIntentServiceの実装
これはGoogleのサンプルを見るのが早いでしょう。
[MyInstanceIDListenerService]
https://github.com/googlesamples/google-services/blob/master/android/gcm/app/src/main/java/gcm/play/android/samples/com/gcmquickstart/MyInstanceIDListenerService.java
[RegistrationIntentService]
https://github.com/googlesamples/google-services/blob/master/android/gcm/app/src/main/java/gcm/play/android/samples/com/gcmquickstart/RegistrationIntentService.java
アプリ独自でRegistration IDを取得する実装を書く場合には、RegistrationIntentServiceから以下のように抜粋してくればよいでしょう。
import com.google.android.gms.iid.InstanceID;
import com.example.R;
...
// SENDER_IDには自身のアプリのIDを入れる
String senderId = context.getString(SENDER_ID);
InstanceID insId = InstanceID.getInstance(context);
if (enabled) {
// GCM有効にする場合はこちら
regId = insId.getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE);
} else {
// 無効にする場合はこちら
insId.deleteToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE);
}
サーバー側
こちらはとてもらくちんでエンドポイントを3.0用のそれに変更するだけでした。
送信するデータ構造などは2.0から引き継げるようです。
- my $url = 'https://android.googleapis.com/gcm/send'; # GCM 2.0
+ my $url = 'https://gcm-http.googleapis.com/gcm/send'; # GCM 3.0
参照
Googleのドキュメント。