Introduction aux activités

La classe Activity est un composant essentiel d'une application Android. La façon dont les activités sont lancées et assemblées est un élément fondamental du modèle d'application de la plate-forme. Contrairement aux paradigmes de programmation dans lesquels les applications sont lancées avec une méthode main, le système Android lance le code dans une instance Activity en appelant des méthodes de rappel spécifiques qui correspondent à des étapes spécifiques de son cycle de vie.

Ce document présente le concept d'activités, puis fournit quelques conseils simples sur la façon de les utiliser. Pour en savoir plus sur les bonnes pratiques de conception de votre application, consultez le guide de l'architecture des applications.

Le concept d'activités

L'expérience d'une application mobile diffère de celle d'une application pour ordinateur de bureau, car l'interaction d'un utilisateur avec l'application ne commence pas toujours au même endroit. Au lieu de cela, le parcours utilisateur commence souvent de manière non déterministe. Par exemple, si vous ouvrez une application de messagerie depuis votre écran d'accueil, vous pouvez voir une liste d'e-mails. En revanche, si vous utilisez une application de réseau social qui lance ensuite votre application de messagerie, vous pouvez accéder directement à l'écran de l'application de messagerie pour rédiger un e-mail.

La classe Activity est conçue pour faciliter ce paradigme. Lorsqu'une application en appelle une autre, l'application appelante appelle une activité dans l'autre application, plutôt que l'application dans son ensemble. De cette façon, l'activité sert de point d'entrée pour l'interaction d'une application avec l'utilisateur. Vous implémentez une activité en tant que sous-classe de la Activity classe.

Une activité fournit la fenêtre dans laquelle l'application dessine son UI. Cette fenêtre remplit généralement l'écran, mais peut être plus petite que l'écran et flotter au-dessus d'autres fenêtres.

En règle générale, une activité d'une application est spécifiée comme l'activité principale, qui est le premier écran à s'afficher lorsque l'utilisateur lance l'application. Dans les applications Compose modernes, il s'agit de la seule activité nécessaire, car elle héberge des composables dans une architecture à activité unique au lieu de posséder une hiérarchie de vues. Au lieu que l'application comporte plusieurs activités pour les écrans, les composables de l'activité hébergent plusieurs destinations de navigation.

Pour utiliser des activités dans votre application, vous devez enregistrer des informations à leur sujet dans le fichier manifeste de l'application. Il est également recommandé de connaître les cycles de vie des activités. Le reste de ce document présente ces sujets.

Configurer le fichier manifeste

Pour que votre application puisse utiliser des activités, vous devez les déclarer, ainsi que certains de leurs attributs, dans le fichier manifeste.

Déclarer des activités

Pour déclarer votre activité, ouvrez votre fichier manifeste et ajoutez un <activity> élément en tant qu'enfant de l'élément <application>. Exemple :

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

Le seul attribut obligatoire pour cet élément est android:name, qui spécifie le nom de classe de l'activité. Vous pouvez également ajouter des attributs qui définissent les caractéristiques de l'activité, telles que le libellé, l'icône ou le thème de l'UI. Pour en savoir plus sur ces attributs et d'autres, consultez la documentation de référence de l'élément <activity>.

Déclarer des filtres d'intent

Les filtres d'intent sont une fonctionnalité très puissante de la plate-forme Android. Ils permettent de lancer une activité non seulement en fonction d'une requête explicite, mais aussi implicite. Par exemple, une requête explicite peut indiquer au système de "démarrer l'activité Envoyer un e-mail dans l'application Gmail". En revanche, une requête implicite indique au système de "démarrer un écran Envoyer un e-mail dans n'importe quelle activité capable de le faire". Lorsque l'UI du système demande à un utilisateur quelle application utiliser pour effectuer une tâche, il s'agit d'un filtre d'intent en cours d'exécution.

Vous pouvez profiter de cette fonctionnalité en déclarant un <intent-filter> attribut dans l'élément <activity>. La définition de cet élément inclut un <action> élément et, éventuellement, un <category> élément et/ou un <data> élément. Ces éléments se combinent pour spécifier le type d'intent auquel votre activité peut répondre. Par exemple, l'extrait de code suivant montre comment configurer une activité qui envoie des données textuelles et des e-mails, et reçoit des requêtes d'autres activités pour ce faire :

