前提条件
Service から次のように Activity を起動しようとした時、直近 5 秒以内に他の Activity を Home キーで閉じていると、startActivity の呼び出しからすぐには Activity が起動しません。
// this は Service Intent intent = new Intent(this, SomeActivity.class); // Service から起動するときには FLAG_ACTIVITY_NEW_TASK が必要 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
Affinity やその他 LaunchMode などの設定に関わらず、Activity を Home キーで閉じたあと 5 秒は Context#startActivity を呼んでもすぐに Activity は起動しないようになっています。
StackOverflow
同じようなことにハマっている人がいて、質問が上がっていました。
Home キーをおした時の処理
PhoneWindowManager に、Home キーを押したときの処理があります。具体的にはPhoneWindowManager#launchHomeFromHotKey(boolean, boolean)
がその処理を受け持つメソッドです。
このメソッドはまず、 KeyGuard が有効かどうかで処理を分岐し、有効でロックスクリーンが表示されている場合はなにもしません。
KeyGuard のアンロックに成功した時、または KeyGuard が関係ない場合にはホームに戻る処理を実行しますが、どちらも必ず次の処理が入ります。
try { ActivityManagerNative.getDefault().stopAppSwitches(); } catch (RemoteException e) { }
名前からして何かを差し止めるための処理に見えますが、ActivityManagerNative.getDefault()
で取得しているオブジェクトの実体はActivityManagerService
です。
ActivityManagerService#stopAppSwitches()
そしてActivityManagerService#stopAppSwitches()
を見ると、次にあげる処理を実行しています。
- メンバ変数の
mAppSwitchesAllowedTime
に5000ミリ秒後(==5秒後)を代入 - メンバ変数の
mDidAppSwitch
にfalseを代入 - Handlerに送信した未実行の
DO_PENDING_ACTIVITY_LAUNCHES_MSG
を削除 APP_SWITCH_DELAY_TIME
の遅延(5000ミリ秒==5秒)でDO_PENDING_ACTIVITY_LAUNCHES_MSG
を再送信
これで"Home キー押下後 5 秒は startActivity がすぐに効かない"の 5 秒という時間の理由がはっきりしました。またDO_PENDING_ACTIVITY_LAUNCHES_MSG
という定数名から分かるとおり、5 秒後にActivityManagerService#L1878
で Activity の起動を再開します。
この 5 秒以内にContext#startActivity(Intent)
を実行すると、ActivityManagerService#checkAppSwitchAllowedLocked()
でfalseが返ります。このメソッドを読んでいるとandroid.Manifest.permission.STOP_APP_SWITCHES
というパーミッションの存在に気が付きますが、このパーミッションの ProtectionLevel はsystemOrSignature
ですから、通常のアプリは許可を得られません。
なぜ Home キー押下後の 5 秒間 Context#startActivity() を止められるのか
APP_SWITCH_DELAY_TIME
のコメントによると、Home キーを押したあとに信頼されない Activity の起動を防ぐためとあります。Home キーのイベントで Activity を起動するような、端末をハイジャックしたような挙動を防ぐためのもののようです。
Home キーのイベント処理からコードを追いかけて分かる通り、Activity#onUserLeaveHint()
などでActivity#finish()
をしていてもこの問題は回避できません。なぜなら問答無用で Home キーのイベントで強制的に 5 秒間の保留が決まるからです。