ActivityResultLauncher : ce que c’est et comment l’utiliser

Auteur : IT Sectr Publié le : 2026-06-10 Temps de lecture : 9 min

ActivityResultLauncher est un composant de l’API Activity Result d’Android, présenté dans la version Activity 1.2.0 de la bibliothèque androidx.activity. Il remplace les méthodes obsolètes startActivityForResult et onActivityResult, qui faisaient partie du SDK Android depuis sa création. Selon Android Developers (2024), la nouvelle API élimine les problèmes de couplage fort avec Activity et l’absence de sécurité de type. ActivityResultLauncher est enregistré à l’avance et utilise un Contract pour un typage strict des données d’entrée et de sortie.

Points clés

  • ActivityResultLauncher — une nouvelle API pour obtenir des résultats d’une Activity au lieu de l’obsolète startActivityForResult
  • Contract — un objet qui définit le type des données d’entrée et de sortie pour un scénario spécifique
  • Enregistrement effectué via registerForActivityResult avant d’appeler launch
  • Callback invoqué après la fin de l’Activity cible avec un résultat
  • API disponible pour Activity, Fragment et Compose à partir d’Activity 1.2.0

Qu’est-ce qu’ActivityResultLauncher

ActivityResultLauncher est une classe du paquet androidx.activity.result qui fournit un mécanisme type-safe pour lancer une Activity et recevoir un résultat. Le launcher est créé via la méthode registerForActivityResult, qui accepte deux paramètres : Contract (décrit les types d’entrée et de sortie) et ActivityResultCallback (gestionnaire de résultat). Après l’enregistrement, le launcher est prêt à être appelé via la méthode launch.

La différence clé avec l’ancienne API est la séparation de l’enregistrement et du lancement. L’enregistrement est effectué lors de l’initialisation (Activity.onCreate ou Fragment.onCreate), le callback est lié au launcher une fois et est garanti de se déclencher lorsque le résultat revient. Cela élimine le problème où onActivityResult se déclenchait dans un ordre inattendu ou sur une Activity détruite.

ActivityResultLauncher prend en charge tous les scénarios qui étaient auparavant traités via onActivityResult : lancer l’appareil photo, la galerie, demander des contacts, des permissions et des Activities personnalisées. De plus, l’API est extensible : les développeurs peuvent créer des Contracts personnalisés pour des scénarios spécifiques d’échange de données entre Activities.

Pourquoi Activity Result API a remplacé startActivityForResult

startActivityForResult faisait partie du SDK Android depuis API Level 1 (2008) et est resté le principal moyen d’obtenir un résultat d’une Activity pendant plus de 12 ans. Cependant, cette méthode présentait des défauts fondamentaux que Google a corrigés dans Activity Result API. Examinons les principaux problèmes et comment la nouvelle API les résout.

Problème 1 : Couplage fort avec Activity

La méthode startActivityForResult est liée à Activity et Fragment via requestCode — un entier arbitraire passé à onActivityResult. Le développeur faisait correspondre manuellement le code à l’opération lancée, ce qui entraînait des erreurs lors de la réutilisation du code et de l’héritage. ActivityResultLauncher élimine complètement requestCode : le callback est lié à un launcher spécifique lors de l’enregistrement et n’est invoqué que pour celui-ci.

Problème 2 : Perte du résultat lors de la rotation de l’écran

Lors des changements de configuration (rotation de l’écran, changement de langue), l’Activity était recréée et onActivityResult pouvait ne pas se déclencher — le callback était perdu. Activity Result API sauvegarde et restaure automatiquement l’état du launcher via SavedStateRegistry, garantissant la réception du résultat même après la recréation de l’Activity.

Problème 3 : Absence de sécurité de type

L’ancienne API transmettait le résultat via Intent avec un Bundle, où les clés et les types de données n’étaient pas vérifiés par le compilateur. Activity Result API utilise Contract — une interface générique qui définit le type de données d’entrée (I) et le type de résultat (O). Les erreurs d’incompatibilité de type sont détectées à la compilation, pas à l’exécution.

CaractéristiquestartActivityForResultActivityResultLauncher
RequestCodeGestion manuelle requiseAutomatique, non requis
Sécurité de typeNonContract générique
Sauvegarde lors de rotationPerdueSavedStateRegistry
API minimaleAPI Level 1Activity 1.2.0
Utilisation dans ComposeNon supportérememberLauncherForActivityResult

Principaux contrats d’Activity Result API

Contract est l’interface ActivityResultContract<I, O>, qui définit comment lancer une Activity et comment interpréter le résultat. Google fournit un ensemble de contrats intégrés pour les scénarios typiques couvrant la plupart des besoins des développeurs.

