GCMの使用を強いられたので,メモです. GCMはサーバからandroidアプリに対して, push通知を送る仕組み・サービスです. 2012/6/26に,公開されたようです. それ以前は,C2DMを使って実装していました. 簡単なサンプルですが,メモとして残しておきます.
こちらに置いています.
http://developer.android.com/google/gcm/index.html,http://www.kotemaru.org/2013/07/28/android-push-message.htmlから,一部引用しています.
仕組み Googleのサーバを,GCMサーバ 自身のサーバを,自サーバ と呼ぶことにします.
はじめにGCMサーバから,端末のID( レジスタID )を取得する. レジスタIDを自サーバへ送信する. 自サーバから,レジスタIDを設定し,メッセージをGCMサーバへ送る. GCMサーバから各端末にメッセージが送信され,push通知される. 準備 まず,https://code.google.com/apis/console/から GoogleAPIを取得します.
Service一覧から,Google Cloud Messaging for Androidのstatusをonにします. API ACCESSから,Create new Server Keyを選択し,API Keyを取得します. ここで,2つの情報を確認しておきます.
API Key: 自サーバから,GCMサーバへメッセージを送信する場合に使う. Key for server appsに書かれています.“Jfdsah82…“のようなもの. Sender id: アプリから,自サーバへメッセージを送信する場合に使う.URLのprojectの後ろの数値です.“4352…“のようなもの. 1. クライアントの実装 古いですが,Google APIs 10で実装しました. はじめに,Android SDK ManagerからGoogleCloudMessaging for Android Libraryをインストールします.次に,{Android SDKディレクトリ}/extras/google/gcm/gcm-client/dist/gcm-src.jarを,プロジェクトに追加します.(srcディレクトリで右クリック => Archive Fileで追加できます)
マニフェストファイル マニフェストファイルに以下のようにpermissionを追加します. BEGIN,ENDで囲ったところを追加してください. com.example.comのところはプロジェクトのパッケージ名に変更します.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.gcm_reciever" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10" /> <!-- BEGIN: for GCM_reciever --> <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="com.example.gcm_reciever.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.example.gcm_reciever.permission.C2D_MESSAGE" /> <!-- END: for GCM_reciever --> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.gcm_reciever.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- BEGIN: for GCM_reciever --> <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="com.example.gcm_reciever" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION"/> <category android:name="com.example.gcm_reciever"/> </intent-filter> </receiver> <service android:name=".GCMIntentService" /> <!-- END: for GCM_reciever --> </application> </manifest> MainActivity.java package com.example.gcm_reciever; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import com.google.android.gcm.GCMRegistrar; import android.net.Uri; import android.net.http.AndroidHttpClient; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.Menu; public class MainActivity extends Activity { /* 自サーバのURL */ public static final String url = "http:/hogehoge.net/closet/gcm.php"; /* sender id */ public static final String senderIds = "xxxxxxxxxx"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GCMRegistrar.checkDevice(this); GCMRegistrar.checkManifest(this); /* GCMサーバからレジスタIDを取得する. * 登録済みなら,それを自サーバへ送信する. * 未登録なら,GCMResistrar.register()でGCMサーバへ登録する. * (自サーバへは,Registeredのタイミングで送信される) */ String regId = GCMRegistrar.getRegistrationId(getApplicationContext()); if(regId.equals("")){ Log.i("GCM", "onCreate call register"); GCMRegistrar.register(getApplicationContext(), senderIds); }else{ Log.i("GCM", "onCreate call sendMyserver"); sendMyServer(regId); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override protected void onDestroy() { GCMRegistrar.onDestroy(this); super.onDestroy(); } /** * レジスタIDを自サーバへ送信する. * @param regId レジスタID */ static public void sendMyServer(String regId){ HttpClient client = new DefaultHttpClient(); List parameters = new ArrayList(); parameters.add(new BasicNameValuePair("action", "reg")); parameters.add(new BasicNameValuePair("regId", regId)); String query = URLEncodedUtils.format(parameters, "UTF-8"); HttpGet get = new HttpGet(url + "?" + query); Log.i("GCM", "sendMyServer: regId="+regId); try { HttpResponse response = client.execute(get); Log.i("GCM", "sending my server success."); } catch (ClientProtocolException e) { e.printStackTrace(); Log.i("GCM", "sending my server failed."); } catch (IOException e) { e.printStackTrace(); Log.i("GCM", "sending my server failed."); } } } GCMIntentService.java package com.example.gcm_reciever; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import com.google.android.gcm.GCMBaseIntentService; import com.example.gcm_reciever.*; public class GCMIntentService extends GCMBaseIntentService { private String tag = "GCM"; public GCMIntentService() { super(MainActivity.senderIds); } /** * レジスタIDがGCMサーバへ登録されたときに呼ばれる. * ここで,自サーバへも送信します. */ @Override protected void onRegistered(Context context, String regId) { Log.i(tag, "onRegistered: regId = " + regId); MainActivity.sendMyServer(regId); } /** * GCMサーバからメッセージを受信した時によばれる. */ @Override protected void onMessage(Context context, Intent intent) { Bundle extras = intent.getExtras(); String message = extras.getString("message"); Log.i(tag, "onMessage: msg = " + message); } @Override public void onError(Context context, String errorId) { Log.i(tag, "onError: " + errorId); } @Override protected boolean onRecoverableError(Context context, String errorId) { Log.i(tag, "onRecoverableError: " + errorId); return super.onRecoverableError(context, errorId); } @Override protected void onUnregistered(Context context, String registrationId) { // TODO Auto-generated method stub } } 2. サーバの実装 <?php require_once "HTTP/Request.php"; if(!ISSET($_GET['action'])) exit(0); if($_GET['action'] == "reg"){ $fp = fopen("id.txt", "w"); fwrite($fp, $_GET['regId']); fclose($fp); print('saved'); }else if(($_GET['action']) == "send"){ $fp = fopen("id.txt", "r"); $regid = fgets($fp); fclose($fp); $apikey = "AIza...."; $msg = 'posted from gcm'; $rq = new HTTP_Request("https://android.googleapis.com/gcm/send"); $rq->setMethod(HTTP_REQUEST_METHOD_POST); $rq->addHeader("Authorization", "key=".$apikey); $rq->addPostData("registration_id", $regid); $rq->addPostData("collapse_key", "1"); $rq->addPostData("data.message", $msg); if (!PEAR::isError($rq->sendRequest())) { print "\n" . $rq->getResponseBody(); } else { print "\nError has occurred"; } } 3. エラーコードとか いくつかエラーを経験したので,その対処法.
...