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 видљивДаДа (делимично или потпуно)
Догађаји додираНе примаНе прима
ТрајањеДо завршетка прекидаДо повратка фокуса или одласка у позадину
Следеће стање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 ms.

Шта је 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. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође