Inactive — суть, переходное состояние между Active и Background

Автор: IT Sectr Опубликовано: 2026-03-03 Время чтения: 10 мин

Inactive — переходное состояние жизненного цикла приложения между Active и Background, в котором приложение видимо на экране, но не получает события касания. Рассказываем, как возникает Inactive на iOS и Android, какие методы делегата за него отвечают и как корректно обрабатывать прерывания — звонки, уведомления и системные жесты.

Главное

  • Inactive — приложение видимо на экране, но не принимает touch-события из-за системного прерывания
  • applicationWillResignActive — основной метод, сигнализирующий о переходе в Inactive на iOS
  • Временный характер — Inactive длится от долей секунды до нескольких секунд, затем следует переход в Active или Background
  • Причины — входящий звонок, Control Center, Notification Center, системный алерт, Apple Pay, Siri
  • SwiftUI — scenePhase .inactive эквивалентен Inactive в UIKit

Inactive — суть переходного состояния

Inactive — промежуточное состояние жизненного цикла мобильного приложения, которое возникает при переходе между Active и Background. В этом состоянии приложение всё ещё находится на переднем плане и видимо пользователю, но не получает события касания, нажатия клавиш и другие UI-события. Система блокирует передачу событий приложению, но при этом UI остаётся на экране и не сворачивается.

Природа Inactive — временная. Это состояние длится ровно столько, сколько длится системное прерывание: от 0.1 секунды при быстром закрытии Control Center до нескольких секунд при входящем звонке с экраном вызова. После завершения прерывания приложение либо возвращается в Active, либо переходит в Background, если пользователь переключился на другое приложение. Inactive — единственное состояние, из которого возможен переход как в обе стороны: обратно в Active или далее в Background.

На iOS Inactive управляется системой автоматически. Разработчик не может продлить или сократить время пребывания в Inactive — это полностью контролируется UIApplication. Единственное, что может сделать разработчик, — корректно обработать уход в Inactive через applicationWillResignActive и возврат через applicationDidBecomeActive. На Android аналогом является onPause, хотя семантика отличается: onPause вызывается даже при частичном перекрытии Activity другим компонентом.

Сравнение Inactive на iOS и Android

На iOS Inactive — это отдельное состояние жизненного цикла приложения (одно из пяти: Not Running, Active, Inactive, Background, Suspended). На Android нет прямого аналога — onPause сигнализирует, что Activity теряет фокус ввода, но может оставаться видимым (например, при открытии диалога). Ключевое различие: iOS Inactive — состояние приложения в целом, Android onPause — состояние конкретной Activity. В multi-window на Android одно Activity может быть в onPause (без фокуса), а другое — в onResume (с фокусом).

ХарактеристикаiOS InactiveAndroid onPause
UI видимДаДа (частично или полностью)
Touch-событияНе принимаетНе принимает
ДлительностьДо завершения прерыванияДо возврата фокуса или ухода в фон
Следующее состояниеActive или BackgroundonResume или onStop
УровеньПриложение (UIApplication)Activity
Multi-windowОдна сцена активнаНесколько 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). Multi-window режим — неактивное окно получает 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
    }
}

В коде показана обработка Inactive в UIKit. applicationWillResignActive приостанавливает видео, останавливает сбор данных и скрывает чувствительную информацию. Это важно, потому что при открытии Control Center или App Switcher система делает скриншот текущего UI — пользователь может увидеть конфиденциальные данные в превью. NotificationCenter позволяет компонентам приложения подписаться на события прерывания.

Inactive в iOS: Swift и UIKit

В iOS Inactive обрабатывается парой методов: applicationWillResignActive (уход в Inactive) и applicationDidBecomeActive (возврат из Inactive). Эти методы являются частью UIApplicationDelegate и вызываются для каждого перехода через Inactive. С iOS 13 и UISceneDelegate к ним добавились sceneWillResignActive и sceneDidBecomeActive для multi-window сценариев.

SceneDelegate и multi-window Inactive

На iPad с iOS 13+ приложение может иметь несколько сцен (окон). Каждая сцена имеет собственный жизненный цикл. Одна сцена может стать Inactive (пользователь переключился на другую сцену), в то время как другая остаётся Active. Это важное отличие от 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
        )
    }
}

В коде показан SceneDelegate для обработки Inactive на уровне сцены. sceneWillResignActive вызывается, когда конкретное окно теряет фокус — это может произойти при переключении между окнами на iPad. AppDelegate настраивает UISceneConfiguration для поддержки multi-window. Каждая сцена имеет независимое состояние, и разработчик должен обрабатывать их отдельно.

Inactive в Android: onPause и видимость

