onResume — 基本、Androidでのユーザーインタラクション

著者: IT Sectr 公開日: 2026-03-04 読了時間: 10 分

onResumeはAndroidのライフサイクルメソッドで、ActivityまたはFragmentがフォアグラウンドに来て入力フォーカスを取得したときに呼び出されます。この状態では、画面はユーザーとの対話の準備ができています。すべてのタッチイベント、キー押下、ジェスチャーがこのコンポーネントに送られます。onResumeはActivityの作業状態であり、アプリケーションがほとんどの時間を過ごす場所です。ここでカメラを開き、ビデオ再生を開始し、音声認識を開始し、排他的アクセスを必要とするセンサーリスナーを登録します。完全なActivityライフサイクルの詳細については、記事Activity Lifecycleをお読みください。

重要なポイント

  • onResume — 入力フォーカスを持つフォアグラウンドのActivity。onStartの後、またはダイアログから戻った後に呼び出される
  • 排他リソース — カメラ、マイク、ビデオキャプチャはonResumeで開き、onPauseで閉じる
  • onResume/onPauseのペア — 完全なフォーカスが必要なリソースはこのペアで管理。onResumeで登録、onPauseで解放
  • onResume vs onStart — onStart = 可視性、onResume = 対話。ダイアログはonResumeを上書きするがonStartは上書きしない
  • タイミング — onResumeは高速であるべき。ここでの長時間の操作はUI応答性を遅らせる
  • Fragment.onResume — Activity.onResumeの後、Fragmentが対話の準備ができたときに呼び出される
  • JetpackでのonResume — lifecycleScopeとLiveDataは自動サブスクリプション管理にonResumeを使用する

AndroidでのonResumeメソッドの基本

onResume — Activityライフサイクルの3番目のメソッドで、onStartの後に呼び出され、画面がユーザーとの完全な対話の準備ができたことを示します。この瞬間、Activityはタスクスタック(バックスタック)の最上位にあり、システムはすべての入力イベントをそれに送り、アプリケーションはユーザーの積極的な参加を必要とする任意の操作(ビデオ通話、ゲーム、オーディオ録音、Canvasへの描画)を開始できます。

onResumeは“フォアグラウンドライフタイム”(foreground lifetime)の一部です — onResumeとonPauseの間の期間です。これはActivityの最もアクティブな期間であり、アプリケーションが最も多くのリソースを消費します:タッチ処理のためのCPU、アニメーションレンダリングのためのGPU、ビデオキャプチャのためのカメラとマイク。ライフサイクルのこのレベルを理解することは、エネルギー消費の最適化に重要です — onResumeで開かれたリソースはonPauseで直ちに閉じる必要があります。

Google I/O 2025によると、Activityが1セッションあたりonResume状態で過ごす平均時間は、ニュースアプリで2〜5分、ゲームやメッセンジャーで15〜30分です。残りの時間、ActivityはonPause、onStop、またはonDestroy状態にあります。つまり、特にonResumeコードを最適化することで、パフォーマンスとバッテリー寿命の最大のメリットが得られます。

ActivityでのonResume

Activityでは、onResumeメソッドは画面が入力フォーカスを取得するたびに呼び出されます — 初回起動時、別のActivityから戻る時、ダイアログを閉じる時、デバイスのロックを解除する時。これは“ホット”なメソッドで、セッション中に何度も呼び出される可能性があり、その実装は可能な限り軽量であるべきです。

kotlin
class CameraActivity : AppCompatActivity() {
    private var cameraProvider: ProcessCameraProvider? = null
    private var preview: Preview? = null

    override fun onResume() {
        super.onResume()
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            cameraProvider = cameraProviderFuture.get()
            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
            preview = Preview.Builder().build().also {
                it.setSurfaceProvider(binding?.viewFinder?.surfaceProvider)
            }
            try {
                cameraProvider?.unbindAll()
                cameraProvider?.bindToLifecycle(
                    this, cameraSelector, preview
                )
            } catch (e: Exception) {
                Log.e("Camera", "Failed to bind camera", e)
            }
        }, ContextCompact.getMainExecutor(this))
    }

    override fun onPause() {
        super.onPause()
        cameraProvider?.unbindAll()
        preview = null
    }
}

CameraXの例は、onResume/onPauseの古典的な使用法を示しています:カメラは一度に1つのアプリケーションだけが使用できる排他リソースです。bindToLifecycleを介してカメラをライフサイクルにバインドすると、onPauseでカメラが自動的に閉じられますが、明示的なunbindAll呼び出しにより即座に解放されます。これはActivity間の切り替え時に特に重要です:別のActivityがカメラを開こうとする前に、カメラを解放する必要があります。

