Inactive — ActiveとBackgroundの間の移行状態

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

Inactive — ActiveとBackgroundの間のアプリケーションライフサイクルにおける移行状態で、アプリは画面に表示されているがタッチイベントを受け取りません。iOSおよびAndroidでInactiveがどのように発生するか、どのデリゲートメソッドがそれを処理するか、割り込み(電話、通知、システムジェスチャー)を正しく処理する方法を説明します。

主なポイント

  • Inactive — アプリは画面に表示されているが、システム割り込みによりタッチイベントを受け取らない
  • applicationWillResignActive — iOSでInactiveへの移行を知らせる主要メソッド
  • 一時的な性質 — Inactiveは数分の一秒から数秒間続き、その後ActiveまたはBackgroundに移行する
  • 原因 — 着信、Control Center、Notification Center、システムアラート、Apple Pay、Siri
  • SwiftUI — scenePhase .inactiveはUIKitのInactiveと同等

Inactive — 移行状態の本質

Inactiveは、ActiveとBackgroundの間の移行中に発生するモバイルアプリのライフサイクルにおける中間状態です。この状態では、アプリはまだフォアグラウンドにありユーザーに表示されますが、タッチイベント、キー入力、その他のUIイベントを受け取りません。システムはアプリへのイベント配信をブロックしますが、UIは画面に残り、最小化されません。

Inactiveの性質は一時的です。この状態は、システム割り込みが続く間だけ続きます:Control Centerをすばやく閉じる場合は0.1秒、着信画面を伴う着信の場合は数秒間。割り込みが終了すると、アプリはActiveに戻るか、ユーザーが別のアプリに切り替えた場合はBackgroundに移行します。Inactiveは両方向に移行できる唯一の状態です:Activeに戻るか、Backgroundに進むか。

iOSでは、Inactiveはシステムによって自動的に管理されます。開発者はInactiveの時間を延長したり短縮したりできません — UIApplicationによって完全に制御されます。開発者ができる唯一のことは、applicationWillResignActiveを介したInactiveへの移行と、applicationDidBecomeActiveを介した復帰を正しく処理することです。Androidでは、同等のものはonPauseです。ただし、セマンティクスは異なります:onPauseは、Activityが別のコンポーネントによって部分的に覆われている場合でも呼び出されます。

iOSとAndroidのInactiveの比較

iOSでは、Inactiveはアプリケーションライフサイクルの個別の状態です(5つのうちの1つ:Not Running、Active、Inactive、Background、Suspended)。Androidには直接の同等物はありません — onPauseは、Activityが入力フォーカスを失いつつあるが表示されたままである可能性があることを通知します(例えば、ダイアログが開いたとき)。主な違い:iOSのInactiveはアプリ全体の状態ですが、AndroidのonPauseはActivityごとの状態です。Androidのマルチウィンドウでは、あるActivityがonPause(フォーカスなし)で、別のActivityがonResume(フォーカスあり)であることがあります。

特性iOS InactiveAndroid onPause
UI表示はいはい(部分的または完全に)
タッチイベント受け取らない受け取らない
期間割り込みが終了するまでフォーカスが戻るかバックグラウンドに移動するまで
次の状態ActiveまたはBackgroundonResumeまたはonStop
レベルアプリ(UIApplication)Activity
マルチウィンドウ1つのシーンのみアクティブ複数のActivityがonPause状態

Inactiveが発生するタイミング

InactiveはiOSではいくつかの厳密に定義されたシナリオで発生します。ユーザーがControl Centerを開く(iPhone X+では右上隅から下にスワイプ、古いモデルでは上にスワイプ)。ユーザーがNotification Centerを開く(左上隅から下にスワイプ)。着信が来る — システムがアプリの上に着信画面を表示する。システム許可が要求される — 位置情報、マイク、カメラ、連絡先。iPadでSlide OverまたはSplit Viewが起動される — アクティブなシーンがInactiveになる。

Androidでは、onPause(Inactiveの同等物)はさらに幅広い状況で発生します。ダイアログの開封(AlertDialog、DialogFragment)。別のActivityによるActivityの部分的なオーバーレイ(例えば、認証用の透過Activity)。画面の回転(Activityが再作成される、順序:onPause → onStop → onDestroy → onCreate → onStart → onResume)。マルチウィンドウモード — 非アクティブなウィンドウがonPauseを受け取る。これらの各イベントでは、バッテリーとパフォーマンスを維持するためにリソース集約型の操作を一時停止する必要があります

