Inactive — istota, stan przejściowy między Active i Background

Autor: IT Sectr Opublikowano: 2026-03-03 Czas czytania: 10 min

Inactive — przejściowy stan cyklu życia aplikacji między Active i Background, w którym aplikacja jest widoczna na ekranie, ale nie odbiera zdarzeń dotyku. Wyjaśniamy, jak powstaje Inactive na iOS i Androidzie, które metody delegata za nie odpowiadają i jak poprawnie obsługiwać przerwania — połączenia, powiadomienia i systemowe gesty.

Najważniejsze

  • Inactive — aplikacja jest widoczna na ekranie, ale nie przyjmuje zdarzeń dotyku z powodu systemowego przerwania
  • applicationWillResignActive — główna metoda sygnalizująca przejście do Inactive na iOS
  • Charakter tymczasowy — Inactive trwa od ułamków sekundy do kilku sekund, a następnie następuje przejście do Active lub Background
  • Przyczyny — połączenie przychodzące, Control Center, Notification Center, systemowy alert, Apple Pay, Siri
  • SwiftUI — scenePhase .inactive jest odpowiednikiem Inactive w UIKit

Inactive — istota stanu przejściowego

Inactive — pośredni stan cyklu życia aplikacji mobilnej, który występuje przy przejściu między Active i Background. W tym stanie aplikacja wciąż znajduje się na pierwszym planie i jest widoczna dla użytkownika, ale nie odbiera zdarzeń dotyku, naciśnięć klawiszy ani innych zdarzeń UI. System blokuje przekazywanie zdarzeń do aplikacji, ale UI pozostaje na ekranie i nie jest zwijany.

Natura Inactive jest tymczasowa. Stan trwa dokładnie tak długo, jak trwa systemowe przerwanie: od 0.1 sekundy przy szybkim zamknięciu Control Center do kilku sekund przy połączeniu przychodzącym z ekranem połączenia. Po zakończeniu przerwania aplikacja albo wraca do Active, albo przechodzi do Background, jeśli użytkownik przełączył się na inną aplikację. Inactive — jedyny stan, z którego możliwe jest przejście w obie strony: z powrotem do Active lub dalej do Background.

Na iOS Inactive jest zarządzane przez system automatycznie. Deweloper nie może wydłużyć ani skrócić czasu przebywania w Inactive — jest to w pełni kontrolowane przez UIApplication. Jedyne, co może zrobić deweloper, to poprawnie obsłużyć przejście do Inactive przez applicationWillResignActive i powrót przez applicationDidBecomeActive. Na Androidzie odpowiednikiem jest onPause, choć semantyka się różni: onPause jest wywoływane nawet przy częściowym zakryciu Activity innym komponentem.

Porównanie Inactive na iOS i Androidzie

Na iOS Inactive — to odrębny stan cyklu życia aplikacji (jeden z pięciu: Not Running, Active, Inactive, Background, Suspended). Na Androidzie nie ma bezpośredniego odpowiednika — onPause sygnalizuje, że Activity traci fokus wejścia, ale może pozostać widoczne (np. przy otwarciu dialogu). Kluczowa różnica: Inactive na iOS to stan aplikacji jako całości, a onPause na Androidzie to stan konkretnej Activity. W trybie multi-window na Androidzie jedna Activity może być w onPause (bez fokusu), a druga — w onResume (z fokusem).

CharakterystykaiOS InactiveAndroid onPause
UI widoczneTakTak (częściowo lub w całości)
Zdarzenia dotykuNie przyjmujeNie przyjmuje
Czas trwaniaDo zakończenia przerwaniaDo powrotu fokusu lub przejścia w tło
Następny stanActive lub BackgroundonResume lub onStop
PoziomAplikacja (UIApplication)Activity
Multi-windowJedna scena aktywnaKilka Activity w onPause

Kiedy występuje Inactive

Inactive na iOS występuje w kilku ściśle określonych scenariuszach. Użytkownik wywołuje Control Center (przesunięcie w dół z prawego górnego rogu na iPhone X+ lub przesunięcie w górę na starszych modelach). Użytkownik otwiera Notification Center (przesunięcie w dół z lewego górnego rogu). Przychodzi połączenie przychodzące — system pokazuje ekran połączenia nad aplikacją. Jest wymagane uprawnienie systemowe — geolokalizacja, mikrofon, kamera, kontakty. Na iPadzie uruchamiany jest Slide Over lub Split View — aktywna scena staje się Inactive.