FragmentでのonResume

FragmentのonResumeは、それを含むActivityがonResumeを受け取った後に呼び出されます。ただし、FragmentManagerとViewPagerの特性により、FragmentのonResume呼び出しのタイミングはActivityに対して遅れる可能性があります。例えば、offscreenPageLimit = 1のViewPager内のFragmentは、Activityの起動時ではなく、現在のページになったときにのみonResumeを受け取ります。

kotlin
class VideoPlayerFragment : Fragment() {
    private var exoPlayer: ExoPlayer? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        exoPlayer = ExoPlayer.Builder(requireContext()).build()
        binding?.playerView?.player = exoPlayer
    }

    override fun onResume() {
        super.onResume()
        exoPlayer?.play()
        if (userVisibleHint) {
            startBiometricAuth()
        }
    }

    override fun onPause() {
        exoPlayer?.pause()
        stopBiometricAuth()
        super.onPause()
    }
}

Fragment.onResumeでのuserVisibleHintチェックはViewPagerに関連します:FragmentはonResumeを受け取っても、隣接するページによって隠されている可能性があります(例えば、アニメーション遷移中)。そのような場合、可視性を確認せずにonResumeでビデオや生体認証を開始すると、予期しない動作を引き起こします。Fragment 1.5.0以降では、ViewPager2でのフラグメントのライフサイクルを正確に制御するためにFragmentTransaction.setMaxLifecycle()を使用することを推奨します。

onResume vs onStart:それぞれの使いどころ

開発者はしばしばonStartとonResumeを混同し、コードを間違ったメソッドに配置します。主なルール:onStart — 可視性がある間動作するリソース用。onResume — 入力フォーカスを必要とするリソース用。具体的なシナリオと正しいメソッドの選択を見てみましょう。

操作メソッド理由
位置情報のサブスクリプションonStart / onStopGPSは部分的な可視性でも動作可能
カメラを開くonResume / onPauseカメラは排他リソース
BroadcastReceiveronStart / onStopシステムイベントはフォーカス不要
ビデオ再生onResume / onPauseビデオはユーザーに見える必要がある
BluetoothスキャンonStart / onStopスキャンはバックグラウンドで可能
ボイスレコーダー(MediaRecorder)onResume / onPause録音にはアクティブなUIが必要
センサーリスナーonResume / onPauseゲームやジェスチャー用のセンサー
データ更新onStart表示時に最新データが必要

実用的なルール:ダイアログが表示されたときに操作を中断すべき場合 — onResume/onPauseを使用します。画面が部分的に覆われていても操作を続行できる場合 — onStart/onStopを使用します。例えば、ビデオプレーヤーはダイアログが開かれたときにビデオを一時停止するべきですが(onPause)、位置情報は更新を続けることができます(onStartのまま)。

排他リソースの管理

排他リソースとは、特定の時点で1つのアプリケーションのみが使用できるデバイスコンポーネントです。カメラ、マイク、ビデオ出力(MediaProjection)、読み取りモードのNFCアダプター、アクセサリモードのUSBデバイス — これらすべてのリソースはonResumeで開き、onPauseで解放する必要があります。

MediaRecorderの操作

MediaRecorderはオーディオとビデオの録音に使用されます。パーミッションのリクエストとMediaRecorderの準備はonCreateで行い、録音の開始はonResumeで行います。ユーザーが別のアプリケーションに切り替えると、onPauseが録音を一時停止し、onResumeが再開します。これはボイスレコーダーやビデオ録画アプリケーションの標準的な動作です。

kotlin
private var mediaRecorder: MediaRecorder? = null
private var isRecording = false

override fun onResume() {
    super.onResume()
    if (isRecording) {
        mediaRecorder?.resume()
    }
}

override fun onPause() {
    if (isRecording) {
        mediaRecorder?.pause()
    }
    super.onPause()
}

BiometricPromptとonResume

生体認証(BiometricPrompt)は、ActivityがonResume状態にあるときのみ呼び出す必要があります。onCreateやonStartで呼び出すと、Activityの初期化が完了する前に生体認証ダイアログが表示され、結果の処理が正しく行われない可能性があります。onResumeで呼び出すことで、生体認証ウィンドウが正しいコンテキストで表示されることが保証されます。

パターンと推奨事項

商用プロジェクトで使用されているonResumeの3つの実証済みパターンを見てみましょう:非アクティブタイマーのリセット、表示データの更新、Jetpack Navigationとの統合。

非アクティブタイマーのリセット