swift
import UIKit

extension Notification.Name {
    static let systemInterruptionBegan = Notification.Name("systemInterruptionBegan")
    static let systemInterruptionEnded = Notification.Name("systemInterruptionEnded")
}

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func applicationWillResignActive(_ application: UIApplication) {
        // アプリがInactiveに移行 — システム割り込み
        print("割り込み:Control Center、電話、またはシステムアラート")

        // 時間に敏感な操作を一時停止
        pauseVideoPlayback()
        stopContinuousDataCollection()
        hideSensitiveInformation()

        // コンポーネントに通知
        NotificationCenter.default.post(name: .systemInterruptionBegan, object: nil)
    }

    // InactiveからActiveに復帰
    func applicationDidBecomeActive(_ application: UIApplication) {
        resumeVideoPlayback()
        restartDataCollection()
        NotificationCenter.default.post(name: .systemInterruptionEnded, object: nil)
    }

    private func pauseVideoPlayback() {
        // 音声が重ならないようにビデオを一時停止
    }

    private func hideSensitiveInformation() {
        // スクリーンショット時に機密データを非表示
        // Control Center/App SwitcherがUIのスクリーンショットを撮る
    }
}

コードはUIKitでのInactive処理を示しています。applicationWillResignActiveはビデオを一時停止し、データ収集を停止し、機密情報を非表示にします。これは、Control CenterまたはApp Switcherが開かれたときに、システムが現在のUIのスクリーンショットを撮るため重要です — ユーザーがプレビューで機密データを見る可能性があります。NotificationCenterにより、アプリのコンポーネントが割り込みイベントを購読できます。

iOSのInactive: SwiftとUIKit

iOSでは、Inactiveは一対のメソッドによって処理されます:applicationWillResignActive(Inactiveへの移行)とapplicationDidBecomeActive(Inactiveからの復帰)。これらのメソッドはUIApplicationDelegateの一部であり、Inactiveを経由するすべての移行で呼び出されます。iOS 13とUISceneDelegate以降、マルチウィンドウシナリオのためにsceneWillResignActiveとsceneDidBecomeActiveが追加されました。

SceneDelegateとマルチウィンドウInactive

iOS 13+のiPadでは、アプリは複数のシーン(ウィンドウ)を持つことができます。各シーンには独自のライフサイクルがあります。1つのシーンがInactiveになる(ユーザーが別のシーンに切り替えた)一方で、別のシーンはActiveのままであることができます。これはiPhoneとの重要な違いです。iPhoneではInactiveはアプリ全体のグローバル状態です。iPad向けに開発する場合は、各シーンごとにInactiveを個別に処理する必要があります。

swift
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    // シーンが非アクティブになる
    func sceneWillResignActive(_ scene: UIScene) {
        // iPadではこのシーンはフォーカスを失うが、他のシーンはアクティブのまま
        print("シーンがアクティビティを失う")

        // このシーンのタスクを一時停止
        pauseSceneSpecificOperations()
    }

    // シーンがアクティブになる
    func sceneDidBecomeActive(_ scene: UIScene) {
        print("シーンがアクティブになった")
        resumeSceneSpecificOperations()
    }

    private func pauseSceneSpecificOperations() {
        // このシーンに固有の操作を一時停止
    }

    private func resumeSceneSpecificOperations() {
        // フォーカスが戻ったときに操作を再開
    }
}

// AppDelegateはエントリポイントのまま、シーンに委任
@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(
        _ application: UIApplication,
        configurationForConnecting connectingSceneSession: UISceneSession,
        options: UIScene.ConnectionOptions
    ) -> UISceneConfiguration {
        return UISceneConfiguration(
            name: "Default Configuration",
            sessionRole: connectingSceneSession.role
        )
    }
}

コードはシーンレベルでInactiveを処理するSceneDelegateを示しています。sceneWillResignActiveは、特定のウィンドウがフォーカスを失ったときに呼び出されます — これはiPadでウィンドウ間を切り替えるときに発生する可能性があります。AppDelegateはマルチウィンドウをサポートするためにUISceneConfigurationを設定します。各シーンは独立した状態を持ち、開発者はそれらを個別に処理する必要があります。

