Inactive — az alkalmazás életciklusának átmeneti állapota az Active és Background között, amelyben az alkalmazás látható a képernyőn, de nem fogad érintéseseményeket. Elmagyarázzuk, hogyan jön létre az Inactive iOS és Android rendszeren, melyik delegált metódus felelős érte, és hogyan kell helyesen kezelni a megszakításokat — hívásokat, értesítéseket és rendszermozdulatokat.
Főbb pontok
Inactive — a mobilalkalmazás életciklusának köztes állapota, amely az Active és Background közötti átmenet során fordul elő. Ebben az állapotban az alkalmazás még mindig az előtérben van és látható a felhasználó számára, de nem fogad érintéseseményeket, billentyűlenyomásokat és egyéb UI-eseményeket. A rendszer blokkolja az események alkalmazáshoz történő továbbítását, de a UI a képernyőn marad és nem minimalizálódik.
Az Inactive jellege ideiglenes. Ez az állapot pontosan addig tart, amíg a rendszermegszakítás tart: 0.1 másodperctől a Control Center gyors bezárásakor néhány másodpercig egy bejövő hívás esetén hívásképernyővel. A megszakítás befejeződése után az alkalmazás vagy visszatér Active állapotba, vagy Background állapotba kerül, ha a felhasználó egy másik alkalmazásra váltott. Az Inactive az egyetlen állapot, amelyből mindkét irányba történhet átmenet: vissza Active-ba vagy tovább Background-ba.
iOS-en az Inactive automatikusan a rendszer által van kezelve. A fejlesztő nem hosszabbíthatja meg vagy rövidítheti le az Inactive-ben töltött időt — ezt teljes mértékben a UIApplication irányítja. Az egyetlen dolog, amit a fejlesztő tehet, az Inactive-be való átmenet helyes kezelése az applicationWillResignActive és a visszatérés az applicationDidBecomeActive segítségével. Androidon az analóg az onPause, bár a szemantika eltér: az onPause akkor is meghívódik, ha az Activity részben le van takarva egy másik komponens által.
iOS-en az Inactive az alkalmazás életciklusának külön állapota (az öt közül az egyik: Not Running, Active, Inactive, Background, Suspended). Androidon nincs közvetlen analóg — az onPause jelzi, hogy az Activity elveszíti a bemeneti fókuszt, de látható maradhat (például párbeszédablak megnyitásakor). A legfontosabb különbség: az iOS Inactive az alkalmazás egészének állapota, az Android onPause egy adott Activity állapota. Androidon multi-window módban az egyik Activity lehet onPause-állapotban (fókusz nélkül), míg a másik onResume-állapotban (fókusszal).
| Jellemző | iOS Inactive | Android onPause |
|---|---|---|
| UI látható | Igen | Igen (részben vagy teljesen) |
| Érintésesemények | Nem fogad | Nem fogad |
| Időtartam | A megszakítás végéig | A fókusz visszatéréséig vagy háttérbe kerülésig |
| Következő állapot | Active vagy Background | onResume vagy onStop |
| Szint | Alkalmazás (UIApplication) | Activity |
| Multi-window | Egy jelenet aktív | Több Activity onPause-állapotban |
Inactive iOS-en néhány szigorún meghatározott forgatókönyvben fordul elő. A felhasználó meghívja a Control Center-t (lefelé húzás a jobb felső sarokból iPhone X+ esetén, vagy felfelé húzás régebbi modelleken). A felhasználó megnyitja a Notification Center-t (lefelé húzás a bal felső sarokból). Bejövő hívás érkezik — a rendszer megjeleníti a hívás képernyőjét az alkalmazás felett. Rendszerengedély kérése történik — helymeghatározás, mikrofon, kamera, névjegyzék. iPaden elindul a Slide Over vagy Split View — az aktív jelenet Inactive lesz.
Androidon az onPause (az Inactive analógja) még tágabb körű helyzetekben fordul elő. Párbeszédablak megnyitása (AlertDialog, DialogFragment). Az Activity részleges lefedése egy másik Activity által (például átlátszó Activity hitelesítéshez). Képernyő elforgatása (az Activity újra létrejön, sorrend: onPause → onStop → onDestroy → onCreate → onStart → onResume). Multi-window mód — az inaktív ablak onPause-t kap. Ezen események mindegyike az erőforrás-igényes műveletek felfüggesztését igényli az akkumulátor és a teljesítmény megőrzése érdekében.
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) {
// Az alkalmazás Inactive-be lép — rendszermegszakítás
print("Megszakítás: Control Center, hívás vagy rendszerriasztás")
// Időérzékeny műveletek felfüggesztése
pauseVideoPlayback()
stopContinuousDataCollection()
hideSensitiveInformation()
// Komponensek értesítése
NotificationCenter.default.post(name: .systemInterruptionBegan, object: nil)
}
// Visszatérés Inactive-ből Active-ba
func applicationDidBecomeActive(_ application: UIApplication) {
resumeVideoPlayback()
restartDataCollection()
NotificationCenter.default.post(name: .systemInterruptionEnded, object: nil)
}
private func pauseVideoPlayback() {
// Videó leállítása a hang átfedésének elkerüléséhez
}
private func hideSensitiveInformation() {
// Érzékeny adatok elrejtése képernyőképnél
// Control Center/App Switcher képernyőképet készít a UI-ról
}
}A kód az Inactive kezelését mutatja UIKit-ben. Az applicationWillResignActive leállítja a videót, leállítja az adatgyűjtést és elrejti az érzékeny információkat. Ez azért fontos, mert a Control Center vagy App Switcher megnyitásakor a rendszer képernyőképet készít a jelenlegi UI-ról — a felhasználó bizalmas adatokat láthat az előnézetben. A NotificationCenter lehetővé teszi az alkalmazás komponensei számára, hogy feliratkozzanak a megszakítási eseményekre.
iOS-en az Inactive kezelése egy metóduspárral történik: applicationWillResignActive (átmenet Inactive-be) és applicationDidBecomeActive (visszatérés Inactive-ből). Ezek a metódusok a UIApplicationDelegate részét képezik, és minden Inactive-en keresztüli átmenetnél meghívódnak. Az iOS 13 és a UISceneDelegate óta a sceneWillResignActive és a sceneDidBecomeActive is hozzáadódott a multi-window forgatókönyvek számára.
Az iOS 13+-os iPaden az alkalmazásnak több jelenete (ablaka) lehet. Minden jelenetnek saját életciklusa van. Az egyik jelenet Inactive lehet (a felhasználó egy másik jelenetre váltott), míg a másik Active marad. Ez egy fontos különbség az iPhone-hoz képest, ahol az Inactive globális állapot az egész alkalmazás számára. iPadre történő fejlesztésnél az Inactive-et minden jelenetnél külön kell kezelni.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
// A jelenet inaktívvá válik
func sceneWillResignActive(_ scene: UIScene) {
// iPaden ez a jelenet elveszíti a fókuszt, de mások aktívak maradhatnak
print("A jelenet elveszíti az aktivitást")
// A jelenet feladatainak felfüggesztése
pauseSceneSpecificOperations()
}
// A jelenet aktívvá válik
func sceneDidBecomeActive(_ scene: UIScene) {
print("A jelenet aktívvá vált")
resumeSceneSpecificOperations()
}
private func pauseSceneSpecificOperations() {
// A jelenetre jellemző műveletek felfüggesztése
}
private func resumeSceneSpecificOperations() {
// Műveletek folytatása a fókusz visszatérésekor
}
}
// Az AppDelegate belépési pont marad, átadja a jeleneteknek
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions
) -> UISceneConfiguration {
return UISceneConfiguration(
name: "Default Configuration",
sessionRole: connectingSceneSession.role
)
}
}A kód a SceneDelegate-et mutatja az Inactive jelenet szintű kezeléséhez. A sceneWillResignActive akkor hívódik meg, amikor egy adott ablak elveszíti a fókuszt — ez iPaden az ablakok váltásakor fordulhat elő. Az AppDelegate konfigurálja a UISceneConfiguration-t a multi-window támogatásához. Minden jelenetnek független állapota van, és a fejlesztőnek külön kell kezelnie azokat.
Androidon az iOS Inactive közvetlen analógja az Activity életciklusának onPause() metódusa. Akkor hívódik meg, amikor az Activity elveszíti a bemeneti fókuszt, de látható maradhat. Tipikus forgatókönyvek: párbeszédablak megnyitása, másik Activity elindítása ugyanabban az alkalmazásban, bejövő hívás, Home vagy Recents gomb megnyomása. Az onPause-ban a fejlesztőnek fel kell függesztenie az erőforrás-igényes műveleteket — animációkat, videólejátszást, a kamerával való munkát.
Egy fontos különbség Androidon — az onPause mindig megelőzi az onStop-ot, de ez fordítva nem igaz. Az Activity onPause-t kaphat onStop nélkül (például átlátszó Activity megnyitásakor). Emellett az onPause többször is meghívódhat az Activity élete során — minden fókuszváltásnál. Ne helyezzen egyszeri logikát az onPause-ba — végleges műveletekhez használja az onStop-ot, és csak az interaktív tevékenységek felfüggesztéséhez használja az onPause-t.
class VideoPlayerActivity : AppCompatActivity() {
private var exoPlayer: ExoPlayer? = null
private var currentPosition: Long = 0L
override fun onPause() {
super.onPause()
// Az alkalmazás elveszíti a fókuszt — videó felfüggesztése
exoPlayer?.let { player ->
if (player.isPlaying) {
currentPosition = player.currentPosition
player.pause()
}
}
// Érzékeny adatok elrejtése (GDPR/banki képernyők)
if (window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_SECURE == 0
) {
hideSensitiveOverlay()
}
}
override fun onResume() {
super.onResume()
// Fókusz visszatérése — lejátszás folytatása
exoPlayer?.seekTo(currentPosition)
exoPlayer?.play()
showSensitiveOverlay()
}
private fun hideSensitiveOverlay() {
// Fekete képernyő elhelyezése a pénzügyi adatok fölé
}
}A kód az onPause helyes kezelését mutatja egy videólejátszó számára. Az ExoPlayer felfüggesztődik a fókusz elvesztésekor, és a lejátszási pozíció mentésre kerül. Az onResume-ba való visszatéréskor a lejátszó a mentett pozíciótól folytatja a lejátszást. Emellett látható az érzékeny adatok elrejtésének mintája — fontos a pénzügyi és orvosi alkalmazások számára, amelyek védelmet igényelnek a váltáskor készülő képernyőképek ellen.
Első szabály — rejtse el a bizalmas adatokat az Inactive-be való átmenetkor. Amikor a felhasználó megnyitja a Control Center-t vagy App Switcher-t, az iOS képernyőképet készít az aktuális képernyőről. Androidon hasonlóan — a rendszer megjeleníti az utolsó Activity előnézetét a Recents-ben. Használja a UIApplication.shouldSnapshotSecureApp (iOS 16+) vagy FLAG_SECURE (Android) opciót a bizalmas képernyők védelméhez.
Második szabály — függessze fel az animációkat és a médiát. Az Inactive nem a legjobb idő a videók vagy animációk lejátszására, mivel a felhasználó nem látja azokat. Továbbá a háttérben történő lejátszás a hangok átfedését okozhatja a rendszerhangokkal (hívás, értesítés). Állítsa le az AVPlayer-t, ExoPlayer-t és UIView.animate-t az Inactive-be való átmenetkor és folytassa az Active-ba való visszatéréskor.
Harmadik szabály — blokkolja az adatbevitelt. Ha az alkalmazás bevítelő űrlapokat vagy piszkozatokat tartalmaz, blokkolja a billentyűzetet és a bevítelő mezőket az Inactive-be való átmenetkor. Ez megakadályozza a véletlenszerű adatbevitelt visszatéréskor és védelmet nyújt az adatok rendszer-átfedéseken keresztüli elfogása ellen. iOS-en kapcsolja ki a first responder-t (view.endEditing(true)), Androidon — törölje a fókuszt (currentFocus?.clearFocus()).
Negyedik szabály — ne végezzen hosszú műveleteket az applicationWillResignActive vagy onPause függvényben. Ezeknek a metódusoknak a másodperc töredéke alatt be kell fejeződniük. Ha nagy mennyiségű adatot kell menteni, kezdje el a mentést egy háttérszálon, és fejezze be az applicationDidEnterBackground vagy onStop függvényben. Az iOS 5 másodpercet ad az applicationWillResignActive végrehajtására, ezután a rendszer kényszerítve megszüntetheti az alkalmazást.
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
}
}
// Használat az AppDelegate-ben
func applicationWillResignActive(_ application: UIApplication) {
SecureOverlayManager().showBlurOverlay()
}
func applicationDidBecomeActive(_ application: UIApplication) {
SecureOverlayManager().removeBlurOverlay()
}A kód egy biztonságos átfedés implementálását mutatja az adatok védelméhez az Inactive-be való átmenetkor. Egy UIVisualEffectView blur effektussal kerül a teljes UI fölé az Inactive-be való átmenetkor és eltávolításra kerül az Active-ba való visszatéréskor. Ez garantálja, hogy a bizalmas adatok nem lesznek láthatók az App Switcher és Control Center képernyőképein. Hasonlóan használható egy UIImageView logóval márkázott átfedéshez.
Gyakran ismételt kérdések
Igen. Az Inactive egy kötelező köztes állapot a Background-ba való átmenet előtt iOS-en. Az alkalmazás nem léphet közvetlenül Active-ból Background-ba — először Inactive lesz, majd Background. Androidon hasonlóan: az onPause mindig az onStop előtt hívódik meg. Ez lehetőséget ad a fejlesztőnek, hogy előkészítse az adatokat a mentésre, mielőtt az alkalmazás teljesen háttérbe kerül.
Igen. iPaden a Slide Over vagy Split View indításakor az aktív jelenet Inactive lesz, annak ellenére, hogy nem történik rendszermegszakítás — a felhasználó egyszerűen egy másik jelenettel lép kapcsolatba. Ez az iPadOS multi-window funkciója. iPhone-on az Inactive-t mindig rendszermegszakítás — hívás, értesítés, Control Center vagy Notification Center — váltja ki.
Általában 0.1 és 2 másodperc között. Bejövő hívás esetén hívásképernyővel — akár 30 másodpercig (amíg a felhasználó fel nem veszi vagy el nem utasítja a hívást). Az iOS nem korlátozza kényszerítve az Inactive-ben töltött időt, de a rendszer megszüntetheti az alkalmazást, ha az nem reagál az eseményekre (watchdog). Androidon az onPause-nak nincs időkorlátja, de ajánlott a munka 200 ms-on belüli befejezése.
ScenePhase.inactive — a ScenePhase enum értéke, amely akkor van beállítva, amikor a jelenet az előtérben van, de nem fogad eseményeket. A SwiftUI-ban megfigyelheti a @Environment(\.scenePhase) segítségével és reagálhat az onChange segítségével. A .active-ból .inactive-be való átmenetkor függessze fel az időzítőket és animációkat. A .active-ba való visszatéréskor — folytassa. A .background-ba való átmenetkor — mentse az állapotot.
Nem, csak a bizalmas adatokkal dolgozó alkalmazásoknál: banki, orvosi, vállalati, privát chatekkel rendelkező üzenetküldők. Játékok és szórakoztató alkalmazások számára a UI elrejtése nem kötelező. Azonban a játék és hang felfüggesztése Inactive esetén jó gyakorlat, hogy elkerülje a hangok átfedését a rendszerértesítésekkel. Az Apple ajánlja az érzékeny adatok elrejtését, de nem követeli meg.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is