onResumeはAndroidのライフサイクルメソッドで、ActivityまたはFragmentがフォアグラウンドに来て入力フォーカスを取得したときに呼び出されます。この状態では、画面はユーザーとの対話の準備ができています。すべてのタッチイベント、キー押下、ジェスチャーがこのコンポーネントに送られます。onResumeはActivityの作業状態であり、アプリケーションがほとんどの時間を過ごす場所です。ここでカメラを開き、ビデオ再生を開始し、音声認識を開始し、排他的アクセスを必要とするセンサーリスナーを登録します。完全なActivityライフサイクルの詳細については、記事Activity Lifecycleをお読みください。
重要なポイント
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から戻る時、ダイアログを閉じる時、デバイスのロックを解除する時。これは“ホット”なメソッドで、セッション中に何度も呼び出される可能性があり、その実装は可能な限り軽量であるべきです。
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は、それを含むActivityがonResumeを受け取った後に呼び出されます。ただし、FragmentManagerとViewPagerの特性により、FragmentのonResume呼び出しのタイミングはActivityに対して遅れる可能性があります。例えば、offscreenPageLimit = 1のViewPager内のFragmentは、Activityの起動時ではなく、現在のページになったときにのみonResumeを受け取ります。
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()を使用することを推奨します。
開発者はしばしばonStartとonResumeを混同し、コードを間違ったメソッドに配置します。主なルール:onStart — 可視性がある間動作するリソース用。onResume — 入力フォーカスを必要とするリソース用。具体的なシナリオと正しいメソッドの選択を見てみましょう。
| 操作 | メソッド | 理由 |
|---|---|---|
| 位置情報のサブスクリプション | onStart / onStop | GPSは部分的な可視性でも動作可能 |
| カメラを開く | onResume / onPause | カメラは排他リソース |
| BroadcastReceiver | onStart / 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の準備はonCreateで行い、録音の開始はonResumeで行います。ユーザーが別のアプリケーションに切り替えると、onPauseが録音を一時停止し、onResumeが再開します。これはボイスレコーダーやビデオ録画アプリケーションの標準的な動作です。
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)は、ActivityがonResume状態にあるときのみ呼び出す必要があります。onCreateやonStartで呼び出すと、Activityの初期化が完了する前に生体認証ダイアログが表示され、結果の処理が正しく行われない可能性があります。onResumeで呼び出すことで、生体認証ウィンドウが正しいコンテキストで表示されることが保証されます。
商用プロジェクトで使用されているonResumeの3つの実証済みパターンを見てみましょう:非アクティブタイマーのリセット、表示データの更新、Jetpack Navigationとの統合。
機密データを扱うアプリケーション(銀行、医療記録)では、onResumeを使用して自動ログアウトタイマーをリセットします。ユーザーがアプリケーションと積極的に対話している場合、画面遷移のたびにonResumeが呼び出され、タイマーがリセットされます。ユーザーがアプリケーションを最小化すると、onPauseがタイマーを停止し、戻ったときにonResumeがタイマーをリセットするか、再認証を要求します。
画面に戻るたびに最新のデータを表示する必要があるリストは、onResumeで更新されます。例えば、ユーザーが別のActivityで新しいエントリを作成して戻ってきた場合、onResumeがローカルデータベースまたはViewModelキャッシュからリストを再読み込みします。これにより、手動でのnotifyDataSetChanged呼び出しなしでデータの一貫性が確保されます。
override fun onResume() {
super.onResume()
// ActivityResultLauncherが結果を返しました — リストを更新しています
viewModel.refreshList()
// 非アクティブタイマーのリセット
inactivityTimer.reset()
}
Jetpack Navigationでは、フラグメントのonResumeは、バックナビゲーションを介してそれに戻るたびに呼び出されます。このプロパティはUI状態のリセットに使用されます:キーボードを非表示にし、検索フィールドをクリアし、ツールバーのタイトルを更新します。OnBackPressedCallbackをonResumeと組み合わせることで、コードの重複なしにナビゲーションを完全に制御できます。
よくある質問
onStart — 画面が見える。onResume — 画面がアクティブで対話の準備ができている。想像してください:あなたはテレビを見ています(onStart)が、リモコンを手に取ります(onResume)。テレビは常に見えますが、対話はリモコンでのみ始まります。誰かがテレビをカーテンで覆うと — 画面は見えなくなります(onStop)。誰かがあなたからリモコンを奪うと — 対話は停止します(onPause)が、テレビはまだ見えています。
onResumeはActivityが入力フォーカスを取得するたびに呼び出されます。最小は1回(起動時)。最大は使用シナリオに依存します:画面の切り替え、ダイアログの開始、デバイスのクイックロックとロック解除 — そのような各シナリオは、画面に戻るときにonResumeを呼び出します。
カメラは一度に1つのアプリケーションのみが利用できる排他リソースです。onCreateやonStartでカメラを開くと、アプリケーションが非アクティブでも他のアプリケーションに対してロックされたままになります。onResumeは、Activityがフォアグラウンドにある場合にのみカメラが開いていることを保証し、onPauseがすぐに閉じます。これはAndroid開発の標準であり、CameraXおよびCamera2 APIのドキュメントで確立されています。
はい、Activityが表示された直後に別のActivityによって覆われた場合、onResumeは発生しない可能性があります。例えば、Activity AがonCreateまたはonStartメソッドでActivity Bを開始した場合、AはonStart → onPause → onStopを受け取り、onResumeをスキップします。システムはonResumeを呼び出しません。Activity Aが入力フォーカスを一度も受け取っていないためです。
onResumeでは、長時間の同期操作を実行してはいけません:ネットワークからの大量データの読み込み、複雑なSQLクエリ、画像処理。onResumeはUIスレッドで実行され、100〜200ミリ秒を超えるブロッキングはインターフェースの応答遅延を引き起こします。すべての重い操作は非同期であるべきです — コルーチン、RxJava、またはWorkManagerを介して。また、確認せずにonResumeでfinish()を呼び出すことは推奨されません — 再作成の無限ループにつながる可能性があります。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。