コードがたくさんあって大変でしたね。ここまでお疲れ様でした。今回の記事でプッシュ機能は完成です。
前回の記事のMainActivityのソース内、登録ボタンを押したときの処理に、こんな記述があったと思います。
// レジストレーションIDを取得 mProgress = null; Handler mHandler = new Handler(); mProgress = new ProgressDialog(context); mProgress.setMessage(RegisterTask.message); mProgress.show(); RegisterTask t = new RegisterTask(context, mHandler, mProgress, regid, prefs, tv_id); t.start();
これは通信部分をHandlerで処理しているのですが、その中身がこんな感じです
[RegisterTask.java]
public class RegisterTask extends Thread { // レスポンスコード int res_code; Context context; Handler mHandler; ProgressDialog mProgress; TextView tv_id; String regid; SharedPreferences prefs; // レジストレーションIDをPOSTするURL String post_url = "○○○○○○○○○.php"; public static String message = "少々お待ちください……"; String TAG = "RegisterTask"; public RegisterTask(Context context, Handler mHandler, ProgressDialog mProgress, String regid, SharedPreferences prefs, TextView tv_id) { this.res_code = 0; this.context = context; this.mHandler = mHandler; this.mProgress = mProgress; this.tv_id = tv_id; this.regid = regid; this.prefs = prefs; } // スレッド内処理 public void run() { // 時間がかかる処理 Log.d(TAG, "postします"); PostData(); // スレッドが終了した場合、終了したことをHandlerに知らせる。 mHandler.post(new Runnable() { public void run() { // ダイアログを消す mProgress.dismiss(); } }); } // POST private void PostData() { // 結果 String ret = ""; // インスタンス取得 GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); try { // GCMサーバーへ登録する regid = gcm.register(Const.SENDER_ID); Log.d(TAG, "regid:" + regid); } catch (IOException e) { e.printStackTrace(); } // レジストレーションIDを自分のサーバーへ送信する URI url = null; try { url = new URI(post_url); Log.d(TAG, "URLはOK:" + post_url); } catch (URISyntaxException e) { e.printStackTrace(); } // POSTするJSONをつくる JSONObject kv1 = new JSONObject(); try { kv1.put("regid", regid); kv1.put("param1", "param"); kv1.put("param2", -1); kv1.put("param3", false); } catch (JSONException e2) { e2.printStackTrace(); } String json = kv1.toString(); Log.d(TAG, "jsonデータ:" + json); // POSTリクエストを実行 DefaultHttpClient httpClient = new DefaultHttpClient(); try { Log.d(TAG, "POST開始"); HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new StringEntity(json, "UTF-8")); httpPost.setHeader("Content-Type", "application/json"); httpPost.setHeader("Accept-Encoding", "application/json"); httpPost.setHeader("Accept-Language", "en-US"); ret = httpClient.execute(httpPost, new ResponseHandler() { @Override public String handleResponse(HttpResponse response) throws IOException { Log.d(TAG, "レスポンスコード:" + response.getStatusLine().getStatusCode()); res_code = response.getStatusLine().getStatusCode(); // 正常に受信できた場合は200 switch (response.getStatusLine().getStatusCode()) { case HttpStatus.SC_OK: Log.d(TAG, "レスポンス取得に成功"); // レスポンスデータをエンコード済みの文字列として取得する return EntityUtils.toString(response.getEntity(), "UTF-8"); case HttpStatus.SC_NOT_FOUND: Log.d(TAG, "データが存在しない"); return null; default: Log.d(TAG, "通信エラー"); return null; } } }); } catch (IOException e) { Log.d(TAG, "通信に失敗:" + e.toString()); } finally { // shutdownすると通信できなくなる httpClient.getConnectionManager().shutdown(); } // 受信結果をUIに表示 Log.d(TAG, "結果:" + ret); // 成功したら if (res_code == HttpStatus.SC_OK) { // レジストレーションIDを端末に保存 Log.d(TAG, "regid:::" + regid); storeRegistrationId(regid); //MainActivity画面に反映 tv_id.setText(regid); } } /* * レジストレーションIDの保存 */ private void storeRegistrationId(String regId) { // 今のバージョン int currentVersion = 0; try { PackageInfo packageInfo = context.getPackageManager() .getPackageInfo(context.getPackageName(), 0); currentVersion = packageInfo.versionCode; } catch (NameNotFoundException e) { } // 保存 Editor editor = prefs.edit(); editor.putString(Const.PROPERTY_REG_ID, regId); editor.putInt(Const.PROPERTY_APP_VERSION, currentVersion); editor.commit(); } }
途中、POSTするためのJSONを作っています。
実際に動作させてログを見れば解りますが、ここでは、
{ "regid" : 123456, //int型 "param1" : "param", //String型 "param2" : -1, //int型 "param3" : false //boolean型 }
という形式のJSONを作っています。
このあたりは、どういう形式のJSONを受け取るのか、サーバー側の処理を作成する人と話し合ってください。また、エラーコードやレスポンスについても、サーバーの処理によるので、話し合いが必要です。
さて、これで、レジストレーションIDの登録まで完了しました。
あとはサーバーからのプッシュ通知を受け取るレシーバーを作るだけです。
[GcmBroadcastReceiver.java]
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { String TAG = "GcmBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { // 送られてきたデータを受け取る GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); String messageType = gcm.getMessageType(intent); // 送られてきたデータのメッセージ Bundle extras = intent.getExtras(); String mess = extras.toString(); if (!extras.isEmpty()) { // エラー if (messageType .equals(GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR)) { Log.d(TAG, "MESSAGE_TYPE_SEND_ERROR:" + mess); } // サーバーでメッセージ削除 else if (messageType .equals(GoogleCloudMessaging.MESSAGE_TYPE_DELETED)) { Log.d(TAG, "MESSAGE_TYPE_DELETED:" + mess); } // 正常に受信 else if (messageType .equals(GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE)) { Resources res = context.getResources(); Notification n = new Notification(); // Notificationの生成 n.icon = R.drawable.ic_launcher; // アイコンの設定 // 通知されたときに通知バーに表示される文章 n.tickerText = mess + "(short)"; // メッセージの設定 n.flags = Notification.FLAG_AUTO_CANCEL; // 通知を選択した時に自動的に通知が消えるための設定 // 通常の着信音を選択する Uri uri = RingtoneManager .getDefaultUri(RingtoneManager.TYPE_ALARM); // アラーム音 n.sound = uri; // サウンド Intent i = new Intent(context, MainActivity.class); i.putExtra("MESS", mess); PendingIntent pi = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); // 上から通知バーを下してきたときに表示される文章をセット n.setLatestEventInfo(context, res.getString(R.string.app_name), mess + "(long)", pi); long[] vibrate_ptn = { 0, 100, 300, 1000 }; // 独自バイブレーションパターン n.vibrate = vibrate_ptn; // 独自バイブレーションパターンを設定 n.defaults |= Notification.DEFAULT_LIGHTS; // デフォルトLED点滅パターンを設定 // NotificationManagerのインスタンス取得 NotificationManager nm = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); nm.notify(1, n); // 設定したNotificationを通知する } } } }
受け取った通知に問題がなければ、Notificationを使って、端末のアラームやバイブレーションを動作させて知らせます。
このあたりはそれぞれお好みの仕様にしてください。
最後に、定数を宣言するクラスを追加すれば完成です。
[Const.java]
public final class Const { //プロダクトID static final String SENDER_ID = "○○○○○○○○○○○○"; // SharedPreferences用 public static final String EXTRA_MESSAGE = "message"; public static final String PROPERTY_REG_ID = "registration_id"; public static final String PROPERTY_APP_VERSION = "appVersion"; }
ここまで上手くいっていれば、プッシュ通知を受け取ると、下記の画像のようになっているのではないでしょうか。
以上でプッシュ通知のアプリ側の実装は完了です!
あとは受け取ったメッセージを煮るなり焼くなり好きにしてください!
あ、「削除」ボタンを押したときの処理を書くのを忘れていました……。
基本的にはRegisterTaskと同じように、サーバーに情報を投げて、受け取ったサーバー側はプッシュ通知を配信しないようにするなどのときに使います。RegisterTaskのほぼコピペでOKです。
それでは!