Send data notification to Android app with Cloud Functions for Firebase

Androidアプリがフォアグラウンドでもバックグラウンドでも、通知を受け取った後にそれを表示するかどうかをアプリ内で判断させたいときは Firebase の data message を送る必要がある。

FirebaseコンソールからはNotification Composerを使って、notification messageを送ることができる。notification messageはアプリケーションがバックグラウンドのとき、システムのトレイに入るため、アプリケーション側で表示・非表示の判断をすることができない。

data messageを送るには、独自サーバーで動いているアプリケーションかCloud Functions for Firebaseを実装しなければならない。

背景

notification messageでは要件を満たせなかった。

  • 毎日18時に、当日(深夜0時から)まだアプリを開いていないユーザー送りたい
  • ユーザーが当日ログインしたかどうかは、端末のDBに保存している
  • 端末のtimezoneが日本ではない場合は通知を表示しない
  • 災害などの緊急時はユーザーがアプリを開かなくても通知を止められる
  • 通知が届く時間は、18時ちょうどである必要はない

必要なもの

  1. Androidアプリ
  2. Firebaseプロジェクト
  3. Cloud Functions for Firebaseプロジェクト

それぞれの役割

Androidアプリ
  • FCMトークンを生成し、Fire Storeに保存
  • data messageを受け取り、通知を表示する
Firebaseプロジェクト
Cloud Functionプロジェクト
  • Fire Storeに保存されたFCMトークンを取り出す
  • httpリクエストをトリガーにして、data messageを送る
  • 有料だがcronで時間をトリガーにして、送ることもできる(Schedule functions  |  Firebase)

1. Firebaseプロジェクトを作る

Add Firebase to your Android project  |  Firebase を参考にプロジェクトを作る。

2. Cloud Functions for Firebaseを作る

時間がある人は Codelab の Cloud Functions for Firebase がおすすめ。

Firebase CLIを使ってファイルを生成する。

Get started: write and deploy your first functions  |  Firebase を参考にする。

npm -g install firebase-tools
firebase login
firebase init functions

途中でFirebaseプロジェクトと言語(JavaScript | TypeScript)を選ぶ。

functioins/index.jsを編集する。

A cloud function which sends data notification to ...

ファイルを保存したら、Firebase CLIを使ってデプロイする。

firebase deploy --only functions

Deployされたら、curlコマンドで叩いてみよう。

curl https://us-central1-MY_PROJECT.cloudfunctions.net/sendNotificationApi

DeployするとFirebaseコンソール の Functionsに登録される。

f:id:bambinya:20190430182227p:plain

3. Androidアプリの作成

Set up a Firebase Cloud Messaging client app on Android  |  Firebase を手順通りに実装する。

生成されたFCMトークンをFirestoreに保存する方法は

Get started with Cloud Firestore  |  Firebase を参考にした。

上で紹介したindex.jsでとりあえず動かしたいときはコピペして使ってください。

private fun sendRegistrationToServer(token: String?) {
val tokenMap : HashMap<String, String> = HashMap()
tokenMap["fcmTokens"] = token?: ""
val db: FirebaseFirestore = FirebaseFirestore.getInstance()
db.collection("fcmTokens")
.document(token?:"")
.set(tokenMap)
.addOnSuccessListener { Log.d(tag, "token was added: ${token}") }
.addOnFailureListener { Log.d(tag, "token was NOT added") }
}

 DBには、このように保存される。

f:id:bambinya:20190430182603p:plain

 

TODO for project:

チャンネルとtopicとバックグラウンドでの使用が制限されたアプリ(Send messages to multiple devices  |  Firebase)に関しては調査が必要。

 

おしまい。