Tips

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

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

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の端末保存の実装を
行ってアプリ実装編を完結したいと思います。

Androidアプリ開発の必須知識!JAVAプログラミングを学べる連載リンク

はじめてのJAVA 連載

Recent News

Recent Tips

Tag Search