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 | 通知を受信した |
それぞれのメソッドを実装してみました。本来ならトークンが更新されたらサーバに保存するなどの処理が必要ですが、ここではログに出すだけにしています。
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) {
// データメッセージを処理
}
}
}
}
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に登録しておきます。
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
最新のトークンを確認
「端末登録トークン」(以下「トークン」)は、端末+アプリの組み合わせを一意に識別するための文字列です。これを利用してアプリにメッセージを送信します。
トークンは、ユーザーの事情やサーバ側の都合で更新される可能性があります。常に最新のトークンを取得することが推奨されていますので、アプリ起動時に確認するよう実装するのが適当かと思います。
トークンを取得するためのコードは以下の通りです。
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);
});
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』をクリックします。
- 「通知のタイトル」「通知テキスト」には適当な文字列を入力してください。
- 「ターゲット」にはアプリケーションIDを入力してください。
2回目以降であれば、今まで送信したメッセージが一覧表示されています。
画面左上の『新しい通知』をクリックして、新しいメッセージを送信します。既存のメッセージを複製することもできます。
b.cURLを使って送信
次に、cURLを使って通知メッセージとデータメッセージの両方を送信します。cURLの導入や使用の方法については割愛します。
サーバキーを確認します。
Firebaseコンソールで歯車型の設定アイコン①をクリックして画面を開きます。設定画面では『クラウド メッセージング』タブ②をクリックしてください。『サーバーキー』③が表示されますのでコピーしておいてください。
以下はデータメッセージを送信するコマンドの例です。
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メッセージを作成していますが、有効期限や優先順位など、他にも色々な情報を含めることができます。
以下を参考に、いろんな実装を試してみてください。
改訂履歴
- 2019/05/24
- 動作・検証環境を変更しました。
- Javaのコードを修正しました。
- Kotlinのコードを追加しました。
- FirebaseInstanceIdServiceがdeprecatedになっていたため、記述を削りました。
- スクリーンショットを全て撮り直しました。