LoginSignup
7
5

More than 3 years have passed since last update.

[Android]PUSH通知

Last updated at Posted at 2020-10-09

概要

ローカル通知について結構前に勉強したことがあった(リモート通知はどうすればいいのか知らなかった)のだが、
だいぶ忘れた状態で、リモート通知のコード見ててどういうことなの・・・・となって、
なるほどねとなるまでにかなり時間がかかったのでメモ

PUSH通知とは?

  • PUSH通知はその発火トリガーによってローカル通知とリモート通知に分類されている。
    • ローカル通知:発火トリガーがローカルのなにかの処理
    • リモート通知:発火トリガーがFCMからのメッセージ受信
  • PUSH通知の本質的な処理・・・すなわち「通知領域への表示」〜「通知タップ時の画面遷移処理」のやり方は全く同じ ←ここがわかってなかった
  • なお、単純にPUSH通知という場合はリモート通知のことを指すことが多い。 ←さらにここでやられた
  • FCMメッセージ送信=PUSH通知と捉えている記事が世にめちゃくちゃ多いが、コレ多分嘘で、ここが理解を妨げていたんだと思う。
    Qiita記事とかでFirebaseからPUSH通知を送信!みたいな図をよく見かけてたせいで、完全にだまされた。 ←こいつが主原因!!!
    Firebase公式でPUSH通知なんていう言葉出てこないもの。送るのはあくまでFCMメッセージだっていってるもの。

リモート通知の実装

デバイストークンの発行〜FCMメッセージが端末に届くまでの大まかなイメージ

AndroidのPush通知(FCM)をサーバー知識無しで試してみようのPush通知の「大体の仕組み」を参照。

※本記事では、上記の図で「固有ID」と呼ばれているものを「デバイストークン」、
「サーバー」と呼んでいるものを「アプリサーバー」と呼ぶことにする。
なお、公式ではデバイストークンは「registration token」と呼んでいる模様。

1. デバイストークンの取得とアプリサーバーへの登録処理

実装すべきこと
- アプリ側: FirebaseMessagingServiceを継承したクラスを定義し、このクラスにonNewToken(token: String)をオーバーライド(★)して、このメソッド内でアプリサーバーへデバイストークンを送信する処理を実装する
- アプリサーバー側: アプリから受け取ったデバイストークンを保存する処理(本記事はアプリ側を扱うので説明は割愛)

説明

FCM SDKをFCMメッセージを送信したい対象のアプリに導入すると、アプリ初回起動時に、FCM SDKがデバイストークンを発行し、Firebaseにアップロードしてくれる。

なお、これに限らずFirebaseはネット側との通信処理が走るため、FCM SDKのメソッドを叩く際には非同期であるべきらしい。

デバイストークンはアプリ初回起動時以外に以下のケースで新規発行されることもある。

  • アプリが新しい端末上に復元された
  • アプリがアンインストール/再インストールされた
  • アプリ上のデータを削除した

上記のように「FCM SDKがデバイストークンを発行した時」には、FCM SDKによって★のメソッドがコールされるようになっている。
また、★のメソッドの引数tokenにはデバイストークンの文字列が格納されているので、★のメソッド内でアプリサーバーへ送信する処理を実装してやればよい。

なお、デバイストークンはonNewToken(token)メソッド内以外でも、FirebaseMessaging.getInstance().getToken()を実行することでアクセスできる。なお、存在しない場合は新規発行される。

・・・とはいえ、アプリ内でデバイストークンが必要になるタイミングは、デバイストークンが新規発行されてアプリサーバーへ送信したいときだけなので、onNewToken()内の実装だけで事足りそうだが・・・? 

2. FCMメッセージが届いた後の処理

アプリがフォアグラウンドにあるときには、FirebaseMessagingServiceを継承したクラスのonMessageReceived()メソッドが呼ばれる。
アプリがバックグラウンド、または起動していない場合は、onMessageReceived()メソッドは呼ばれない。代わりに、通知センターにメッセージが表示され、この通知をタップしたときに起動されるインテントにFCMメッセージが渡される。

実装すべきこと

  • アプリ側: FirebaseMessagingServiceを継承したクラスに以下メソッドをオーバーライドして実装
    • onMessageReceived(remoteMessage: RemoteMessage) : FCMメッセージを受け取ったときの処理
    • onMessageDeleted() : 「端末に配信されていないFCMメッセージが100件たまっているとき」「1ヶ月以上FCMとの接続がないとき」にコールされる。これを受けて何らかの処理をしたい場合には実装する。いらないならいらないでOK。

説明

onMessageReceived() については、
https://github.com/firebase/quickstart-android/blob/d20b5b4a7e226ff49bef2c20fe0cc01ff23b171a/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/kotlin/MyFirebaseMessagingService.kt#L26-L61
のコメントに実装すべきことが書いてある。

翻訳すると、

FCMメッセージに対する処理をonMessageReceived()で実装する。
onMessageReceived内でメッセージが取得できていないならば、その理由は
https://goo.gl/39bRNJ
にあるかもしれない。

メッセージがデータペイロード(※)を含むかチェック
 長時間動くジョブによって処理される必要があるデータであるかチェック
    長時間実行タスク(10秒以上)の場合はワークマネージャーを使う 
    そうでない場合は、10秒以内にメッセージを処理する
 
メッセージが通知ペイロードを含むかチェック

また、受け取ったFCMメッセージの結果として自身の通知の生成を意図する場合は、ここから始めるべきだ。
以下のsendNotificationメソッドを参照しろ。

remoteMesage.getData() で、FCMメッセージに含まれていたペイロードデータ(Map)を取得できる

※データペイロード
ヘッダを抜いたデータ本体のこと。httpレスポンスでいうところのbody。

参考

7
5
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
7
5