Inactive — un état transitoire dans le cycle de vie de l'application entre Active et Background, dans lequel l'app est visible à l'écran mais ne reçoit pas les événements tactiles. Nous expliquons comment l'Inactive se produit sur iOS et Android, quelles méthodes du délégué en sont responsables et comment traiter correctement les interruptions — appels, notifications et gestes système.
Points clés
Inactive est un état intermédiaire dans le cycle de vie de l'application mobile qui se produit lors de la transition entre Active et Background. Dans cet état, l'app est toujours au premier plan et visible pour l'utilisateur, mais ne reçoit pas les événements tactiles, les pressions de touches ou les autres événements de l'interface. Le système bloque la distribution des événements à l'app, mais l'interface reste à l'écran et n'est pas minimisée.
La nature de l'Inactive est temporaire. Cet état dure exactement le temps de l'interruption système : de 0,1 seconde lors de la fermeture rapide du Control Center à plusieurs secondes lors d'un appel entrant avec écran d'appel. Après la fin de l'interruption, l'app retourne en Active ou passe en Background si l'utilisateur est passé à une autre app. Inactive est le seul état qui peut transiter dans les deux directions : retour en Active ou poursuite vers Background.
Sur iOS, Inactive est géré automatiquement par le système. Le développeur ne peut ni prolonger ni raccourcir le temps passé en Inactive — il est entièrement contrôlé par UIApplication. La seule chose que le développeur peut faire est de gérer correctement le passage en Inactive via applicationWillResignActive et le retour via applicationDidBecomeActive. Sur Android, l'équivalent est onPause, bien que la sémantique diffère : onPause est appelé même lorsqu'une Activity est partiellement couverte par un autre composant.
Sur iOS, Inactive est un état séparé du cycle de vie de l'application (un des cinq : Not Running, Active, Inactive, Background, Suspended). Sur Android, il n'y a pas d'équivalent direct — onPause signale que l'Activity perd le focus d'entrée mais peut rester visible (par exemple, lors de l'ouverture d'un dialogue). La différence clé : Inactive sur iOS est un état au niveau de l'application entière, tandis que onPause sur Android est un état par Activity. En multi-fenêtre Android, une Activity peut être en onPause (sans focus) tandis qu'une autre est en onResume (avec focus).
| Caractéristique | iOS Inactive | Android onPause |
|---|---|---|
| UI visible | Oui | Oui (partiellement ou totalement) |
| Événements tactiles | Ne reçoit pas | Ne reçoit pas |
| Durée | Jusqu'à la fin de l'interruption | Jusqu'au retour du focus ou passage en arrière-plan |
| État suivant | Active ou Background | onResume ou onStop |
| Niveau | Application (UIApplication) | Activity |
| Multi-fenêtre | Une scène active | Plusieurs Activity en onPause |
Inactive sur iOS se produit dans plusieurs scénarios strictement définis. L'utilisateur ouvre le Control Center (balayage vers le bas depuis le coin supérieur droit sur iPhone X+ ou balayage vers le haut sur les anciens modèles). L'utilisateur ouvre le Notification Center (balayage vers le bas depuis le coin supérieur gauche). Un appel entrant arrive — le système affiche l'écran d'appel par-dessus l'app. Une permission système est demandée — géolocalisation, microphone, caméra, contacts. Sur iPad, Slide Over ou Split View est lancé — la scène active devient Inactive.
Sur Android, onPause (l'équivalent d'Inactive) se produit dans un éventail encore plus large de situations. Ouverture d'un dialogue (AlertDialog, DialogFragment). Chevauchement partiel d'une Activity par une autre Activity (par exemple, une Activity transparente pour l'authentification). Rotation de l'écran (l'Activity est recréée, séquence : onPause → onStop → onDestroy → onCreate → onStart → onResume). Mode multi-fenêtre — la fenêtre inactive reçoit onPause. Chacun de ces événements nécessite la suspension des opérations gourmandes en ressources pour préserver la batterie et les performances.
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) {
// L'application passe en Inactive — interruption système
print("Interruption : Control Center, appel ou alerte système")
// Suspension des opérations sensibles au temps
pauseVideoPlayback()
stopContinuousDataCollection()
hideSensitiveInformation()
// Notification des composants
NotificationCenter.default.post(name: .systemInterruptionBegan, object: nil)
}
// Retour d'Inactive à Active
func applicationDidBecomeActive(_ application: UIApplication) {
resumeVideoPlayback()
restartDataCollection()
NotificationCenter.default.post(name: .systemInterruptionEnded, object: nil)
}
private func pauseVideoPlayback() {
// Mise en pause de la vidéo pour éviter la superposition audio
}
private func hideSensitiveInformation() {
// Masquage des données sensibles lors de la capture d'écran
// Control Center/App Switcher prennent une capture de l'interface
}
}Le code montre la gestion d'Inactive dans UIKit. applicationWillResignActive met en pause la vidéo, arrête la collecte de données et masque les informations sensibles. Ceci est important car lorsque le Control Center ou l'App Switcher est ouvert, le système prend une capture d'écran de l'interface actuelle — l'utilisateur pourrait voir des données confidentielles dans l'aperçu. NotificationCenter permet aux composants de l'app de s'abonner aux événements d'interruption.
Sur iOS, Inactive est géré par une paire de méthodes : applicationWillResignActive (passage en Inactive) et applicationDidBecomeActive (retour d'Inactive). Ces méthodes font partie de UIApplicationDelegate et sont appelées pour chaque transition via Inactive. Depuis iOS 13 et UISceneDelegate, sceneWillResignActive et sceneDidBecomeActive ont été ajoutées pour les scénarios multi-fenêtre.
Sur iPad avec iOS 13+, une app peut avoir plusieurs scènes (fenêtres). Chaque scène a son propre cycle de vie. Une scène peut devenir Inactive (l'utilisateur est passé à une autre scène) tandis qu'une autre reste Active. Ceci est une différence importante par rapport à l'iPhone, où Inactive est un état global pour toute l'app. Lors du développement pour iPad, vous devez gérer Inactive pour chaque scène séparément.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
// La scène devient inactive
func sceneWillResignActive(_ scene: UIScene) {
// Sur iPad, cette scène perd le focus, mais d'autres peuvent être actives
print("La scène perd l'activité")
// Suspension des tâches de cette scène
pauseSceneSpecificOperations()
}
// La scène devient active
func sceneDidBecomeActive(_ scene: UIScene) {
print("La scène est devenue active")
resumeSceneSpecificOperations()
}
private func pauseSceneSpecificOperations() {
// Suspension des opérations spécifiques à cette scène
}
private func resumeSceneSpecificOperations() {
// Reprise des opérations au retour du focus
}
}
// AppDelegate reste le point d'entrée, délègue aux scènes
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions
) -> UISceneConfiguration {
return UISceneConfiguration(
name: "Default Configuration",
sessionRole: connectingSceneSession.role
)
}
}Le code montre un SceneDelegate pour gérer Inactive au niveau de la scène. sceneWillResignActive est appelé lorsqu'une fenêtre spécifique perd le focus — cela peut se produire lors du changement de fenêtre sur iPad. AppDelegate configure UISceneConfiguration pour prendre en charge le multi-fenêtre. Chaque scène a un état indépendant et le développeur doit les gérer séparément.
Sur Android, l'équivalent direct d'Inactive sur iOS est la méthode onPause() du cycle de vie de l'Activity. Elle est appelée lorsque l'Activity perd le focus d'entrée mais peut rester visible. Scénarios typiques : ouverture d'un dialogue, lancement d'une autre Activity dans la même app, appel entrant, pression du bouton Home ou Recents. Dans onPause, le développeur doit suspendre les opérations gourmandes en ressources — animations, lecture vidéo, travail avec la caméra.
Une différence importante d'Android est que onPause précède toujours onStop, mais pas l'inverse. Une Activity peut recevoir onPause sans onStop (par exemple, lors de l'ouverture d'une Activity transparente). De plus, onPause peut être appelé plusieurs fois durant la vie d'une Activity — à chaque changement de focus. Ne placez pas de logique unique dans onPause — utilisez onStop pour les opérations finales et onPause uniquement pour suspendre les actions interactives.
class VideoPlayerActivity : AppCompatActivity() {
private var exoPlayer: ExoPlayer? = null
private var currentPosition: Long = 0L
override fun onPause() {
super.onPause()
// L'application perd le focus — mise en pause de la vidéo
exoPlayer?.let { player ->
if (player.isPlaying) {
currentPosition = player.currentPosition
player.pause()
}
}
// Masquage des données sensibles (RGPD/écrans bancaires)
if (window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_SECURE == 0
) {
hideSensitiveOverlay()
}
}
override fun onResume() {
super.onResume()
// Retour du focus — reprise de la lecture
exoPlayer?.seekTo(currentPosition)
exoPlayer?.play()
showSensitiveOverlay()
}
private fun hideSensitiveOverlay() {
// Superposition d'un écran noir sur les données financières
}
}Le code montre la gestion correcte d'onPause pour un lecteur vidéo. ExoPlayer est mis en pause lorsque le focus est perdu, et la position de lecture est sauvegardée. Au retour dans onResume, le lecteur reprend la lecture à partir de la position sauvegardée. De plus, un modèle de masquage des données sensibles est présenté — important pour les applications financières et médicales qui nécessitent une protection contre les captures d'écran lors du changement d'app.
Première règle — masquez les données confidentielles lors du passage en Inactive. Lorsque l'utilisateur ouvre le Control Center ou l'App Switcher, iOS prend une capture d'écran de l'écran actuel. Sur Android, de même, le système montre un aperçu de la dernière Activity dans Recents. Utilisez UIApplication.shouldSnapshotSecureApp (iOS 16+) ou FLAG_SECURE (Android) pour protéger les écrans confidentiels.
Deuxième règle — mettez en pause les animations et les médias. Inactive n'est pas un bon moment pour lire une vidéo ou des animations, car l'utilisateur ne peut pas les voir. De plus, la lecture en arrière-plan peut superposer l'audio avec les sons système (sonnerie, notification). Arrêtez AVPlayer, ExoPlayer et UIView.animate lors du passage en Inactive et reprenez-les lors du retour en Active.
Troisième règle — bloquez la saisie de données. Si l'app contient des formulaires de saisie ou des brouillons, verrouillez le clavier et les champs de saisie lors du passage en Inactive. Cela évite les saisies accidentelles au retour et protège contre l'interception de données via les superpositions système. Sur iOS, démissionnez le premier répondeur (view.endEditing(true)), sur Android — effacez le focus (currentFocus?.clearFocus()).
Quatrième règle — n'effectuez pas d'opérations longues dans applicationWillResignActive ou onPause. Ces méthodes doivent se terminer en fractions de seconde. Si vous devez sauvegarder une grande quantité de données, commencez la sauvegarde dans un thread d'arrière-plan et terminez-la dans applicationDidEnterBackground ou onStop. iOS donne 5 secondes pour exécuter applicationWillResignActive, après quoi le système peut forcer la fermeture de l'app.
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
}
}
// Utilisation dans AppDelegate
func applicationWillResignActive(_ application: UIApplication) {
SecureOverlayManager().showBlurOverlay()
}
func applicationDidBecomeActive(_ application: UIApplication) {
SecureOverlayManager().removeBlurOverlay()
}Le code montre l'implémentation d'une superposition sécurisée pour la protection des données lors du passage en Inactive. Un UIVisualEffectView avec effet de flou est superposé sur toute l'interface lors du passage en Inactive et retiré lors du retour en Active. Cela garantit que les données confidentielles ne seront pas visibles dans les captures d'écran de l'App Switcher et du Control Center. De même, vous pouvez utiliser UIImageView avec un logo pour une superposition personnalisée.
Questions fréquentes
Oui. Inactive est un état intermédiaire obligatoire avant le passage en Background sur iOS. Une app ne peut pas passer directement d'Active à Background — elle devient d'abord Inactive, puis Background. Sur Android, de même, onPause est toujours appelé avant onStop. Cela donne au développeur la possibilité de préparer les données à sauvegarder avant de passer complètement en arrière-plan.
Oui. Sur iPad, lors du lancement de Slide Over ou Split View, la scène active devient Inactive, même si aucune interruption système ne se produit — l'utilisateur interagit simplement avec une autre scène. C'est une fonctionnalité d'iPadOS multi-fenêtre. Sur iPhone, Inactive est toujours déclenché par une interruption système — appel, notification, Control Center ou Notification Center.
Généralement de 0,1 à 2 secondes. Lors d'un appel entrant avec écran d'appel — jusqu'à 30 secondes (jusqu'à ce que l'utilisateur réponde ou refuse l'appel). iOS ne limite pas forcément le temps en Inactive, mais le système peut fermer l'app si elle ne répond pas aux événements (watchdog). Sur Android, onPause n'a pas de limite de temps, mais il est recommandé de terminer le travail en 200 ms.
ScenePhase.inactive — la valeur de l'énumération ScenePhase définie lorsque la scène est au premier plan mais ne reçoit pas d'événements. Dans SwiftUI, vous pouvez l'observer via @Environment(\.scenePhase) et réagir via onChange. Lors du passage de .active à .inactive, mettez en pause les temporisateurs et les animations. Au retour en .active, reprenez-les. Lors du passage en .background, sauvegardez l'état.
Non, uniquement pour les apps qui traitent des données confidentielles : bancaires, médicales, d'entreprise et de messagerie avec des conversations privées. Pour les jeux et les apps de divertissement, le masquage de l'interface n'est pas nécessaire. Cependant, mettre en pause le jeu et le son pendant Inactive est une bonne pratique pour éviter la superposition de l'audio avec les notifications système. Apple recommande de masquer les données sensibles mais ne l'exige pas.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi