本記事はAndroid Advent Calendar 2020の2020/12/05分です。
PUSH通知受信のためにFirebaseを使うことが多いと思いますが、
私毎回業務でやるたびにアプリ起動でハマるので2020年で終えれるようこちらの記事を書かせていただきます。
サンプルプロジェクト
実務でのコードを使うことはできないので、類似のサンプルプロジェクトを作成しました。
FirebaseSample
※google-servies.json はサーバにUPしていませんのでビルドはそのままだとできないです。
Firebaseの導入〜メッセージ送信までは公式ガイドに丁寧に記載があります。
(本当ありがたいです...ちなみに最近ドキュメント変わった?BoM めっちゃ便利ですね..)
本題: 通知とデータペイロードが両方ある場合のアプリ起動について
こちらのページに全てまとまっています!
抜粋すれば、このスクリーンショットにも収まります..
この
バックグラウンドでかつ両方
通知: システムトレイ、データ: インテントの追加部分内
が曲者でした。
当時のアプリの構成
主なActivity
- SplashActivity スプラッシュ画面を表示して、MainActivityに遷移する
- MainActivity MainのActivityとして各種画面を表示する
PUSH通知の要件
- 通知は notification を表示する
- payload に type や ログ集計するためのパラメータが渡され、起動時にログ集計や画面の出し分けをする
困ったこと(ハマったこと)
- アプリが起動している場合はパラメータをきちんと取得できて、要件通りの挙動をするが、アプリキルされている場合にパラメータを取得できずログ集計や画面の出しわけができなかった
原因
この場合、通知はデバイスのシステムトレイに配信され、データ ペイロードはランチャーアクティビティのインテントの追加部分に配信されます。
公式ドキュメントにしっかり書いてありますが、バックグラウンドからのアプリ起動時はランチャーアクティビティのインテントに設定されていたため...
つまり、画面を出しわけするMainActivityに以下のようにだけ実装するのは不十分で..
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))
val date = intent.extras?.getString("date") ?: ""
val screen = intent.extras?.getString("screen") ?: ""
Log.d("MainActivity", "$date=$screen")
}
SplashActivityからデータを渡してあげる必要がありました..
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
val date = intent.getStringExtra("date")
val screen = intent.getStringExtra("screen")
Log.d("SplashActivity", "$date=$screen")
GlobalScope.launch {
delay(2000)
val intent = Intent(this@SplashActivity, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
intent.putExtra("date", date)
intent.putExtra("screen", screen)
startActivity(intent)
finish()
}
}
解決策
今回は上述の通り、SplashActivityからもMainActivityにインテントのデータを渡すことで解決しました。
特定の場合のみ変わるとかハマりそうですが、Firebaseからの実装の仕組み見ると理解できるんだろうなぁ..
あと、自分の場合は上記のような形で困ったことがありましたが、アプリの実装によって再現したりしなかったり..
別の解決方法もあると思います。
まとめ
android で Firebase でPUSH通知することがよくありますが、
アプリ起動に関する処理は複雑になりがちで Firebase の仕様もあいまって
ちょいちょいハマるのでまとめてみました。
来年は同じことでハマる時間が短くなる(覚えていること)といいです..