Na Androidzie onPause (odpowiednik Inactive) występuje w jeszcze szerszym spektrum sytuacji. Otwarcie okna dialogowego (AlertDialog, DialogFragment). Częściowe zakrycie Activity przez inne Activity (np. przezroczysta Activity do autoryzacji). Obrót ekranu (Activity jest odtwarzana, sekwencja: onPause → onStop → onDestroy → onCreate → onStart → onResume). Tryb multi-window — nieaktywne okno otrzymuje onPause. Każde z tych zdarzeń wymaga wstrzymania operacji zasobożernych, aby oszczędzać baterię i wydajność.

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) {
        // Aplikacja przechodzi w Inactive — systemowe przerwanie
        print("Przerwanie: Control Center, połączenie lub systemowy alert")

        // Wstrzymanie operacji wrażliwych na czas
        pauseVideoPlayback()
        stopContinuousDataCollection()
        hideSensitiveInformation()

        // Powiadomienie komponentów
        NotificationCenter.default.post(name: .systemInterruptionBegan, object: nil)
    }

    // Powrót z Inactive do Active
    func applicationDidBecomeActive(_ application: UIApplication) {
        resumeVideoPlayback()
        restartDataCollection()
        NotificationCenter.default.post(name: .systemInterruptionEnded, object: nil)
    }

    private func pauseVideoPlayback() {
        // Wstrzymanie wideo, aby dźwięk się nie nakładał
    }

    private func hideSensitiveInformation() {
        // Ukrycie wrażliwych danych przy zrzucie ekranu
        // Control Center/App Switcher robią zrzut ekranu UI
    }
}

W kodzie pokazano obsługę Inactive w UIKit. applicationWillResignActive wstrzymuje wideo, zatrzymuje zbieranie danych i ukrywa wrażliwe informacje. To ważne, ponieważ przy otwarciu Control Center lub App Switcher system robi zrzut ekranu bieżącego UI — użytkownik może zobaczyć poufne dane w podglądzie. NotificationCenter umożliwia komponentom aplikacji subskrypcję zdarzeń przerwania.

Inactive na iOS: Swift i UIKit

Na iOS Inactive jest obsługiwane przez parę metod: applicationWillResignActive (przejście do Inactive) i applicationDidBecomeActive (powrót z Inactive). Te metody są częścią UIApplicationDelegate i są wywoływane przy każdym przejściu przez Inactive. Od iOS 13 i UISceneDelegate doszły do nich sceneWillResignActive i sceneDidBecomeActive dla scenariuszy multi-window.

SceneDelegate i Inactive w multi-window

Na iPadzie z iOS 13+ aplikacja może mieć kilka scen (okien). Każda scena ma własny cykl życia. Jedna scena może stać się Inactive (użytkownik przełączył się na inną scenę), podczas gdy inna pozostaje Active. To ważna różnica w porównaniu z iPhonem, gdzie Inactive jest stanem globalnym dla całej aplikacji. Przy tworzeniu aplikacji na iPada trzeba obsługiwać Inactive dla każdej sceny osobno.

swift
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    // Scena staje się nieaktywna
    func sceneWillResignActive(_ scene: UIScene) {
        // Na iPadzie ta scena traci fokus, ale inne mogą być aktywne
        print("Scena traci aktywność")

        // Wstrzymanie zadań tej sceny
        pauseSceneSpecificOperations()
    }

    // Scena staje się aktywna
    func sceneDidBecomeActive(_ scene: UIScene) {
        print("Scena stała się aktywna")
        resumeSceneSpecificOperations()
    }

    private func pauseSceneSpecificOperations() {
        // Wstrzymanie operacji specyficznych dla danej sceny
    }

    private func resumeSceneSpecificOperations() {
        // Wznowienie operacji przy powrocie fokusu
    }
}