В Android прямым аналогом iOS Inactive является метод onPause() жизненного цикла Activity. Он вызывается, когда Activity теряет фокус ввода, но может оставаться видимым. Типичные сценарии: открытие диалогового окна, запуск другого Activity в том же приложении, входящий звонок, нажатие кнопки Home или Recents. В onPause разработчик должен приостановить ресурсоёмкие операции — анимации, воспроизведение видео, работу с камерой.

Важное отличие Android — onPause всегда предшествует onStop, но не наоборот. Activity может получить onPause без onStop (например, при открытии прозрачного 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 аналогично — система показывает превью последнего Activity в Recents. Используйте UIApplication.shouldSnapshotSecureApp (iOS 16+) или FLAG_SECURE (Android) для защиты конфиденциальных экранов.

Второе правило — приостанавливайте анимации и медиа. Inactive — не лучшее время для воспроизведения видео или анимаций, так как пользователь их не видит. Более того, воспроизведение в фоне может привести к наложению звуков на системные звуки (звонок, уведомление). Останавливайте AVPlayer, ExoPlayer и UIView.animate при уходе в Inactive и возобновляйте при возврате в Active.

Третье правило — блокируйте ввод данных. Если приложение содержит формы ввода или черновики, заблокируйте клавиатуру и поля ввода при уходе в Inactive. Это предотвращает случайный ввод при возврате и защищает от перехвата данных через системные оверлеи. На iOS отключайте first responder (view.endEditing(true)), на Android — очищайте фокус (currentFocus?.clearFocus()).

Четвёртое правило — не выполняйте долгие операции в applicationWillResignActive или onPause. Эти методы должны завершаться за доли секунды. Если нужно сохранить большой объём данных, начните сохранение в фоновом потоке и завершите его в applicationDidEnterBackground или onStop. iOS даёт 5 секунд на выполнение applicationWillResignActive, после чего система может принудительно завершить приложение.

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 с blur-эффектом накладывается поверх всего UI при уходе в Inactive и удаляется при возврате в Active. Это гарантирует, что конфиденциальные данные не будут видны на скриншотах App Switcher и Control Center. Аналогично можно использовать UIImageView с логотипом для брендированного оверлея.

Часто задаваемые вопросы

Всегда ли Inactive предшествует Background?

Да. Inactive — обязательное промежуточное состояние перед переходом в Background на iOS. Приложение не может перейти из Active напрямую в Background — сначала оно становится Inactive, затем Background. На Android аналогично: onPause всегда вызывается перед onStop. Это даёт разработчику возможность подготовить данные к сохранению перед полным уходом в фон.

Может ли приложение получить Inactive без прерывания?

Да. На iPad при запуске Slide Over или Split View активная сцена становится Inactive, хотя никакого системного прерывания не происходит — пользователь просто взаимодействует с другой сценой. Это особенность multi-window iPadOS. На iPhone Inactive всегда вызывается системным прерыванием — звонком, уведомлением, Control Center или Notification Center.

Как долго приложение может находиться в Inactive?

Обычно от 0.1 до 2 секунд. При входящем звонке с экраном вызова — до 30 секунд (пока пользователь не ответит или не отклонит вызов). iOS не ограничивает принудительно время в Inactive, но система может завершить приложение, если оно не реагирует на события (watchdog). На Android onPause не имеет ограничения по времени, но рекомендуется завершать работу за 200 мс.

Что такое scenePhase в SwiftUI при Inactive?

ScenePhase.inactive — значение enum ScenePhase, устанавливаемое, когда сцена находится на переднем плане, но не принимает события. В SwiftUI вы можете наблюдать его через @Environment(\.scenePhase) и реагировать через onChange. При переходе из .active в .inactive приостанавливайте таймеры и анимации. При возврате в .active — возобновляйте. При уходе в .background — сохраняйте состояние.

Нужно ли скрывать UI при Inactive для всех приложений?

Нет, только для приложений, работающих с конфиденциальными данными: банковские, медицинские, корпоративные, мессенджеры с приватными чатами. Для игр и развлекательных приложений скрытие UI не требуется. Однако приостановка игрового процесса и звука при Inactive — хорошая практика, чтобы избежать наложения звуков на системные уведомления. Apple рекомендует скрывать чувствительные данные, но не требует этого.

Итоги

  • Inactive — переходное состояние между Active и Background, приложение видимо но не интерактивно
  • Причины — Control Center, Notification Center, входящий звонок, системные разрешения, Siri, Apple Pay
  • iOS обработка — applicationWillResignActive для приостановки анимаций, медиа и скрытия чувствительных данных
  • SwiftUI — scenePhase .inactive через Environment, onChange для выполнения побочных эффектов
  • Android — onPause как аналог, с поддержкой multi-window и частичного перекрытия Activity
  • Безопасность — blur-оверлей или FLAG_SECURE для защиты от скриншотов App Switcher и Control Center
  • Временный характер — Inactive длится до завершения прерывания, затем возврат в Active или уход в Background

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также