AndroidのInactive: onPauseと可視性

Androidでは、iOSのInactiveに直接相当するのは、ActivityライフサイクルのonPause()メソッドです。これは、Activityが入力フォーカスを失ったが表示されたままである可能性がある場合に呼び出されます。典型的なシナリオ:ダイアログを開く、同じアプリで別のActivityを起動する、着信、HomeまたはRecentsボタンを押す。onPauseでは、開発者はリソース集約型の操作 — アニメーション、ビデオ再生、カメラ作業 — を一時停止する必要があります。

Androidの重要な違いは、onPauseは常にonStopの前に発生するが、その逆はないことです。ActivityはonStopなしでonPauseを受け取ることができます(例えば、透過Activityを開くとき)。また、onPauseはActivityのライフタイム中に複数回呼び出される可能性があります — フォーカスが切り替わるたびに。onPauseに一度きりのロジックを配置しないでください — 最終的な操作にはonStopを使用し、onPauseはインタラクティブなアクションを一時停止するためだけに使用してください。

kotlin
class VideoPlayerActivity : AppCompatActivity() {

    private var exoPlayer: ExoPlayer? = null
    private var currentPosition: Long = 0L

    override fun onPause() {
        super.onPause()
        // アプリがフォーカスを失う — ビデオを一時停止
        exoPlayer?.let { player ->
            if (player.isPlaying) {
                currentPosition = player.currentPosition
                player.pause()
            }
        }
        // 機密データを非表示(GDPR/銀行画面)
        if (window.decorView.systemUiVisibility and
            View.SYSTEM_UI_FLAG_SECURE == 0
        ) {
            hideSensitiveOverlay()
        }
    }

    override fun onResume() {
        super.onResume()
        // フォーカスが戻る — 再生を再開
        exoPlayer?.seekTo(currentPosition)
        exoPlayer?.play()
        showSensitiveOverlay()
    }

    private fun hideSensitiveOverlay() {
        // 金融データの上に黒い画面を重ねる
    }
}

コードはビデオプレーヤーの正しいonPause処理を示しています。ExoPlayerが一時停止され、フォーカスが失われたときに再生位置が保存されます。onResumeに戻ると、プレーヤーは保存された位置から再生を再開します。さらに、機密データを非表示にするパターンが示されています — 切り替え時にスクリーンショットからの保護が必要な金融および医療アプリにとって重要です。

Inactive処理のベストプラクティス

第一のルール — Inactiveに移行する際に機密データを非表示にします。ユーザーがControl CenterまたはApp Switcherを開くと、iOSは現在の画面のスクリーンショットを撮ります。Androidでも同様に、システムはRecentsの最後のActivityのプレビューを表示します。機密画面を保護するには、UIApplication.shouldSnapshotSecureApp(iOS 16+)またはFLAG_SECURE(Android)を使用してください。

第二のルール — アニメーションとメディアを一時停止します。Inactiveはビデオやアニメーションを再生するのに適した時間ではありません。ユーザーはそれらを見ることができません。さらに、バックグラウンド再生はシステムサウンド(着信音、通知)とオーディオが重なる可能性があります。Inactiveに移行する際はAVPlayer、ExoPlayer、UIView.animateを停止し、Activeに戻る際に再開してください。

第三のルール — データ入力をブロックします。アプリに入力フォームや下書きが含まれている場合、Inactiveに移行する際にキーボードと入力フィールドをロックします。これにより、復帰時の誤入力を防ぎ、システムオーバーレイを介したデータ傍受から保護します。iOSではファーストレスポンダーを解除し(view.endEditing(true))、Androidではフォーカスをクリアします(currentFocus?.clearFocus())。

第四のルール — applicationWillResignActiveまたはonPauseで長時間の操作を行わないでください。これらのメソッドは数分の一秒で完了する必要があります。大量のデータを保存する必要がある場合は、バックグラウンドスレッドで保存を開始し、applicationDidEnterBackgroundまたはonStopで完了させてください。iOSはapplicationWillResignActiveの実行に5秒を与え、その後システムはアプリを強制終了する可能性があります。

swift
import UIKit

