【Androidプログラム】Serviceから起動画面を呼ぼうとするとたまに起動の次の画面が呼ばれて困った話
※本題とは関係ないアイキャッチ
表題の通りです。
とあるアプリを作っていて結構ハマったので備忘録。
遷移が特殊なので自分以外の人には何の役にも立たないかもしれないのであしからず。
作ろうとしていたアプリの遷移
アプリ起動
↓
起動画面
(アイコンからの起動?PUSH通知?など起動の種類や過去の起動回数等を参照して遷移先を選定)
↓
次の画面(画面A)
(起動画面でもらったIntentを元にしていろんな処理を行う。場合によっては更に次の画面Bに遷移することもある。)
↓
画面B
(処理や操作を行いユーザが終了ボタンをタップするとAに戻る。)
↓
画面A
(遷移後、即ブラウザを起動する。)
ざっとこんな感じ。
で、何がおかしかったのかというと。
上記の一連の処理を終えたあとに、PUSH通知を受け取る。
すると問題なく画面Bまで遷移することができる。(PUSH通知から起動された場合は、そのまま画面Bまで行くのが正しい挙動)
しかし、上記の一連の処理を終える前に、画面Aにてタスクキルを行う。
すると、上記の処理を一度行ったあとにもう一度、一連の処理を行おうとすると、PUSH通知取得後になぜか起動画面が呼ばれず、画面Aに直接遷移する。
ややこしいので簡単なフローにすると以下。
初回起動&タスクキル
↓
PUSH通知を受け取り1回目の一連の処理
↓
処理終了後、PUSH通知を受け取り2回目の一連の処理を行おうとする
↓
起動画面の onCreate() すら呼ばれず、いきなり画面Aが描画される
◆手がかりにしたポイント
・EsFirebaseServiceのonMessageReceive()ではもちろん起動画面のIntentでstartActivity()を呼んでいる。
・EsFirebaseServiceでは画面Aについて一切触れていない。
・いきなり描画される画面Bは onPause() から始まっている。
・いきなり描画される画面Bでは onRestoreInstanceState() が呼ばれている。
以上の諸々を手がかりに savedInstanceStateあたりが怪しいな~と思いながら試行錯誤
なにかが初期化できてない?
そもそもなんでBのIntentが?
savedInstanceStateが最後に開いていたアクティビティの情報を保持している??
いろいろ考えたが何もできず。。。orz
◆onNewIntent()
万策尽きてとある知人に相談してみると
「起動画面で onNewIntent() は呼ばれている?」
とアドバイスを貰ったので確認してみると、呼ばれている!
onNewIntent()については以下が詳しい。
起動画面はPUSH通知で呼び出している都合上、 startActivity()する際にIntentに FLAG_ACTIVITY_SINGLE_TOPフラグを指定している。
あと、マニフェストで android:launchMode:singleTask を指定してやる。
とりあえず、起動画面が呼ばれているポイントが分かれば、そこをガッチリ掴んでやればOK。
onCreate()で行っている処理を、onNewIntent()でもやってやることでなんとか事なきを得た。
なんでこんなよくわからない挙動をしているのかは、知人もよくわからないらしいので、時間があれば調べてみたいと思う。
※この記事の作業用BGM