ちょっと話題の記事

[改訂版]Google Cloud Messaging (GCM) でプッシュ配信する[Android]

2013.12.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Google Cloud Messagingの使い方が少々変わっていたらしい

以前弊社の記事で、 Google Cloud Messaging(以下GCM)のセットアップから使い方について紹介しました。
※GCMとは、AndroidでPush通知を利用するための仕組みです

最近仕事でGCMを使う機会があり、記事を参考にセットアップしようとしたのですが、
どうやら最近はセットアップ方法が前と少し変わっているみたいだったので、ここにあるサンプルと以前の記事を参考にして、
最近のGCMセットアップ&実装をあらためてやってみます。

環境構築方法

今回使用した動作環境は以下のとおりです。

  • OS : MacOS X 10.9
  • Eclipse : 4.2

ADT Pluginはインストール済み、GCMを実装するサンプルのAndroidプロジェクトは作成済みとします。

サンプルプログラムの作成

1.APIコンソール設定

まずは、Google Cloud Consoleにアクセスします。
※Projectを作成していなければ作成します
任意のプロジェクトを選択し、左のメニューからAPIs & authへアクセスします。
Google Cloud Messaging for Androidを選択し、onにしましょう。
APIコンソール自体も、以前と比べるとけっこう変化していますね。

次に、メニューのAPIs&authのRegistered appsを選択して、必要事項を入力してREGISTER APPボタンを押します。
アプリを登録することで、API KEYが発行されます。これはPUSHメッセージを送信する際に必要になります。
そして、APIコンソールのDashboardで表示されるProject Numberは受信時に必要になるので覚えておきましょう。

gcm1

2.Google Play Servicesをimport

さて、次にAndroidプロジェクトでGCMを使用するための準備をします。
以前はAndroid SDK Managerを使用してExtras/Google Cloud Messaging for Android Libraryを
インストールすればよかったのですが、現在このライブラリは非推奨になっているので、
代わりにGoolge Play servicesをインストールします。
gcm2

インストールしたら、/extras/google/google_play_services/libproject/google-play-services_lib
をAndroid Project From Exting Code形式でimportします。
次にGCMを使用するプロジェクトを右クリックし、Properties->Androidを選択します。
ダイアログ右下のAddボタンを押し、google-play-services_libを選択します。
これでGCM用のクラスが使用できるようになります。

3.AndroidManifest修正

では、Push配信を受けるためにAndroidManifest.xmlを修正しましょう。

    <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="<パッケージ名>.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="<パッケージ名>.permission.C2D_MESSAGE" />
    <uses-permission android:name="<パッケージ名>.c2dm.permission.RECEIVE" />
・
・
    <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="<パッケージ名>" />
            </intent-filter>
     </receiver>
     <service android:name=".GcmIntentService" />
・
・

必要なpermissionを追加し、後で定義するreceiverとserviceの定義もしておきます。

4.受信用クラスの作成

では、AndroidManifestで定義したreceiverとserviceを実装しましょう。
まずはGcmBroadcastReceiverクラスを実装します。

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
	@Override
	public void onReceive(Context context, Intent intent) {
		ComponentName comp = 
		  new ComponentName(context.getPackageName(), GcmIntentService.class.getName());
		startWakefulService(context, (intent.setComponent(comp)));
		setResultCode(Activity.RESULT_OK);
	}
}

GcmBroadcastReceiverでは、WakefulBroadcastReceiverを継承し、後述するサービスを実行します。
WakefulBroadcastReceiverは、処理を行っている間はデバイスがスリープしないことを保証できるReceiverです。

次はサービスの実装です。メッセージを受け取った際、内容をLogで出力しています。
実際にはNotificationを使用して、ユーザーに通知したりすることが多いかと思います。

public class GcmIntentService extends IntentService {
	private static final String TAG = "GcmIntentService";
	public GcmIntentService() {
		super("GcmIntentService");
	}
	@Override
	protected void onHandleIntent(Intent intent) {
		Bundle extras = intent.getExtras();
		GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
		String messageType = gcm.getMessageType(intent);

		if (!extras.isEmpty()) {
			if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
				Log.d(TAG,"messageType: " + messageType + ",body:" + extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
				Log.d(TAG,"messageType: " + messageType + ",body:" + extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
				Log.d(TAG,"messageType: " + messageType + ",body:" + extras.toString());
			}
		}
		GcmBroadcastReceiver.completeWakefulIntent(intent);
	}
}

最後に端末自身をGCMへ登録するために、Activityを修正しましょう。
ここで修正しているActivityは、アプリケーションのエンドポイントとなるActivityです。

public class MainActivity extends Activity {
	/** Google Cloud Messagingオブジェクト */
	private GoogleCloudMessaging gcm;
	/** コンテキスト */
	private Context context;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		context = getApplicationContext();

		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(<Project Number>);
					msg = "Device registered, registration ID=" + regid;
				} catch (IOException ex) {
					msg = "Error :" + ex.getMessage();
				}
				return msg;
			}

			@Override
			protected void onPostExecute(String msg) {
			}
		}.execute(null, null, null);
	}
}

onCreateでGoogleCloudMessagingインスタンスを取得し、別スレッドでデバイスの登録を行っています。
ここで先ほど覚えておいたProjectNumberを指定します。
なお、ここで記述したActivityの処理はデバイスを登録するだけです。
本来なら取得したRegistrationIdを保存したり、GCMが使えるかチェックしたりする必要があります。
そういった処理はこのあたりで説明しているので、確認してみてください。

5.動作確認

では動作確認してみましょう。今回はcurlコマンドでメッセージの配信を直接行います。
まずはアプリを実行し、ログに出力されたRegistrationIDを覚えておきます。
その状態で下記curlコマンドを実行し、Push配信を行ってみます。

%curl --header "Authorization: key=<API KEY>" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"<RegistrationID>\"],\"data\":{\"message\":\"Hello\"}}"

Serviceが呼び出され、ログが出力されるはずです。

まとめ

今回は、最近のGCM実装をセットアップからやってみました。
最近はAWSのモバイルPushと組み合わせて使ったりすることも多いようなので、活用してみてください。

参考サイトなど