StartIntentSenderForResult

StartIntentSenderForResult — un contrat de base pour lancer IntentSender. Utilisé dans des scénarios système, par exemple lors de l’autorisation via Google Sign-In ou des paiements via Google Pay. Le paramètre d’entrée est PendingIntent, la sortie est ActivityResult avec le code et Intent.

RequestMultiplePermissions

RequestMultiplePermissions — un contrat pour demander plusieurs permissions simultanément sur Android 6.0+. Le paramètre d’entrée est un tableau de String avec les noms des permissions, la sortie est Map<String, Boolean> avec le résultat de chaque demande. Auparavant, cela nécessitait une analyse manuelle dans onRequestPermissionsResult avec correspondance des codes de demande.

TakePicture et TakeVideo

TakePicture — un contrat pour prendre une photo via l’appareil photo système. L’entrée est un Uri où sauvegarder l’image, la sortie est Boolean (succès). TakeVideo fonctionne de manière similaire avec la vidéo. Ces contrats remplacent l’obsolète MediaStore.ACTION_IMAGE_CAPTURE au comportement instable sur différents appareils.

GetContent et OpenDocument

GetContent — un contrat pour sélectionner du contenu via le sélecteur système. L’entrée est un type MIME (par exemple image/*), la sortie est un Uri du fichier sélectionné. OpenDocument diffère en supportant la sélection multiple et le filtrage par type de document. Les deux contrats fonctionnent via SAF (Storage Access Framework).

CreateDocument et OpenDocumentTree

CreateDocument — un contrat pour créer un nouveau document via la boîte de dialogue système. L’utilisateur choisit un nom et un dossier, le système retourne un Uri pour l’écriture. OpenDocumentTree fournit un accès à un répertoire entier — l’utilisateur sélectionne un dossier et l’application reçoit un tree-uri pour lire et écrire tous les fichiers à l’intérieur.

Utilisation dans Activity et Fragment

Le modèle de base pour utiliser ActivityResultLauncher dans Android classique comprend deux étapes : l’enregistrement via registerForActivityResult lors de l’initialisation et l’appel de launch en réponse à une action de l’utilisateur. Examinons un exemple typique de sélection d’une image depuis la galerie.

Enregistrement et lancement dans Activity

Enregistrez le launcher dans le onCreate de l’Activity — cela garantit que le callback est prêt avant tout appel potentiel. N’enregistrez jamais un launcher juste avant de le lancer — cela viole le contrat de l’API et peut entraîner une perte du résultat lors de la recréation de l’Activity.

kotlin
class MainActivity : AppCompatActivity() {
    private val pickImageLauncher =
        registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
            uri?.let { binding.imageView.setImageURI(it) }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        pickImageLauncher.launch("image/*")
    }
}

Utilisation dans Fragment

Dans un Fragment, l’enregistrement est effectué dans onCreate, onAttach ou lors de l’initialisation dans onCreateView. FragmentActivity transmet le launcher via l’Activity parente, donc le résultat est traité à l’intérieur du Fragment, pas dans l’Activity. Cela améliore l’encapsulation par rapport à onActivityResult, où tous les résultats de tous les Fragments étaient rassemblés dans une seule méthode d’Activity.

kotlin
class ProfileFragment : Fragment() {
    private val cameraLauncher =
        registerForActivityResult(ActivityResultContracts.TakePicture()) { success ->
            if (success) { updateProfilePhoto() }
        }

    fun takePhoto(photoUri: Uri) {
        cameraLauncher.launch(photoUri)
    }
}

ActivityResultLauncher dans Jetpack Compose

Jetpack Compose fournit une fonction composable spéciale pour Activity Result API — rememberLauncherForActivityResult. Contrairement à l’approche classique, dans Compose le launcher est créé comme un objet lié au cycle de vie du composable via remember. Cela permet d’utiliser Activity Result API entièrement dans un style déclaratif sans accès direct à Activity ou Fragment.

rememberLauncherForActivityResult

rememberLauncherForActivityResult prend un Contract et un callback, retournant un ActivityResultLauncher. Le launcher est préservé lors de la recomposition et automatiquement nettoyé en quittant la composition. L’appel de launch se produit en réponse à un événement — par exemple, un clic sur un bouton ou un changement d’état.

kotlin
@Composable
fun PhotoPicker() {
    val context = LocalContext.current
    val launcher = rememberLauncherForActivityResult(
        ActivityResultContracts.GetContent()
    ) { uri -> handleImage(uri) }

    Button(onClick = { launcher.launch("image/*") }) {
        Text("Choisir une photo")
    }
}

Gestion des permissions dans Compose

Les demandes de permissions dans Compose sont également effectuées via rememberLauncherForActivityResult avec le contrat RequestPermission ou RequestMultiplePermissions. Google recommande d’utiliser accompanist-permissions, mais en interne il utilise aussi Activity Result API. Pour suivre l’état des permissions, il est pratique de stocker l’état dans remember ou ViewModel.

Erreurs courantes et bonnes pratiques

Activity Result API a éliminé de nombreux problèmes de l’ancienne approche, mais une utilisation incorrecte peut entraîner de nouveaux types d’erreurs. Examinons les problèmes les plus courants et comment les éviter.

Erreur : enregistrement dans une lambda ou une coroutine

L’enregistrement du launcher doit être effectué lors de l’initialisation du composant — dans le onCreate de l’Activity ou l’initialiseur du Fragment. Si vous enregistrez le launcher dans une lambda, un callback ou une coroutine, lors de la recréation de l’Activity l’enregistrement peut être effectué à nouveau et l’ancien launcher perdra la connexion avec le résultat.

Erreur : enregistrement de plusieurs launchers avec la même clé

Chaque launcher reçoit une clé unique pour la sauvegarde d’état. Si vous enregistrez deux launchers avec le même Contract dans un composant, SavedStateRegistry peut écraser l’état de l’un par celui de l’autre. Android Studio avertit de cela via la règle lint UnnecessaryRegisterForActivityResult, mais il est préférable de contrôler l’unicité manuellement.

Bonne pratique : toujours traiter le résultat nul

L’utilisateur peut annuler l’action — appuyer sur le bouton retour système, minimiser l’application ou passer à une autre application. Dans ce cas, le callback recevra null ou ActivityResult avec RESULT_CANCELED. Vérifiez toujours si le résultat est null avant de l’utiliser pour éviter NullPointerException.

Bonne pratique : Contracts personnalisés pour la logique réutilisable

Si votre application lance fréquemment des scénarios similaires — par exemple, sélectionner un contact et retourner un nom et un téléphone — créez un Contract personnalisé. Cela améliore la lisibilité du code et permet des modifications centralisées de la logique de lancement et de traitement des résultats.

kotlin
class PickContactContract : ActivityResultContract<Void, ContactData?>() {
    override fun createIntent(context: Context, input: Void?) =
        Intent(Intent.ACTION_PICK).setType(ContactsContract.Contacts.CONTENT_TYPE)

    override fun parseResult(resultCode: Int, intent: Intent?) =
        intent?.data?.let { queryContact(it) }
}

Questions fréquentes

Peut-on utiliser ActivityResultLauncher dans ViewModel ?

Non — ActivityResultLauncher nécessite un contexte Activity ou Fragment pour l’enregistrement. Utilisez ViewModel uniquement pour stocker l’état, et créez le launcher dans Activity ou Fragment et passez le résultat au ViewModel.

Quel SDK minimum est requis pour Activity Result API ?

Activity Result API est disponible à partir de la bibliothèque activity-ktx 1.2.0. Le SDK minimum est API Level 14 (Android 4.0), mais la plupart des contrats fonctionnent uniquement sur API Level 19+.

Que se passe-t-il si launch est appelé deux fois avant la réception d’un résultat ?

Un appel répété de launch avant la fin de la première opération sera ignoré. Activity Result API ne prend pas en charge les lancements parallèles — attendez le callback de la première opération avant un nouvel appel.

Comment remplacer onActivityResult dans l’ancien code ?

La migration se fait en remplaçant l’appel startActivityForResult par registerForActivityResult avec le Contract approprié. Supprimez onActivityResult et traitez le résultat dans le callback du launcher. Google fournit un guide de migration dans la documentation Android Developers.

ActivityResultLauncher fonctionne-t-il avec des bibliothèques comme ML Kit ou Barcode Scanner ?

Oui, de nombreuses bibliothèques prennent en charge l’intégration via ActivityResultContracts. Par exemple, ML Kit Barcode Scanner utilise StartIntentSenderForResult pour lancer le scanner. Consultez la documentation de la bibliothèque spécifique.

Résumé

  • ActivityResultLauncher — une API moderne type-safe remplaçant l’obsolète startActivityForResult
  • Contract définit les types de données d’entrée et de sortie, éliminant la correspondance manuelle de requestCode
  • Enregistrement effectué à l’initialisation, le résultat est garanti via callback
  • Contrats intégrés couvrent appareil photo, galerie, permissions, documents et contacts
  • Jetpack Compose utilise rememberLauncherForActivityResult pour travailler avec l’API
  • Contracts personnalisés permettent de réutiliser la logique de lancement entre composants
  • API préserve l’état lors des changements de configuration via SavedStateRegistry

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.

Discuter du projet

Lisez aussi