// AppDelegate pozostaje punktem wejścia, deleguje do scen
@main
class AppDelegate: UIResponder, UIApplicationDelegate {

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

W kodzie pokazano SceneDelegate do obsługi Inactive na poziomie sceny. sceneWillResignActive jest wywoływane, gdy konkretne okno traci fokus — może to nastąpić przy przełączaniu między oknami na iPadzie. AppDelegate konfiguruje UISceneConfiguration do obsługi multi-window. Każda scena ma niezależny stan, a deweloper powinien obsługiwać je osobno.

Inactive na Androidzie: onPause i widoczność

Na Androidzie bezpośrednim odpowiednikiem iOS Inactive jest metoda onPause() cyklu życia Activity. Jest wywoływana, gdy Activity traci fokus wejścia, ale może pozostać widoczne. Typowe scenariusze: otwarcie okna dialogowego, uruchomienie innej Activity w tej samej aplikacji, połączenie przychodzące, naciśnięcie przycisku Home lub Recents. W onPause deweloper powinien wstrzymać operacje zasobożerne — animacje, odtwarzanie wideo, pracę z kamerą.

Ważna różnica na Androidzie — onPause zawsze poprzedza onStop, ale nie odwrotnie. Activity może otrzymać onPause bez onStop (np. przy otwarciu przezroczystej Activity). Ponadto onPause może być wywoływane wielokrotnie w ciągu życia Activity — przy każdej zmianie fokusu. Nie umieszczaj w onPause logiki jednorazowej — używaj onStop do operacji końcowych, a onPause tylko do wstrzymania interaktywnych działań.

kotlin
class VideoPlayerActivity : AppCompatActivity() {

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

    override fun onPause() {
        super.onPause()
        // Aplikacja traci fokus — wstrzymujemy wideo
        exoPlayer?.let { player ->
            if (player.isPlaying) {
                currentPosition = player.currentPosition
                player.pause()
            }
        }
        // Ukrywamy wrażliwe dane (GDPR/ekrany bankowe)
        if (window.decorView.systemUiVisibility and
            View.SYSTEM_UI_FLAG_SECURE == 0
        ) {
            hideSensitiveOverlay()
        }
    }

    override fun onResume() {
        super.onResume()
        // Powrót fokusu — wznawiamy odtwarzanie
        exoPlayer?.seekTo(currentPosition)
        exoPlayer?.play()
        showSensitiveOverlay()
    }

    private fun hideSensitiveOverlay() {
        // Nakładamy czarny ekran na dane finansowe
    }
}

W kodzie pokazano poprawną obsługę onPause dla odtwarzacza wideo. ExoPlayer jest wstrzymywany przy utracie fokusu, a pozycja odtwarzania jest zapisywana. Przy powrocie do onResume odtwarzacz wznawia odtwarzanie z zapisanej pozycji. Dodatkowo pokazano wzorzec ukrywania wrażliwych danych — ważny dla aplikacji finansowych i medycznych, które wymagają ochrony przed zrzutami ekranu przy przełączaniu.

Najlepsze praktyki obsługi Inactive

Pierwsza zasada — ukrywaj poufne dane przy przejściu do Inactive. Gdy użytkownik otwiera Control Center lub App Switcher, iOS robi zrzut ekranu bieżącego ekranu. Na Androidzie analogicznie — system pokazuje podgląd ostatniej Activity w Recents. Używaj UIApplication.shouldSnapshotSecureApp (iOS 16+) lub FLAG_SECURE (Android), aby chronić poufne ekrany.

Druga zasada — wstrzymuj animacje i multimedia. Inactive to nie najlepszy czas na odtwarzanie wideo lub animacji, ponieważ użytkownik ich nie widzi. Co więcej, odtwarzanie w tle może powodować nakładanie się dźwięków na dźwięki systemowe (połączenie, powiadomienie). Zatrzymuj AVPlayer, ExoPlayer i UIView.animate przy przejściu do Inactive i wznawiaj przy powrocie do Active.

Trzecia zasada — blokuj wprowadzanie danych. Jeśli aplikacja zawiera formularze lub wersje robocze, zablokuj klawiaturę i pola wprowadzania przy przejściu do Inactive. Zapobiega to przypadkowemu wpisywaniu przy powrocie i chroni przed przechwyceniem danych przez systemowe nakładki. Na iOS wyłączaj first responder (view.endEditing(true)), a na Androidzie — czyść fokus (currentFocus?.clearFocus()).

Czwarta zasada — nie wykonuj długich operacji w applicationWillResignActive lub onPause. Te metody powinny kończyć się w ułamki sekundy. Jeśli trzeba zapisać dużą ilość danych, rozpocznij zapis w wątku w tle i zakończ go w applicationDidEnterBackground lub onStop. iOS daje 5 sekund na wykonanie applicationWillResignActive, po czym system może przymusowo zakończyć aplikację.

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
    }
}

