【android】【備忘録】ロック画面(Keyguard)の上にアクティビティを表示させる その3
記事のまとめ:
- ロック画面でアクティビティを起動しようとするとonStop()まで呼ばれちゃうよ!
- windowのフラグが評価されるのはonStop()の後だよ!
連投に見せかけた下書きがそこにあった(過去形)
どうも、白鳥です。
日々更新するネタは生まなくてはいけないものの、
やっぱり少しずつ少しずつ手持ちのネタを刻んでいきたい。
そう、シュトーレンみたいにね。
はい。下書きです。
あるいは下書きでした(予定)
前回は
『インテント経由でアプリ起動する場合、プロセスの有無に気をつけんしゃい』
という内容でした。
で、今回なんですが、継続してフラグ消去のタイミングについてひっかかりやすいところをば・・・
前回ライフサイクルについて記述しました。
一般的に描かれるライフサイクルの図ではインテントに関する記述がない、と
今回も若干ながらライフサイクルに関わるお話。
ホーム画面からアプリを起動した場合、
該当アプリの
onCreate() ⇒ onStart() ⇒ onResume() と呼ばれるのはandroid開発の初歩ですが
実はロック画面(Keyguard)の状態で、且つプロセスなしでアプリ起動した場合(インテント経由)、呼ばれるのはonResume()までではなく、一気にonStop()まで呼ばれてしまいます。
そして、アクティビティをロック画面の上に表示するか否か、の判定はonStop()を呼び出した後に判定されるのです。
図にするとこんな感じ。
ロック画面より優先して表示するフラグが~と簡単に書いてますが、セキュリティ設定してる場合とかいろいろ見てます。
実はロック画面より上に表示するためのフラグはFLAG_SHOW_WHEN_LOCKED以外にFLAG_DISMISS_KEYGUARDがあるのです。
FLAG_DISMISS_KEYGUARDを設定すると、PINコードなどのロックをかけていない場合のみロック画面の上に表示されます。
ロックしてるかどうかを判定するにはKeyguardManagerのメソッドを利用すると捗ったり。
ちょっと脱線しましたが、上の図を見て気がつかれたでしょうか?
onPause()/onStop()内にWindow.clearFlags()を仕込むと、判定時にフラグが立っていないとみなされ、ロック画面の上にアクティビティが表示されなくなるのです。
ここが地味にハマッたところでして・・・
自分が実装しようとしていたアプリでは、
『インテントでロック画面の上にアクティビティを表示する』
『ただし、電源キー押下でディスプレイをOFFしたとき、アクティビティは非表示となり、ロック画面が表示されるようになる』
という仕様でした。
で、四苦八苦した結果、Window.clearFlags()の処理をするためだけにBroadcastReceiverを設定するハメに・・・
他にもいい方法があったのかもしれないんですが、力及ばずですね。ぐぬぬ。
ログを仕込めば簡単にわかることではあるものの、
割と引っかかるポイントについて書いてみました。
参考になれば幸いです。
--- ここからオマケ ---
さて、コメントにてご相談いただいたのですが
「ロック画面で表示したウィジェットからインテントを飛ばすとロック解除画面に遷移し、アクティビティが起動しない」とのことでした。
その他の条件としては、clearFlags()は仕込んでいない。
後はandroidがKitKutであろうことが推測されるくらいです。
・・・なんでロリポップでロック画面のウィジェットなくなっちゃったんでしょうね?
便利だったのに。
多分脆弱性につながるとかが理由なんでしょうけども。
ちなみに、サービスからインテント投げると普通にアクティビティ起動します。
JerryBeansとLollipopで確認済み。
ので、おそらくウィジェットからインテントを投げる処理についてandroid兄貴からロック解除を求められているのだろうと推測されます。
ウィジェットの実装やってみたかったのでこれ幸いとTP作成