Skip to content

Activityのバックボタン処理:onBackPressed()から最新APIへの移行

Androidアプリ開発において、バックボタンの処理は基本的な機能の一つです。これまで広く使用されていたonBackPressed()メソッドが非推奨(deprecated)となったため、新しい代替方法への移行が必要です。

問題の概要

Android APIレベル33以降、Activity.onBackPressed()メソッドは非推奨となりました。これはAndroidの新しいバックナビゲーションジェスチャーシステムへの移行に伴う変更です。

従来のコード例:

kotlin
override fun onBackPressed() {
    if (isTaskRoot) {
        startActivity(Intent(mContext, Dashboard::class.java))
        finish()
    } else {
        finishWithResultOK()
    }
}

このメソッドを使用すると、次のような警告が表示されます:

'onBackPressed()' is deprecated. Deprecated in Java

推奨される解決策

基本的な代替方法

最もシンプルな代替方法は、OnBackPressedDispatcherを使用することです:

kotlin
// Kotlin
onBackPressedDispatcher.onBackPressed()

// Java
getOnBackPressedDispatcher().onBackPressed();

カスタムバックナビゲーションの実装

バックボタンの動作をカスタマイズする場合は、OnBackPressedCallbackを使用します:

kotlin
// Kotlin
val callback = object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
        // カスタムバックナビゲーション処理
        if (isTaskRoot) {
            startActivity(Intent(this@MyActivity, Dashboard::class.java))
            finish()
        } else {
            finishWithResultOK()
        }
    }
}

onBackPressedDispatcher.addCallback(this, callback)
java
// Java
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
    @Override
    public void handleOnBackPressed() {
        // カスタムバックナビゲーション処理
        if (isTaskRoot()) {
            startActivity(new Intent(MyActivity.this, Dashboard.class));
            finish();
        } else {
            finishWithResultOK();
        }
    }
};

getOnBackPressedDispatcher().addCallback(this, callback);

実装のベストプラクティス

ライフサイクル対応

バックボタンコールバックはアクティビティのライフサイクルに適切に関連付けることが重要です:

kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // バックナビゲーション処理
            handleBackPressed()
        }
    })
}

private fun handleBackPressed() {
    if (isTaskRoot) {
        // ルートアクティビティの場合の処理
        navigateToDashboard()
    } else {
        // それ以外の場合の処理
        finishWithResult()
    }
}

ナビゲーションコンポーネントとの連携

Jetpack Navigationを使用している場合、より統合された方法でバックナビゲーションを処理できます:

kotlin
val appBarConfiguration = AppBarConfiguration(
    setOf(R.id.homeFragment, R.id.profileFragment, R.id.settingsFragment)
)

val callback = object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START)
        } else {
            NavigationUI.navigateUp(navController, appBarConfiguration)
        }
    }
}

onBackPressedDispatcher.addCallback(this, callback)

拡張関数による簡素化

よく使用するパターンは拡張関数として定義することで、コードの重複を減らせます:

kotlin
// Activity拡張関数
fun Activity.onBackButtonPressed(callback: () -> Boolean) {
    (this as? FragmentActivity)?.onBackPressedDispatcher?.addCallback(
        this, 
        object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                if (!callback()) {
                    remove()
                    onBackPressedDispatcher.onBackPressed()
                }
            }
        }
    )
}

// 使用例
onBackButtonPressed {
    if (shouldShowConfirmationDialog()) {
        showExitConfirmationDialog()
        true // システムのデフォルト動作をオーバーライド
    } else {
        false // システムのデフォルト動作を実行
    }
}

注意点と考慮事項

WARNING

バックボタンの処理をオーバーライドする場合、ユーザーがアプリ内で行き詰まらないように注意してください。常にバックナビゲーションを完全に無効化するのではなく、適切な代替ナビゲーションを提供することが重要です。

TIP

OnBackPressedDispatcherはAPIレベル13以降で利用可能であり、Android T(API 33)以降では内部で新しいOnBackInvokedDispatcher APIを自動的に使用します。互換性を気にせずに使用できます。

まとめ

onBackPressed()の非推奨化は、Androidのモダンなバックナビゲーションシステムへの移行の一環です。OnBackPressedDispatcherOnBackPressedCallbackを使用することで、より柔軟で保守性の高いバックナビゲーション処理を実現できます。

新しいAPIは以下の利点を提供します:

  • ライフサイクルに対応した安全な実装
  • 複数のコールバック登録による柔軟な処理
  • ジェスチャーナビゲーションとの互換性
  • ナビゲーションコンポーネントとの統合

既存のコードベースを段階的に移行し、アプリのナビゲーション体験を向上させましょう。