<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
   <intent-filter>
        <action android:name="android.intent.action.SENDTO" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="mailto" />
    </intent-filter>
</activity>

Dans cet exemple, l'élément <action> spécifie que cette activité envoie des données. La déclaration de l'élément <category> en tant que DEFAULT permet à l'activité de recevoir des requêtes de lancement. L'élément <data> spécifie le type de données que cette activité peut envoyer. L'extrait de code suivant montre comment appeler l'activité décrite ci-dessus pour rédiger un e-mail :

fun composeEmail(addresses: Array<String>, subject: String) {
    val intent = Intent(Intent.ACTION_SENDTO).apply {
        data = Uri.parse("mailto:") // Only email apps handle this.
        putExtra(Intent.EXTRA_EMAIL, addresses)
        putExtra(Intent.EXTRA_SUBJECT, subject)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

Si vous souhaitez que votre application soit autonome et n'autorise pas d'autres applications à activer ses activités, vous n'avez pas besoin d'autres filtres d'intent. Les activités que vous ne souhaitez pas mettre à la disposition d'autres applications ne doivent pas avoir de filtres d'intent, et vous pouvez les démarrer vous-même à l'aide d'intents explicites. Pour en savoir plus sur la façon dont vos activités peuvent répondre aux intents, consultez Intents et filtres d'intent.

Gérer les intents entrants

L'exemple suivant montre un modèle de gestion du cycle de vie des activités lors de la gestion de plusieurs types d'intents : partages de texte unique, images uniques et tableaux d'images multiples. En acheminant ces entrées variées via une fonction handleIntent centralisée, il s'assure que les actions ACTION_SEND et ACTION_SEND_MULTIPLE sont correctement analysées et déléguées au ViewModel pour une mise à jour réactive de l'UI.

class ExampleActivity : ComponentActivity() {
  private val viewModel: MyViewModel by viewModels()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    handleIntent(intent)
    setContent {
      ComposeApp(viewModel)
    }
  }

  override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    handleIntent(intent)
  }

  private fun handleIntent(intent: Intent?) {
    when (intent?.action) {
      Intent.ACTION_SEND -> {
        if ("text/plain" == intent.type) {
          intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
            viewModel.handleText(it) // Update UI to reflect text being shared
          }
        } else if (intent.type?.startsWith("image/") == true) {
          (intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java))?.let {
            viewModel.handleImage(it) // Update UI to reflect image being shared
          }
        }
      }

      Intent.ACTION_SEND_MULTIPLE -> {
          if (intent.type?.startsWith("image/") == true) {
              intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)?.let {
                  viewModel.handleMultipleImages(it) // Update UI to reflect multiple images being shared
              }
          } else {
              // Handle other types
          }
      }

      else -> {
          // Handle other intents
      }
    }
  }
}

Déclarer des autorisations

Vous pouvez utiliser la balise <activity> du fichier manifeste pour contrôler les applications qui peuvent démarrer une activité particulière. Une activité parente ne peut pas lancer une activité enfant, sauf si les deux activités disposent des mêmes autorisations dans leur fichier manifeste. Si vous déclarez un <uses-permission> élément pour une activité parente, chaque activité enfant doit avoir un <uses-permission> élément correspondant.

Par exemple, si votre application souhaite utiliser une application hypothétique nommée SocialApp pour partager un post sur un réseau social, SocialApp elle-même doit définir l'autorisation dont une application l'appelant doit disposer :

<manifest>
<activity android:name="...."
   android:permission="com.google.socialapp.permission.SHARE_POST"

/>

Ensuite, pour être autorisé à appeler SocialApp, votre application doit correspondre à l'ensemble d'autorisations défini dans le fichier manifeste de SocialApp :

<manifest>
   <uses-permission android:name="com.google.socialapp.permission.SHARE_POST" />
</manifest>

