Inactive — podstata, přechodový stav mezi Active a Background

Autor: IT Sectr Publikováno: 2026-03-03 Doba čtení: 10 min

Inactive — přechodový stav životního cyklu aplikace mezi Active a Background, ve kterém je aplikace viditelná na obrazovce, ale nepřijímá dotykové události. Vysvětlujeme, jak vzniká Inactive na iOS a Android, které metody delegáta za něj odpovídají a jak správně zpracovávat přerušení — hovory, oznámení a systémová gesta.

Hlavní body

  • Inactive — aplikace je viditelná na obrazovce, ale nepřijímá dotykové události kvůli systémovému přerušení
  • applicationWillResignActive — hlavní metoda signalizující přechod do Inactive na iOS
  • Dočasný charakter — Inactive trvá od zlomků sekundy po několik sekund, poté následuje přechod do Active nebo Background
  • Příčiny — příchozí hovor, Control Center, Notification Center, systémový alert, Apple Pay, Siri
  • SwiftUI — scenePhase .inactive je ekvivalentem Inactive v UIKit

Inactive — podstata přechodového stavu

Inactive — přechodový stav životního cyklu mobilní aplikace, který vzniká při přechodu mezi Active a Background. V tomto stavu je aplikace stále na popředí a viditelná uživateli, ale nepřijímá dotykové události, stisky kláves ani jiné UI události. Systém blokuje přenos událostí do aplikace, ale UI zůstává na obrazovce a není minimalizováno.

Povaha Inactive je dočasná. Tento stav trvá přesně tak dlouho, jak dlouho trvá systémové přerušení: od 0.1 sekundy při rychlém zavření Control Center po několik sekund při příchozím hovoru s obrazovkou hovoru. Po skončení přerušení se aplikace buď vrátí do Active, nebo přejde do Background, pokud uživatel přepnul na jinou aplikaci. Inactive je jediný stav, ze kterého je možný přechod oběma směry: zpět do Active nebo dále do Background.

Na iOS je Inactive spravován systémem automaticky. Vývojář nemůže prodloužit ani zkrátit dobu strávenou v Inactive — je zcela řízena UIApplication. Jediné, co může vývojář udělat, je správně zpracovat přechod do Inactive přes applicationWillResignActive a návrat přes applicationDidBecomeActive. Na Androidu je analogií onPause, i když sémantika se liší: onPause je volán i při částečném zakrytí Activity jinou komponentou.

Srovnání Inactive na iOS a Androidu

Na iOS je Inactive samostatný stav životního cyklu aplikace (jeden z pěti: Not Running, Active, Inactive, Background, Suspended). Na Androidu neexistuje přímá analogie — onPause signalizuje, že Activity ztrácí vstupní fokus, ale může zůstat viditelné (například při otevření dialogu). Klíčový rozdíl: iOS Inactive je stav aplikace jako celku, Android onPause je stav konkrétního Activity. V režimu multi-window na Androidu může být jedno Activity v onPause (bez fokusu) a druhé v onResume (s fokusem).

VlastnostiOS InactiveAndroid onPause
UI viditelnéAnoAno (částečně nebo zcela)
Dotykové událostiNepřijímáNepřijímá
Doba trváníDo konce přerušeníDo návratu fokusu nebo přechodu na pozadí
Další stavActive nebo BackgroundonResume nebo onStop
ÚroveňAplikace (UIApplication)Activity
Multi-windowJedna scéna aktivníVíce Activity v onPause

Kdy vzniká Inactive

Inactive na iOS vzniká v několika přesně definovaných scénářích. Uživatel vyvolá Control Center (tažení dolů z pravého horního rohu na iPhone X+ nebo tažení nahoru na starších modelech). Uživatel otevře Notification Center (tažení dolů z levého horního rohu). Přichází příchozí hovor — systém zobrazí obrazovku hovoru nad aplikací. Je vyžádáno systémové oprávnění — geolokace, mikrofon, kamera, kontakty. Na iPadu se spouští Slide Over nebo Split View — aktivní scéna se stává Inactive.

Na Androidu onPause (analogie Inactive) vzniká v ještě širším spektru situací. Otevření dialogového okna (AlertDialog, DialogFragment). Částečné zakrytí Activity jiným Activity (například průhledné Activity pro autentizaci). Otáčení obrazovky (Activity je znovu vytvořeno, sekvence: onPause → onStop → onDestroy → onCreate → onStart → onResume). Režim multi-window — neaktivní okno obdrží onPause. Každá z těchto událostí vyžaduje pozastavení operací náročných na zdroje pro úsporu baterie a výkonu.

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) {
        // Aplikace přechází do Inactive — systémové přerušení
        print("Přerušení: Control Center, hovor nebo systémový alert")

        // Pozastavení operací citlivých na čas
        pauseVideoPlayback()
        stopContinuousDataCollection()
        hideSensitiveInformation()

        // Upozornění komponent
        NotificationCenter.default.post(name: .systemInterruptionBegan, object: nil)
    }

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

    private func pauseVideoPlayback() {
        // Zastavení videa, aby se zvuk nepřekrýval
    }

    private func hideSensitiveInformation() {
        // Skrytí citlivých dat při snímku obrazovky
        // Control Center/App Switcher pořizují snímek UI
    }
}

