LoginSignup
2

More than 1 year has passed since last update.

Firebaseのメッセージ受信からアプリ起動までの覚書

Posted at

本記事はAndroid Advent Calendar 2020の2020/12/05分です。

PUSH通知受信のためにFirebaseを使うことが多いと思いますが、
私毎回業務でやるたびにアプリ起動でハマるので2020年で終えれるようこちらの記事を書かせていただきます。

サンプルプロジェクト

実務でのコードを使うことはできないので、類似のサンプルプロジェクトを作成しました。
FirebaseSample
※google-servies.json はサーバにUPしていませんのでビルドはそのままだとできないです。

Firebaseの導入〜メッセージ送信までは公式ガイドに丁寧に記載があります。
(本当ありがたいです...ちなみに最近ドキュメント変わった?BoM めっちゃ便利ですね..)

本題: 通知とデータペイロードが両方ある場合のアプリ起動について

こちらのページに全てまとまっています!

抜粋すれば、このスクリーンショットにも収まります..

summary.png

この
バックグラウンドでかつ両方
通知: システムトレイ、データ: インテントの追加部分内

が曲者でした。

当時のアプリの構成

主な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 の仕様もあいまって
ちょいちょいハマるのでまとめてみました。

来年は同じことでハマる時間が短くなる(覚えていること)といいです..

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
What you can do with signing up
2