↩️

Android 16 で Predictive Back を有効にしつつ戻るときに処理を差し込む

に公開

この記事は「Android 16 で Predictive Back を有効にしつつ 戻る確定直前にだけ処理を差し込む方法を紹介します。


1. 背景

  • 戻る処理をBackHandlerやonBackPressedDispatcherなどで上書きすると、36以降でPredectiveBackが有効にならない

👉 解決策
システムの戻るフローを邪魔せず onBeforeFinish() だけ挟み、
他は OS 標準の finish(API 36+ なら Predictive Backあり)に任せる。


2. 拡張関数の作成

/**
 * Predictive-Back 対応バックハンドラ。
 * API 36+ → OS の finish アニメを活かしつつ副作用を実行
 * API 28-35 → 従来 onBackPressedDispatcher で同じ副作用を実行
 */
fun ComponentActivity.registerPredictiveBackHandler(
    onBeforeFinish: () -> Unit
) {
    if (Build.VERSION.SDK_INT >= 36) {
        // ① 副作用を「戻る確定直前」にだけ注入
        onBackInvokedDispatcher.registerOnBackInvokedCallback(
            OnBackInvokedDispatcher.PRIORITY_SYSTEM_NAVIGATION_OBSERVER
        ) { onBeforeFinish() }
        // ② 終了そのものは OS 既定 (finishAndRemoveTask) が自動実行
    } else {
        // ── 旧 API:従来の戻るボタンをフック ──
        onBackPressedDispatcher.addCallback(
            this,
            object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    onBeforeFinish()
                    finish()
                }
            }
        )
    }
}

使い方

@AndroidEntryPoint
class PlayerActivity : ComponentActivity() {

    private val vm by viewModels<PlayerViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Predictive-Back 対応バックハンドラ登録
        registerPredictiveBackHandler { vm.releasePlayer() }

        setContent { PlayerScreen() }
    }
}

3. 動作フロー

戻る Gesture 開始
 └─ PRIORITY_SYSTEM_NAVIGATION_OBSERVER → onBeforeFinish()   ← 副作用だけ実行
     └─ OS 既定 finishAndRemoveTask()  ← Predictive-Back プレビュー→完了アニメ

API 35 以下は onBeforeFinish()finish() の2 ステップ。


4. その他

Q A
「タスク削除せず背面に送りたい」 moveTaskToBackCallback(this) を自作で登録すれば可
「BackHandlerやonBackPressedDispatcherを併用していい?」 *スタックが残っている画面や条件だけ有効にし、ルート画面や戻るタイミングでは無効にしてください。常時有効にすると Predictive Back が無効化されます。

5. まとめ

  • 副作用だけ差し込むなら PR­IORITY_SYSTEM_NAVIGATION_OBSERVER に登録
    → OS の Predictive-Back アニメもそのまま
  • 旧 API は 簡易的にonBackPressedDispatcher で同じ副作用 → finish()

Discussion