Kód ukazuje zpracování Inactive v UIKit. applicationWillResignActive zastaví video, zastaví sběr dat a skryje citlivé informace. To je důležité, protože při otevření Control Center nebo App Switcher systém pořídí snímek aktuálního UI — uživatel může vidět důvěrná data v náhledu. NotificationCenter umožňuje komponentám aplikace přihlásit se k odběru událostí přerušení.

Inactive na iOS: Swift a UIKit

Na iOS je Inactive zpracováván dvojicí metod: applicationWillResignActive (přechod do Inactive) a applicationDidBecomeActive (návrat z Inactive). Tyto metody jsou součástí UIApplicationDelegate a jsou volány pro každý přechod přes Inactive. Od iOS 13 a UISceneDelegate k nim přibyly sceneWillResignActive a sceneDidBecomeActive pro multi-window scénáře.

SceneDelegate a multi-window Inactive

Na iPadu s iOS 13+ může mít aplikace více scén (oken). Každá scéna má svůj vlastní životní cyklus. Jedna scéna se může stát Inactive (uživatel přepnul na jinou scénu), zatímco druhá zůstává Active. To je důležitý rozdíl oproti iPhonu, kde je Inactive globálním stavem pro celou aplikaci. Při vývoji pro iPad je třeba Inactive zpracovávat pro každou scénu zvlášť.

swift
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    // Scéna se stává neaktivní
    func sceneWillResignActive(_ scene: UIScene) {
        // Na iPadu tato scéna ztrácí fokus, ale ostatní mohou být aktivní
        print("Scéna ztrácí aktivitu")

        // Pozastavení úkolů této scény
        pauseSceneSpecificOperations()
    }

    // Scéna se stává aktivní
    func sceneDidBecomeActive(_ scene: UIScene) {
        print("Scéna se stala aktivní")
        resumeSceneSpecificOperations()
    }

    private func pauseSceneSpecificOperations() {
        // Pozastavení operací specifických pro tuto scénu
    }

    private func resumeSceneSpecificOperations() {
        // Obnovení operací při návratu fokusu
    }
}

// AppDelegate zůstává vstupním bodem, deleguje scénám
@main
class AppDelegate: UIResponder, UIApplicationDelegate {

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

Kód ukazuje SceneDelegate pro zpracování Inactive na úrovni scény. sceneWillResignActive je voláno, když konkrétní okno ztrácí fokus — to může nastat při přepínání mezi okny na iPadu. AppDelegate konfiguruje UISceneConfiguration pro podporu multi-window. Každá scéna má nezávislý stav a vývojář by je měl zpracovávat odděleně.

Inactive na Androidu: onPause a viditelnost

Na Androidu je přímou analogií iOS Inactive metoda onPause() životního cyklu Activity. Je volána, když Activity ztrácí vstupní fokus, ale může zůstat viditelné. Typické scénáře: otevření dialogového okna, spuštění jiného Activity ve stejné aplikaci, příchozí hovor, stisk tlačítka Home nebo Recents. V onPause by měl vývojář pozastavit operace náročné na zdroje — animace, přehrávání videa, práci s kamerou.

Důležitý rozdíl na Androidu — onPause vždy předchází onStop, ale ne naopak. Activity může obdržet onPause bez onStop (například při otevření průhledného Activity). Také onPause může být voláno několikrát během života Activity — při každé změně fokusu. Neumisťujte do onPause jednorázovou logiku — použijte onStop pro finální operace a onPause pouze pro pozastavení interaktivních akcí.

kotlin
class VideoPlayerActivity : AppCompatActivity() {

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

    override fun onPause() {
        super.onPause()
        // Aplikace ztrácí fokus — pozastavujeme video
        exoPlayer?.let { player ->
            if (player.isPlaying) {
                currentPosition = player.currentPosition
                player.pause()
            }
        }
        // Skrýváme citlivá data (GDPR/bankovní obrazovky)
        if (window.decorView.systemUiVisibility and
            View.SYSTEM_UI_FLAG_SECURE == 0
        ) {
            hideSensitiveOverlay()
        }
    }

    override fun onResume() {
        super.onResume()
        // Návrat fokusu — obnovujeme přehrávání
        exoPlayer?.seekTo(currentPosition)
        exoPlayer?.play()
        showSensitiveOverlay()
    }