機密データを扱うアプリケーション(銀行、医療記録)では、onResumeを使用して自動ログアウトタイマーをリセットします。ユーザーがアプリケーションと積極的に対話している場合、画面遷移のたびにonResumeが呼び出され、タイマーがリセットされます。ユーザーがアプリケーションを最小化すると、onPauseがタイマーを停止し、戻ったときにonResumeがタイマーをリセットするか、再認証を要求します。

戻り時のデータ更新

画面に戻るたびに最新のデータを表示する必要があるリストは、onResumeで更新されます。例えば、ユーザーが別のActivityで新しいエントリを作成して戻ってきた場合、onResumeがローカルデータベースまたはViewModelキャッシュからリストを再読み込みします。これにより、手動でのnotifyDataSetChanged呼び出しなしでデータの一貫性が確保されます。

kotlin
override fun onResume() {
    super.onResume()
    // ActivityResultLauncherが結果を返しました — リストを更新しています
    viewModel.refreshList()
    // 非アクティブタイマーのリセット
    inactivityTimer.reset()
}

Jetpack NavigationとonResume

Jetpack Navigationでは、フラグメントのonResumeは、バックナビゲーションを介してそれに戻るたびに呼び出されます。このプロパティはUI状態のリセットに使用されます:キーボードを非表示にし、検索フィールドをクリアし、ツールバーのタイトルを更新します。OnBackPressedCallbackをonResumeと組み合わせることで、コードの重複なしにナビゲーションを完全に制御できます。

よくある質問

onResumeとonStartの違いを簡単に説明すると?

onStart — 画面が見える。onResume — 画面がアクティブで対話の準備ができている。想像してください:あなたはテレビを見ています(onStart)が、リモコンを手に取ります(onResume)。テレビは常に見えますが、対話はリモコンでのみ始まります。誰かがテレビをカーテンで覆うと — 画面は見えなくなります(onStop)。誰かがあなたからリモコンを奪うと — 対話は停止します(onPause)が、テレビはまだ見えています。

onResumeはどのくらいの頻度で呼び出されますか?

onResumeはActivityが入力フォーカスを取得するたびに呼び出されます。最小は1回(起動時)。最大は使用シナリオに依存します:画面の切り替え、ダイアログの開始、デバイスのクイックロックとロック解除 — そのような各シナリオは、画面に戻るときにonResumeを呼び出します。

なぜonResumeがカメラを開くのに最適な場所なのですか?

カメラは一度に1つのアプリケーションのみが利用できる排他リソースです。onCreateやonStartでカメラを開くと、アプリケーションが非アクティブでも他のアプリケーションに対してロックされたままになります。onResumeは、Activityがフォアグラウンドにある場合にのみカメラが開いていることを保証し、onPauseがすぐに閉じます。これはAndroid開発の標準であり、CameraXおよびCamera2 APIのドキュメントで確立されています。

onStartの後にonResumeが呼び出されないことはありますか?

はい、Activityが表示された直後に別のActivityによって覆われた場合、onResumeは発生しない可能性があります。例えば、Activity AがonCreateまたはonStartメソッドでActivity Bを開始した場合、AはonStart → onPause → onStopを受け取り、onResumeをスキップします。システムはonResumeを呼び出しません。Activity Aが入力フォーカスを一度も受け取っていないためです。

onResumeでやってはいけないことは?

onResumeでは、長時間の同期操作を実行してはいけません:ネットワークからの大量データの読み込み、複雑なSQLクエリ、画像処理。onResumeはUIスレッドで実行され、100〜200ミリ秒を超えるブロッキングはインターフェースの応答遅延を引き起こします。すべての重い操作は非同期であるべきです — コルーチン、RxJava、またはWorkManagerを介して。また、確認せずにonResumeでfinish()を呼び出すことは推奨されません — 再作成の無限ループにつながる可能性があります。

まとめ

  • onResume — 入力フォーカスを持つフォアグラウンド状態。Activityはユーザーとの対話の準備ができている
  • 排他リソース — カメラ、マイク、ビデオキャプチャはonResumeで開き、onPauseで閉じる
  • onResume vs onStart — onStartは可視リソース用、onResumeはアクティブリソース用。ダイアログはonResumeを中断するがonStartは中断しない
  • パフォーマンス — onResumeは軽量であるべき。すべての重い操作は非同期
  • Fragment.onResume — ViewPagerでの可視性に依存。userVisibleHintを確認するか、setMaxLifecycleを使用
  • 典型的なタスク — タイマーリセット、戻り時のデータ更新、BiometricPromptの管理
  • onResume/onPauseペア — 排他アクセスを持つリソースはこのペアのみで管理

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください