LoginSignup
7
2

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

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

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