    private fun hideSensitiveOverlay() {
        // Překrýváme černou obrazovkou finanční data
    }
}

Kód ukazuje správné zpracování onPause pro přehrávač videa. ExoPlayer je pozastaven při ztrátě fokusu a pozice přehrávání je uložena. Při návratu do onResume přehrávač obnoví přehrávání z uložené pozice. Dále je ukázán vzor skrývání citlivých dat — důležitý pro finanční a lékařské aplikace vyžadující ochranu před snímky obrazovky při přepínání.

Nejlepší postupy zpracování Inactive

První pravidlo — skrývejte důvěrná data při přechodu do Inactive. Když uživatel otevře Control Center nebo App Switcher, iOS pořídí snímek aktuální obrazovky. Na Androidu podobně — systém zobrazí náhled posledního Activity v Recents. Použijte UIApplication.shouldSnapshotSecureApp (iOS 16+) nebo FLAG_SECURE (Android) pro ochranu důvěrných obrazovek.

Druhé pravidlo — pozastavujte animace a média. Inactive není nejvhodnější doba pro přehrávání videa nebo animací, protože je uživatel nevidí. Navíc přehrávání na pozadí může vést k překrývání zvuků se systémovými zvuky (hovor, oznámení). Zastavte AVPlayer, ExoPlayer a UIView.animate při přechodu do Inactive a obnovte při návratu do Active.

Třetí pravidlo — blokujte vstup dat. Pokud aplikace obsahuje vstupní formuláře nebo koncepty, zablokujte klávesnici a vstupní pole při přechodu do Inactive. To zabraňuje náhodnému vstupu při návratu a chrání před zachycením dat přes systémové překryvy. Na iOS vypněte first responder (view.endEditing(true)), na Androidu — vyčistěte fokus (currentFocus?.clearFocus()).

Čtvrté pravidlo — neprovádějte dlouhé operace v applicationWillResignActive nebo onPause. Tyto metody by měly být dokončeny ve zlomcích sekundy. Pokud potřebujete uložit velké množství dat, začněte ukládání na vlákně na pozadí a dokončete ho v applicationDidEnterBackground nebo onStop. iOS dává 5 sekund na provedení applicationWillResignActive, poté může systém aplikaci násilně ukončit.

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

// Použití v AppDelegate
func applicationWillResignActive(_ application: UIApplication) {
    SecureOverlayManager().showBlurOverlay()
}

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

Kód ukazuje implementaci bezpečného překryvu pro ochranu dat při přechodu do Inactive. UIVisualEffectView s efektem rozostření (blur) je umístěn přes celé UI při přechodu do Inactive a odstraněn při návratu do Active. To zaručuje, že důvěrná data nebudou viditelná na snímcích App Switcher a Control Center. Podobně lze použít UIImageView s logem pro brandovaný překryv.

Často kladené otázky

Předchází Inactive vždy Background?

Ano. Inactive je povinný přechodový stav před přechodem do Background na iOS. Aplikace nemůže přejít přímo z Active do Background — nejprve se stane Inactive, poté Background. Na Androidu podobně: onPause je vždy volán před onStop. To dává vývojáři možnost připravit data k uložení před úplným přechodem na pozadí.

Může aplikace obdržet Inactive bez přerušení?

Ano. Na iPadu při spuštění Slide Over nebo Split View se aktivní scéna stává Inactive, i když nedochází k žádnému systémovému přerušení — uživatel jednoduše interaguje s jinou scénou. To je funkce multi-window iPadOS. Na iPhonu je Inactive vždy způsoben systémovým přerušením — hovorem, oznámením, Control Center nebo Notification Center.

Jak dlouho může aplikace zůstat v Inactive?

Obvykle 0.1 až 2 sekundy. Při příchozím hovoru s obrazovkou hovoru — až 30 sekund (dokud uživatel neodpoví nebo neodmítne hovor). iOS čas v Inactive násilně neomezuje, ale systém může aplikaci ukončit, pokud nereaguje na události (watchdog). Na Androidu onPause nemá časové omezení, ale doporučuje se dokončit práci do 200 ms.

Co je scenePhase ve SwiftUI při Inactive?

ScenePhase.inactive — hodnota enum ScenePhase, nastavená když je scéna na popředí, ale nepřijímá události. Ve SwiftUI ji můžete pozorovat přes @Environment(\.scenePhase) a reagovat přes onChange. Při přechodu z .active do .inactive pozastavte časovače a animace. Při návratu do .active — obnovte. Při přechodu do .background — uložte stav.

Je třeba skrývat UI při Inactive pro všechny aplikace?

Ne, pouze pro aplikace pracující s důvěrnými daty: bankovní, lékařské, firemní, messengery s privátními chaty. Pro hry a zábavní aplikace skrývání UI není vyžadováno. Pozastavení hry a zvuku při Inactive je však dobrá praxe, aby se předešlo překrývání zvuků se systémovými oznámeními. Apple doporučuje skrývání citlivých dat, ale nevyžaduje ho.

Shrnutí

  • Inactive — přechodový stav mezi Active a Background, aplikace viditelná ale neinteraktivní
  • Příčiny — Control Center, Notification Center, příchozí hovor, systémová oprávnění, Siri, Apple Pay
  • Zpracování iOS — applicationWillResignActive pro pozastavení animací, médií a skrytí citlivých dat
  • SwiftUI — scenePhase .inactive přes Environment, onChange pro vedlejší efekty
  • Android — onPause jako analogie, s podporou multi-window a částečného zakrytí Activity
  • Bezpečnost — blur překryv nebo FLAG_SECURE pro ochranu před snímky App Switcher a Control Center
  • Dočasný charakter — Inactive trvá do konce přerušení, pak návrat do Active nebo přechod do Background

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také