コードがたくさんあって大変でしたね。ここまでお疲れ様でした。今回の記事でプッシュ機能は完成です。
前回の記事の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です。
それでは!