androidでプッシュ通知を実装する【第4回 アプリ側実装中編】

この記事は2015年10月5日に書かれたものです。内容が古い可能性がありますのでご注意ください。


androidでプッシュ通知の実装をテーマとして第4回目。

第3回でサポートライブラリをインポートしたり
AndroidManifestに必要なpermissionを追加したりと下ごしらえを済ませたので
今回はクライアントアプリの機能実装についてです。

プッシュ通知をGoogleCloudMessaging(GCM)サーバから受け取るために
クライアントアプリに必要な機能は大きく分けて次の四つです。

  1. 通知を受け取る
  2. 受け取ったメッセージを処理する
  3. レジストレーションIDの登録と端末保存
  4. (取得したレジストレーションIDのAppサーバへの送信)

1.通知を受け取るためにブロードキャストレシーバーを用意します。

2.具体的にはステータスバーにNotificationを出す、バイブレーションを鳴らす等、
メッセージを受け取ったら行う処理を実装しておかばければなりません。
バックグラウンドでこの処理を行うためのServiceを用意します。

3.GCMにセンダーIDを送ると、GCMが端末情報を登録すると同時に
レジストレーションIDを発行してくれるのでした。(第1回参照)
レジストレーションIDを元に通知の送付先を識別します。
このIDの取得機能を用意します。

4.プッシュ通知を送るには、メッセージ本文と送りたい先のレジストレーションIDを
AppサーバからGCMサーバに送信する必要があります。(これまた第1回参照)
よってAppサーバがレジストレーションIDを知っておかなければなりませんが、
IDのクライアントアプリ-APPサーバ間の送信は各々のアプリケーションの設計に依って実装してください。

ブロードキャストレシーバー

スリープ時でもBroadcastの処理を確実に実行できるように
レシーバーはサポートライブラリのWakefulBroadcastReceiverクラスを継承して実装します。

package jp.techpjin.samplepushnotification;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //受け取ったインテントの処理をGcmIntentServiceで行う
        ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());

        //サービスの起動。処理中スリープを制御
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}

通知を受信すると、GcmBroadcastReceiver#onReceive()が呼び出され、
GcmIntentServiceを起動します。

サービス

今回はメッセージを受け取ったらNotificationにより
ステータスバーに通知を表示する実装を行います。

package jp.techpjin.samplepushnotification;

import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.android.gms.gcm.GoogleCloudMessaging;

public class GcmIntentService extends IntentService {
    public static final int NOTIFICATION_ID = 1;
    private NotificationManager notificationManager;
    private NotificationCompat.Builder builder;

    public GcmIntentService(String name) {
        super(name);
    }

    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("LOG","messageType(error): " + messageType + ",body:" + extras.toString());
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
                Log.d("LOG","messageType(deleted): " + messageType + ",body:" + extras.toString());
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
                Log.d("LOG", "messageType(message): " + messageType + ",body:" + extras.toString());

                String message = extras.getString("message");
                sendNotification(message);
            }
        }
        GcmBroadcastReceiver.completeWakefulIntent(intent);

    }

    private void sendNotification(String msg) {
        notificationManager = (NotificationManager)
                this.getSystemService(Context.NOTIFICATION_SERVICE);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MainActivity.class), 0);

        builder = new NotificationCompat.Builder(this)
                        .setContentTitle("GCM Notification")
                        .setSmallIcon(R.drawable.app_icon)
                        .setStyle(new NotificationCompat.BigTextStyle()
                                .bigText(msg))
                        .setContentText(msg);

        builder.setContentIntent(contentIntent);
        notificationManager.notify(NOTIFICATION_ID, builder.build());
    }
}

onHandleIntentで具体的なメッセージ処理を実装します。

PendingIntentはintentを即時発行するのではなくタイミングを指定して発行できるintentのこと。

今回の例であれば、Notificationがクリックされたタイミングで発行されるintentになります。
NotificationCompat.Builder#setContentIntentでNotificationがクリック
されたとき発行されるPendingIntentを設定している)

一連の処理が終わったらcompleteWakefulIntentを呼び出して
レシーバーによるwake lockを解放するのを忘れずに。

3つ目のレジストレーションIDの登録と端末保存まで一気にやってしまいたいところですが
記事が少々長くなるので今回は1と2を終えたこの辺りで。

次回

通知を受け取るレシーバーと受信メッセージの処理Serviceの実装を行いました。

次回はクライアントアプリからGCMへのレジストレーションIDの登録とIDの端末保存の実装を
行ってアプリ実装編を完結したいと思います。

  • このエントリーをはてなブックマークに追加

PAGE TOP