Pour en savoir plus sur les autorisations et la sécurité en général, consultez la checklist de sécurité.

Gérer le cycle de vie des activités

Au cours de sa durée de vie, une activité passe par plusieurs états. Vous utilisez une série de rappels pour gérer les transitions entre les états. Les sections suivantes présentent ces rappels. Dans une application Compose, il n'est pas recommandé de se connecter directement à ces rappels. Utilisez plutôt l'API Lifecycle pour observer les changements d'état. Pour en savoir plus, consultez Intégrer le cycle de vie à Compose.

onCreate

Vous devez implémenter ce rappel, qui se déclenche lorsque le système crée votre activité. Votre implémentation doit initialiser les composants essentiels de votre activité. Par exemple, votre application doit créer des vues et lier des données à des listes ici.

Dans une application Compose, utilisez ce rappel pour configurer votre composable hôte à l'aide de setContent, comme indiqué ci-dessous :

class MyActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text(text = stringResource(id = R.string.greeting))
        }
    }
}

Lorsque onCreate se termine, le rappel suivant est toujours onStart.

onStart

Lorsque onCreate se termine, l'activité passe à l'état Started et le activité devient visible pour l'utilisateur. Ce rappel contient ce qui équivaut aux préparatifs finaux de l'activité pour passer au premier plan et devenir interactive.

onResume

Le système appelle ce rappel juste avant que l'activité ne commence à interagir avec l'utilisateur. À ce stade, l'activité se trouve en haut de la pile d'activités et capture toutes les entrées de l'utilisateur. La plupart des fonctionnalités de base d'une application sont implémentées dans la onResume méthode.

Le onPause rappel suit toujours onResume.

onPause

Le système appelle onPause lorsque l'activité perd le focus et passe à l' état Paused. Cet état se produit, par exemple, lorsque l'utilisateur appuie sur le bouton "Retour" ou "Applications récentes". Lorsque le système appelle onPause pour votre activité, cela signifie techniquement que votre activité est toujours partiellement visible, mais le plus souvent, cela indique que l'utilisateur quitte l'activité, et que l'activité passera bientôt à l'état Stopped ou Resumed.

Une activité à l'état Paused peut continuer à mettre à jour l'UI si l'utilisateur s'attend à ce qu'elle le fasse. Par exemple, une activité qui affiche un écran de carte de navigation ou un lecteur multimédia en cours de lecture. Même si ces activités perdent le focus, l'utilisateur s'attend à ce que leur UI continue de se mettre à jour.

Vous ne devez pas utiliser onPause pour enregistrer des données d'application ou utilisateur, effectuer des appels réseau ou exécuter des transactions de base de données. Pour en savoir plus sur l'enregistrement des données, consultez Enregistrer et restaurer l'état temporaire de l'UI.

Une fois onPause l'exécution terminée, le rappel suivant est soit onStop ou onResume, selon ce qui se passe après que l'activité passe à l'état Paused.

onStop

Le système appelle onStop lorsque l'activité n'est plus visible pour l' utilisateur. Cela peut se produire parce que l'activité est en cours de destruction, qu'une nouvelle activité démarre ou qu'une activité existante passe à l'état Resumed et couvre l'activité arrêtée. Dans tous ces cas, l'activité arrêtée n'est plus visible.

Le rappel suivant que le système appelle est onRestart, si l' activité revient pour interagir avec l'utilisateur, ou onDestroy si cette activité se termine complètement.

onRestart

Le système appelle ce rappel lorsqu'une activité à l'état Stopped est sur le point de redémarrer. onRestart restaure l'état de l'activité à partir du moment où elle a été arrêtée.

Ce rappel est toujours suivi de onStart.

onDestroy

Le système appelle ce rappel avant la destruction d'une activité.

Ce rappel est le dernier que l'activité reçoit. onDestroy est généralement implémenté pour s'assurer que toutes les ressources d'une activité sont libérées lorsque l'activité ou le processus qui la contient est détruit.

Cette section ne fournit qu'une introduction à ce sujet. Pour une présentation plus détaillée du cycle de vie des activités et de ses rappels, consultez Le cycle de vie des activités.