final class SecureOverlayManager {
    private var blurView: UIVisualEffectView?

    func showBlurOverlay() {
        guard let window = UIApplication.shared.keyWindow,
              blurView == nil
        else { return }

        let blur = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
        blur.frame = window.bounds
        blur.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        window.addSubview(blur)
        blurView = blur
    }

    func removeBlurOverlay() {
        blurView?.removeFromSuperview()
        blurView = nil
    }
}

// AppDelegateでの使用
func applicationWillResignActive(_ application: UIApplication) {
    SecureOverlayManager().showBlurOverlay()
}

func applicationDidBecomeActive(_ application: UIApplication) {
    SecureOverlayManager().removeBlurOverlay()
}

コードはInactiveへの移行中のデータ保護のためのセーフオーバーレイの実装を示しています。ブラー効果のあるUIVisualEffectViewがInactiveに移行する際にUI全体の上に重ねられ、Activeに戻る際に削除されます。これにより、機密データがApp SwitcherおよびControl Centerのスクリーンショットに表示されないことが保証されます。同様に、ブランド化されたオーバーレイにはロゴ付きのUIImageViewを使用できます。

よくある質問

Inactiveは常にBackgroundの前に発生しますか?

はい。InactiveはiOSでBackgroundに移行する前の必須の中間状態です。アプリはActiveから直接Backgroundに移行できません — 最初にInactiveになり、次にBackgroundになります。Androidでも同様に、onPauseは常にonStopの前に呼び出されます。これにより、開発者は完全にバックグラウンドに移行する前にデータを保存する準備をする機会を得られます。

アプリは割り込みなしでInactiveになることができますか?

はい。iPadでSlide OverまたはSplit Viewを起動すると、アクティブなシーンがInactiveになります。システム割り込みは発生しません — ユーザーは単に別のシーンとやり取りしているだけです。これはマルチウィンドウiPadOSの機能です。iPhoneでは、Inactiveは常にシステム割り込み(電話、通知、Control Center、Notification Center)によってトリガーされます。

アプリはInactiveにどのくらい留まることができますか?

通常は0.1秒から2秒です。着信画面を伴う着信中は最大30秒(ユーザーが応答するか拒否するまで)。iOSはInactiveの時間を強制的に制限しませんが、アプリがイベントに応答しない場合(watchdog)、システムはアプリを終了する可能性があります。Androidでは、onPauseに時間制限はありませんが、200 ms以内に作業を完了することをお勧めします。

Inactive中のSwiftUIのscenePhaseとは何ですか?

ScenePhase.inactive — シーンがフォアグラウンドにあるがイベントを受け取っていない場合に設定されるScenePhase列挙値です。SwiftUIでは、@Environment(\.scenePhase)を介して観測し、onChangeを介して反応できます。.activeから.inactiveに移行する際は、タイマーとアニメーションを一時停止します。.activeに戻る際は、それらを再開します。.backgroundに移行する際は、状態を保存します。

すべてのアプリでInactive中にUIを非表示にする必要がありますか?

いいえ、機密データを扱うアプリ(銀行、医療、企業、プライベートチャットのあるメッセージングアプリ)のみです。ゲームやエンターテイメントアプリでは、UIを非表示にする必要はありません。ただし、Inactive中にゲームプレイとサウンドを一時停止することは、システム通知とオーディオが重なるのを避けるための良いプラクティスです。Appleは機密データを非表示にすることを推奨していますが、必須ではありません。

まとめ

  • Inactive — ActiveとBackgroundの間の移行状態、アプリは表示されるが操作不可
  • 原因 — Control Center、Notification Center、着信、システム許可、Siri、Apple Pay
  • iOSでの処理 — applicationWillResignActiveでアニメーションとメディアを一時停止し機密データを非表示に
  • SwiftUI — Environmentを介したscenePhase .inactive、副作用のためのonChange
  • Android — onPauseが同等、マルチウィンドウと部分的なActivityオーバーレイをサポート
  • セキュリティ — App SwitcherおよびControl Centerのスクリーンショットからの保護にブラーオーバーレイまたはFLAG_SECURE
  • 一時的な性質 — Inactiveは割り込みが終了するまで続き、その後Activeに戻るかBackgroundに移行

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

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

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

こちらもお読みください