LoginSignup
70
69

More than 3 years have passed since last update.

AndroidアプリにFirebase Cloud Messagingを実装する(2) - アプリでメッセージを受信する

Last updated at Posted at 2017-11-06

Firebase Cloud Messagingを使って、Androidアプリにプッシュ通知を導入する方法について書きました。
このエントリでは実際に通知を受信するのに必要なコードを書いて、通知を受信するまでをまとめています。

FCMメッセージの種類

FCMメッセージの種類には以下の2つがあります。詳しくはこちらをご覧ください。

メッセージタイプ 概要
通知メッセージ アプリの代わりにFCMが処理するメッセージ。予め定義されたキーを使って送信するため、決められた以外の情報を送ることはできない
データメッセージ アプリが直接処理するメッセージ。メッセージのキーなど、送信側が自由にメッセージのフォーマットを決めることができる

両者の違いは主に以下の2つです。

  • メッセージ送信に使うJSONのフォーマットが違う
  • アプリでメッセージを受信した時の挙動が異なる

メッセージを受信した時のアプリの挙動は以下の通りです。
"onMessageReceived"と書かれているケースでは、FirebaseMessagingServiceクラスを継承したサービスのonMessageReceivedメソッドが呼び出されます。

メッセージタイプ アプリがフォアグラウンド アプリがバックグラウンド
通知メッセージ タスクトレイに入る  onMessageReceived
データメッセージ onMessageReceived  onMessageReceived

通知メッセージにはデータを含めることもできます。両者を併用した場合についてはここを参考にしてください。

前提条件

AndroidプロジェクトにFirebaseが追加されていること。追加する方法は、前のエントリをご確認ください。

環境

以下の環境を使って実施しています。

  • macOS Mojave バージョン10.14.5
  • Android Studio 3.4.1
  • Nexus5X + Android7.1.2
  • Pixel3a + Android9

実装

サービスの定義

FirebaseMessagingServiceを継承したサービスを作成します。
このサービスには、以下2つのメソッドを実装します(他にも実装できるメソッドはありますが、ここでは割愛します)。

メソッド 呼び出されるタイミング
onNewToken トークン(端末+アプリの組み合わせを一意に識別するための文字列)が更新された
onMessageReceived 通知を受信した

それぞれのメソッドを実装してみました。本来ならトークンが更新されたらサーバに保存するなどの処理が必要ですが、ここではログに出すだけにしています。

MyFirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onNewToken(String token) {
        // 端末+アプリを一意に識別するためのトークンを取得
        Log.i("FIREBASE", "[SERVICE] Token = " + token);
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        if (remoteMessage != null) {
            // 通知メッセージ
            RemoteMessage.Notification notification = remoteMessage.getNotification();
            if (notification != null) {
                // 通知メッセージを処理
            }

            // データメッセージ
            Map<String, String> data = remoteMessage.getData();
            if (data != null) {
                // データメッセージを処理
            }
        }
    }
}
MyFirebaseMessagingService.kt
class MyFirebaseMessagingService : FirebaseMessagingService() {
    override fun onNewToken(token: String?) {
        // 端末+アプリを一意に識別するためのトークンを取得
        Log.i("FIREBASE", "[SERVICE] Token = ${token ?: "Empty"}")
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage?) {
        remoteMessage?.let { message ->
            // 通知メッセージ
            message.notification?.let {
                // 通知メッセージを処理
            }

            // データメッセージ
            message.data?.let {
                // データメッセージを処理
            }
        }
    }
}

作成したサービスはAndroidManifest.xmlに登録しておきます。

AndroidManifest.xml
<service
        android:name=".MyFirebaseMessagingService"
        android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

最新のトークンを確認

「端末登録トークン」(以下「トークン」)は、端末+アプリの組み合わせを一意に識別するための文字列です。これを利用してアプリにメッセージを送信します。
トークンは、ユーザーの事情やサーバ側の都合で更新される可能性があります。常に最新のトークンを取得することが推奨されていますので、アプリ起動時に確認するよう実装するのが適当かと思います。
トークンを取得するためのコードは以下の通りです。

トークンの取得(Java)
FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener((task) -> {
    if (!task.isSuccessful()) {
        Log.w("FIREBASE", "getInstanceId failed.", task.getException());
        return;
    }

    String token = (task.getResult() == null) ? "empty" : task.getResult().getToken();
    Log.i("FIREBASE", "[CALLBACK] Token = " + token);
});
トークンの取得(Kotlin)
FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { task ->
    if (!task.isSuccessful) {
        Log.w("FIREBASE", "getInstanceId failed", task.exception)
        return@addOnCompleteListener
    }

    Log.i("FIREBASE", "[CALLBACK] Token = ${task.result?.token}")
}

FCMメッセージの受信

メッセージを受信すると、FirebaseMessagingServiceのサブクラスに実装したonMessageReceived(RemoteMessage)が呼び出されます。その中に、メッセージをパースしてどのように扱うかのロジックを定義します。
『サービスの定義』の項に載せたサンプルコードは、通知メッセージとデータメッセージそれぞれに対応しています。ご確認ください。

FCMメッセージの送信

ここまでできればメッセージを受信する準備は完了です。
Firebaseコンソール、もしくはHTTPリクエストでメッセージを送信することができますので試してみます。

a.コンソールから送信

通知メッセージを送るには、Firebaseコンソールにログインして目的のプロジェクトを開き、「Cloud Messaging」へ遷移します。
『Send your first message』をクリックします。
fcm1.png

  • 「通知のタイトル」「通知テキスト」には適当な文字列を入力してください。
  • 「ターゲット」にはアプリケーションIDを入力してください。

2回目以降であれば、今まで送信したメッセージが一覧表示されています。
画面左上の『新しい通知』をクリックして、新しいメッセージを送信します。既存のメッセージを複製することもできます。
fcm2.png

b.cURLを使って送信

次に、cURLを使って通知メッセージとデータメッセージの両方を送信します。cURLの導入や使用の方法については割愛します。

サーバキーを確認します。
Firebaseコンソールで歯車型の設定アイコン①をクリックして画面を開きます。設定画面では『クラウド メッセージング』タブ②をクリックしてください。『サーバーキー』③が表示されますのでコピーしておいてください。
fcm27.png

以下はデータメッセージを送信するコマンドの例です。

SERVER_KEY=(サーバーキー)
TARGET_TOKEN=(トークン)

curl -X POST -H "Content-Type:application/json" \
     -H "Authorization:key=$SERVER_KEY" \
     -d "{\"data\":{\"name\" : \"Taro Nihon\",\"age\" : \"20\",\"address\" : \"Tokyo\"},\"to\" : \"$TARGET_TOKEN\"}" \
     https://fcm.googleapis.com/fcm/send

まとめ

コードの作成からメッセージを受信するまでを書いてみました。
ここでは最低限の内容でFCMメッセージを作成していますが、有効期限や優先順位など、他にも色々な情報を含めることができます。
以下を参考に、いろんな実装を試してみてください。

  • 通知メッセージとデータメッセージの違いなど、FCMメッセージの詳細についてはこちらで確認してください。
  • 送信時のJSONに定義することのできる内容は、リファレンスで確認できます。

改訂履歴

  • 2019/05/24
    • 動作・検証環境を変更しました。
    • Javaのコードを修正しました。
    • Kotlinのコードを追加しました。
    • FirebaseInstanceIdServiceがdeprecatedになっていたため、記述を削りました。
    • スクリーンショットを全て撮り直しました。
70
69
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
70
69