// Użycie w AppDelegate
func applicationWillResignActive(_ application: UIApplication) {
    SecureOverlayManager().showBlurOverlay()
}

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

W kodzie pokazano implementację bezpiecznej nakładki do ochrony danych przy przejściu do Inactive. UIVisualEffectView z efektem rozmycia jest nakładany na cały UI przy przejściu do Inactive i usuwany przy powrocie do Active. Gwarantuje to, że poufne dane nie będą widoczne na zrzutach ekranu App Switcher i Control Center. Analogicznie można użyć UIImageView z logo do nakładki z brandingiem.

Często zadawane pytania

Czy Inactive zawsze poprzedza Background?

Tak. Inactive — to obowiązkowy stan pośredni przed przejściem do Background na iOS. Aplikacja nie może przejść z Active bezpośrednio do Background — najpierw staje się Inactive, a następnie Background. Na Androidzie analogicznie: onPause zawsze jest wywoływane przed onStop. Daje to deweloperowi możliwość przygotowania danych do zapisu przed całkowitym przejściem w tło.

Czy aplikacja może otrzymać Inactive bez przerwania?

Tak. Na iPadzie przy uruchomieniu Slide Over lub Split View aktywna scena staje się Inactive, chociaż żadne systemowe przerwanie nie następuje — użytkownik po prostu współdziała z inną sceną. To cecha multi-window w iPadOS. Na iPhonie Inactive zawsze jest wywoływane przez systemowe przerwanie — połączenie, powiadomienie, Control Center lub Notification Center.

Jak długo aplikacja może przebywać w Inactive?

Zwykle od 0.1 do 2 sekund. Przy połączeniu przychodzącym z ekranem połączenia — do 30 sekund (dopóki użytkownik nie odbierze lub nie odrzuci połączenia). iOS nie ogranicza przymusowo czasu w Inactive, ale system może zakończyć aplikację, jeśli nie reaguje ona na zdarzenia (watchdog). Na Androidzie onPause nie ma limitu czasu, ale zaleca się kończenie pracy w 200 ms.

Czym jest scenePhase w SwiftUI przy Inactive?

ScenePhase.inactive — wartość enum ScenePhase, ustawiana, gdy scena znajduje się na pierwszym planie, ale nie przyjmuje zdarzeń. W SwiftUI możesz je obserwować przez @Environment(\.scenePhase) i reagować przez onChange. Przy przejściu z .active do .inactive wstrzymuj timery i animacje. Przy powrocie do .active — wznawiaj. Przy przejściu do .background — zapisuj stan.

Czy trzeba ukrywać UI przy Inactive dla wszystkich aplikacji?

Nie, tylko dla aplikacji pracujących z poufnymi danymi: bankowych, medycznych, korporacyjnych, komunikatorów z prywatnymi czatami. Dla gier i aplikacji rozrywkowych ukrywanie UI nie jest wymagane. Jednak wstrzymanie rozgrywki i dźwięku przy Inactive to dobra praktyka, aby uniknąć nakładania się dźwięków na powiadomienia systemowe. Apple zaleca ukrywanie wrażliwych danych, ale tego nie wymaga.

Podsumowanie

  • Inactive — stan przejściowy między Active i Background, aplikacja jest widoczna, ale nieinteraktywna
  • Przyczyny — Control Center, Notification Center, połączenie przychodzące, uprawnienia systemowe, Siri, Apple Pay
  • Obsługa na iOS — applicationWillResignActive do wstrzymywania animacji, multimediów i ukrywania wrażliwych danych
  • SwiftUI — scenePhase .inactive przez Environment, onChange do wykonywania efektów ubocznych
  • Android — onPause jako odpowiednik, z obsługą multi-window i częściowego zakrycia Activity
  • Bezpieczeństwo — nakładka z rozmyciem lub FLAG_SECURE do ochrony przed zrzutami ekranu App Switcher i Control Center
  • Charakter tymczasowy — Inactive trwa do zakończenia przerwania, a następnie powrót do Active lub przejście do Background

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również