Inactive — tətbiqin həyat dövründə Active və Background arasında keçid vəziyyətidir, bu zaman tətbiq ekranda görünür, lakin toxunma hadisələrini qəbul etmir. Inactive-in iOS və Android-də necə yarandığını, hansı deleqat metodlarının cavabdeh olduğunu və kəsilmələrin — zənglər, bildirişlər və sistem jestlərinin necə düzgün idarə olunacağını izah edirik.
Əsas məqamlar
Inactive — Active və Background arasında keçid zamanı yaranan mobil tətbiqin həyat dövrünün aralıq vəziyyətidir. Bu vəziyyətdə tətbiq hələ də ön plandadır və istifadəçiyə görünür, lakin toxunma hadisələrini, düymə basmalarını və digər UI hadisələrini qəbul etmir. Sistem hadisələrin tətbiqə ötürülməsini bloklayır, lakin UI ekranda qalır və yığışdırılmır.
Inactive-in təbiəti müvəqqətidir. Bu vəziyyət sistem kəsilməsi nə qədər davam edərsə, o qədər davam edir: Control Center-in sürətli bağlanması zamanı 0.1 saniyədən zəng ekranı ilə daxil olan zəng zamanı bir neçə saniyəyə qədər. Kəsilmə bitdikdən sonra tətbiq ya Active-ə qayıdır, ya da istifadəçi başqa tətbiqə keçibsə Background-a keçir. Inactive hər iki istiqamətdə keçidin mümkün olduğu yeganə vəziyyətdir: geri Active-ə və ya daha sonra Background-a.
iOS-da Inactive sistem tərəfindən avtomatik idarə olunur. Tərtibatçı Inactive-də qalma müddətini uzada və ya qısalda bilməz — bu tamamilə UIApplication tərəfindən idarə olunur. Tərtibatçının edə biləcəyi yeganə şey applicationWillResignActive vasitəsilə Inactive-ə keçidi və applicationDidBecomeActive vasitəsilə qayıdışı düzgün idarə etməkdir. Android-də analoq onPause-dur, baxmayaraq ki, semantika fərqlidir: onPause hətta Activity-nin başqa komponent tərəfindən qismən örtülməsi zamanı da çağırılır.
iOS-da Inactive tətbiqin həyat dövrünün ayrıca vəziyyətidir (beş vəziyyətdən biri: Not Running, Active, Inactive, Background, Suspended). Android-də birbaşa analoqu yoxdur — onPause Activity-nin giriş fokusunu itirdiyini bildirir, lakin görünən qala bilər (məsələn, dialoq açıldıqda). Əsas fərq: iOS Inactive bütövlükdə tətbiqin vəziyyətidir, Android onPause isə konkret Activity-nin vəziyyətidir. Android-də multi-window rejimində bir Activity onPause-də (fokus olmadan), digəri isə onResume-də (fokusla) ola bilər.
| Xüsusiyyət | iOS Inactive | Android onPause |
|---|---|---|
| UI görünür | Bəli | Bəli (qismən və ya tam) |
| Toxunma hadisələri | Qəbul etmir | Qəbul etmir |
| Müddət | Kəsilmə bitənə qədər | Fokus qayıdana və ya fon-a keçənə qədər |
| Növbəti vəziyyət | Active və ya Background | onResume və ya onStop |
| Səviyyə | Tətbiq (UIApplication) | Activity |
| Multi-window | Bir səhnə aktiv | Bir neçə Activity onPause-də |
Inactive iOS-da bir neçə ciddi müəyyən edilmiş ssenaridə yaranır. İstifadəçi Control Center-i çağırır (iPhone X+-da sağ yuxarı küncdən aşağı sürüşdürmə və ya köhnə modellərdə yuxarı sürüşdürmə). İstifadəçi Notification Center-i açır (sol yuxarı küncdən aşağı sürüşdürmə). Daxil olan zəng gəlir — sistem tətbiqin üzərində zəng ekranını göstərir. Sistem icazəsi tələb olunur — geolokasiya, mikrofon, kamera, kontaktlar. iPad-də Slide Over və ya Split View işə salınır — aktiv səhnə Inactive olur.
Android-də onPause (Inactive-in analoqu) daha geniş situasiyalarda yaranır. Dialoq pəncərəsinin açılması (AlertDialog, DialogFragment). Activity-nin başqa Activity tərəfindən qismən örtülməsi (məsələn, avtorizasiya üçün şəffaf Activity). Ekranın çevrilməsi (Activity yenidən yaradılır, ardıcıllıq: onPause → onStop → onDestroy → onCreate → onStart → onResume). Multi-window rejimi — qeyri-aktiv pəncərə onPause alır. Bu hadisələrin hər biri batareyaya qənaət və performans üçün resurs tutumlu əməliyyatların dayandırılmasını tələb edir.
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) {
// Tətbiq Inactive-ə keçir — sistem kəsilməsi
print("Kəsilmə: Control Center, zəng və ya sistem xəbərdarlığı")
// Zamana həssas əməliyyatların dayandırılması
pauseVideoPlayback()
stopContinuousDataCollection()
hideSensitiveInformation()
// Komponentlərə bildiriş
NotificationCenter.default.post(name: .systemInterruptionBegan, object: nil)
}
// Inactive-dən Active-ə qayıdış
func applicationDidBecomeActive(_ application: UIApplication) {
resumeVideoPlayback()
restartDataCollection()
NotificationCenter.default.post(name: .systemInterruptionEnded, object: nil)
}
private func pauseVideoPlayback() {
// Səsin üst-üstə düşməməsi üçün videonun dayandırılması
}
private func hideSensitiveInformation() {
// Ekran skrinşotunda həssas məlumatların gizlədilməsi
// Control Center/App Switcher UI skrinşotunu çəkir
}
}Kodda UIKit-də Inactive-in idarə edilməsi göstərilir. applicationWillResignActive videonu dayandırır, məlumat toplamanı durdurur və həssas məlumatları gizlədir. Bu vacibdir, çünki Control Center və ya App Switcher açıldıqda sistem cari UI-nin skrinşotunu çəkir — istifadəçi ön baxışda məxfi məlumatları görə bilər. NotificationCenter tətbiq komponentlərinə kəsilmə hadisələrinə abunə olmağa imkan verir.
iOS-da Inactive bir cüt metod tərəfindən idarə olunur: applicationWillResignActive (Inactive-ə giriş) və applicationDidBecomeActive (Inactive-dən qayıdış). Bu metodlar UIApplicationDelegate-in bir hissəsidir və hər Inactive-dən keçid zamanı çağırılır. iOS 13 və UISceneDelegate-dən etibarən onlara multi-window ssenariləri üçün sceneWillResignActive və sceneDidBecomeActive əlavə edilmişdir.
iOS 13+ ilə iPad-də tətbiqin bir neçə səhnəsi (pəncərəsi) ola bilər. Hər səhnənin öz həyat dövrü var. Bir səhnə Inactive ola bilər (istifadəçi başqa səhnəyə keçib), digəri isə Active qalır. Bu vacib fərqdir iPhone-dan fərqli olaraq, burada Inactive bütün tətbiq üçün qlobal vəziyyətdir. iPad üçün tətbiq hazırlayarkən Inactive hər səhnə üçün ayrıca idarə edilməlidir.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
// Səhnə qeyri-aktiv olur
func sceneWillResignActive(_ scene: UIScene) {
// iPad-də bu səhnə fokusu itirir, lakin digərləri aktiv ola bilər
print("Səhnə aktivliyini itirir")
// Bu səhnənin tapşırıqlarının dayandırılması
pauseSceneSpecificOperations()
}
// Səhnə aktiv olur
func sceneDidBecomeActive(_ scene: UIScene) {
print("Səhnə aktiv oldu")
resumeSceneSpecificOperations()
}
private func pauseSceneSpecificOperations() {
// Bu səhnə üçün spesifik əməliyyatların dayandırılması
}
private func resumeSceneSpecificOperations() {
// Fokus qayıtdıqda əməliyyatların bərpası
}
}
// AppDelegate giriş nöqtəsi olaraq qalır, səhnələrə həvalə edir
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions
) -> UISceneConfiguration {
return UISceneConfiguration(
name: "Default Configuration",
sessionRole: connectingSceneSession.role
)
}
}Kodda səhnə səviyyəsində Inactive-in idarə edilməsi üçün SceneDelegate göstərilir. sceneWillResignActive konkret pəncərə fokusu itirdikdə çağırılır — bu iPad-də pəncərələr arasında keçid zamanı baş verə bilər. AppDelegate multi-window dəstəyi üçün UISceneConfiguration konfiqurasiya edir. Hər səhnənin müstəqil vəziyyəti var və tərtibatçı onları ayrıca idarə etməlidir.
Android-də iOS Inactive-in birbaşa analoqu Activity həyat dövrünün onPause() metodudur. Activity giriş fokusunu itirdikdə çağırılır, lakin görünən qala bilər. Tipik ssenarilər: dialoq pəncərəsinin açılması, eyni tətbiqdə başqa Activity-nin işə salınması, daxil olan zəng, Home və ya Recents düyməsinin basılması. onPause-da tərtibatçı resurs tutumlu əməliyyatları — animasiyaları, video oxutmanı, kamera ilə işi dayandırmalıdır.
Android-in vacib fərqi — onPause həmişə onStop-dan əvvəl gəlir, lakin əksi doğru deyil. Activity onStop olmadan onPause ala bilər (məsələn, şəffaf Activity açıldıqda). Həmçinin onPause Activity-nin həyatı ərzində dəfələrlə çağırıla bilər — hər fokus dəyişikliyində. onPause-da birdəfəlik məntiq yerləşdirməyin — son əməliyyatlar üçün onStop-dan, yalnız interaktiv hərəkətləri dayandırmaq üçün onPause-dan istifadə edin.
class VideoPlayerActivity : AppCompatActivity() {
private var exoPlayer: ExoPlayer? = null
private var currentPosition: Long = 0L
override fun onPause() {
super.onPause()
// Tətbiq fokusu itirir — videonu dayandırırıq
exoPlayer?.let { player ->
if (player.isPlaying) {
currentPosition = player.currentPosition
player.pause()
}
}
// Həssas məlumatları gizlədirik (GDPR/bank ekranları)
if (window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_SECURE == 0
) {
hideSensitiveOverlay()
}
}
override fun onResume() {
super.onResume()
// Fokus qayıdışı — oxutmanı bərpa edirik
exoPlayer?.seekTo(currentPosition)
exoPlayer?.play()
showSensitiveOverlay()
}
private fun hideSensitiveOverlay() {
// Maliyyə məlumatlarının üzərinə qara ekran qoyuruq
}
}Kodda video pleyer üçün onPause-un düzgün idarə edilməsi göstərilir. ExoPlayer dayandırılır fokus itirildikdə və oxutma mövqeyi saxlanılır. onResume-ə qayıtdıqda pleyer saxlanılmış mövqedən oxutmanı bərpa edir. Əlavə olaraq həssas məlumatların gizlədilməsi nümunəsi göstərilir — keçid zamanı skrinşotlardan qorunma tələb edən maliyyə və tibbi tətbiqlər üçün vacibdir.
Birinci qayda — Inactive-ə keçid zamanı məxfi məlumatları gizlədin. İstifadəçi Control Center və ya App Switcher açdıqda iOS cari ekranın skrinşotunu çəkir. Android-də analoji olaraq sistem Recents-də son Activity-nin ön baxışını göstərir. Məxfi ekranları qorumaq üçün UIApplication.shouldSnapshotSecureApp (iOS 16+) və ya FLAG_SECURE (Android) istifadə edin.
İkinci qayda — animasiyaları və medianı dayandırın. Inactive video və ya animasiya oxutmaq üçün ən yaxşı vaxt deyil, çünki istifadəçi onları görmür. Üstəlik, fonda oxutma səslərin sistem səsləri ilə (zəng, bildiriş) üst-üstə düşməsinə səbəb ola bilər. Inactive-ə keçid zamanı AVPlayer, ExoPlayer və UIView.animate dayandırın və Active-ə qayıtdıqda bərpa edin.
Üçüncü qayda — məlumat daxil edilməsini bloklayın. Tətbiqdə daxiletmə formaları və ya qaralamalar varsa, Inactive-ə keçid zamanı klaviaturanı və daxiletmə sahələrini bloklayın. Bu qayıdarkən təsadüfi daxil edilmənin qarşısını alır və məlumatların sistem örtükləri vasitəsilə ələ keçirilməsindən qoruyur. iOS-da first responder-i söndürün (view.endEditing(true)), Android-də — fokusu təmizləyin (currentFocus?.clearFocus()).
Dördüncü qayda — applicationWillResignActive və ya onPause-da uzun əməliyyatlar yerinə yetirməyin. Bu metodlar saniyənin kəsrlərində tamamlanmalıdır. Böyük həcmdə məlumat saxlamaq lazımdırsa, saxlamağı fon thread-də başlayın və applicationDidEnterBackground və ya onStop-da tamamlayın. iOS applicationWillResignActive-in yerinə yetirilməsi üçün 5 saniyə verir, bundan sonra sistem tətbiqi məcburi olaraq bağlaya bilər.
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-də istifadə
func applicationWillResignActive(_ application: UIApplication) {
SecureOverlayManager().showBlurOverlay()
}
func applicationDidBecomeActive(_ application: UIApplication) {
SecureOverlayManager().removeBlurOverlay()
}Kodda Inactive-ə keçid zamanı məlumatların qorunması üçün təhlükəsiz örtük tətbiqi göstərilir. Blur effekti ilə UIVisualEffectView Inactive-ə keçid zamanı bütün UI-nin üzərinə qoyulur və Active-ə qayıtdıqda silinir. Bu, məxfi məlumatların App Switcher və Control Center skrinşotlarında görünməyəcəyinə zəmanət verir. Analoji olaraq markalı örtük üçün loqo ilə UIImageView istifadə edilə bilər.
Tez-tez verilən suallar
Bəli. Inactive iOS-da Background-a keçiddən əvvəl məcburi aralıq vəziyyətdir. Tətbiq Active-dən birbaşa Background-a keçə bilməz — əvvəlcə Inactive, sonra Background olur. Android-də analoji olaraq: onPause həmişə onStop-dan əvvəl çağırılır. Bu tərtibatçıya tama məlumatları saxlamağa hazırlamaq imkanı verir.
Bəli. iPad-də Slide Over və ya Split View işə salındıqda aktiv səhnə Inactive olur, heç bir sistem kəsilməsi olmasa da — istifadəçi sadəcə başqa səhnə ilə qarşılıqlı əlaqədədir. Bu iPadOS multi-window xüsusiyyətidir. iPhone-da Inactive həmişə sistem kəsilməsi — zəng, bildiriş, Control Center və ya Notification Center tərəfindən çağırılır.
Adətən 0.1-dən 2 saniyəyə qədər. Zəng ekranı ilə daxil olan zəng zamanı — 30 saniyəyə qədər (istifadəçi cavab verənə və ya zəngi rədd edənə qədər). iOS Inactive-də vaxtı məcburi məhdudlaşdırmır, lakin tətbiq hadisələrə cavab vermirsə (watchdog) sistem onu bağlaya bilər. Android-də onPause-un vaxt məhdudiyyəti yoxdur, lakin işin 200 ms ərzində tamamlanması tövsiyə olunur.
ScenePhase.inactive — səhnə ön planda olduqda, lakin hadisələri qəbul etmədikdə təyin olunan ScenePhase enum dəyəri. SwiftUI-də onu @Environment(\.scenePhase) vasitəsilə müşahidə edə və onChange ilə reaksiya verə bilərsiniz. .active-dən .inactive-ə keçid zamanı taymerləri və animasiyaları dayandırın. .active-ə qayıtdıqda — bərpa edin. .background-a keçid zamanı — vəziyyəti qeyd edin.
Xeyr, yalnız məxfi məlumatlarla işləyən tətbiqlər üçün: bank, tibb, korporativ, şəxsi söhbətlər olan messencerlər. Oyunlar və əyləncə tətbiqləri üçün UI gizlətmək tələb olunmur. Bununla belə, Inactive zamanı oyun prosesini və səsi dayandırmaq yaxşı təcrübədir, beləliklə səslərin sistem bildirişləri ilə üst-üstə düşməsinin qarşısı alınır. Apple həssas məlumatların gizlədilməsini tövsiyə edir, lakin tələb etmir.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun