Les Activités

Introduction

Les activités représentent une famille de classe centrale dans la structure de code d’Android. Une activité contient tous les mécanismes nécessaires pour utiliser les différents services Android (contexte, ressources, « intents », etc.) Bien comprendre les activités en Android revient à bien comprendre la structure applicative d’Android. Par contre, la gestion des activités se fait différemment de l’approche objet standard en Java.

Qu’est-ce qu’une activité

La question peut avoir plusieurs réponses en fonction du point de vue que nous le prenons.

Au niveau structural (programmation-objet), on peut voir une activité comme un contrôleur (voir modèle MVC). Dans ce sens, il fait le pont entre les éléments du modèle (par exemple, dans un logiciel de vente, ce serait les objets Produit, Client, Facture, etc.) et les vues (qui sont presque entièrement gérés par des librairies Android externes à votre programme et géré dans les ressources). Ce contrôleur peut être aidé par d’autres classes (helper, adaptateur, etc.) En général, chaque application gère un seul affichage (qu’on pourrait appeler page).

Au niveau code, on peut voir une activité comme le point d’entrée d’une application. Contrairement à une application conventionnelle; une application Android ne démarre pas dans une fonction Main. Une application Android fonctionne par événement. On pourrait dire d’une certaine manière que le point d’entrée d’une application Android est la méthode « onCreate » d’une Activité. Il est par contre important de comprendre qu’il s’agit là d’une simplification et que lorsque la méthode onCreate est lancée, l’application a déjà effectué une grande quantité de travail que nous ne voyons pas. Il est également important de spécifier qu’il peut y avoir plusieurs « points d’entrée » dans une application Android. En effet, il peut y avoir plusieurs activités, dans la même application, qui peut être lancée par Android. Prenez par exemple une application de courriel. Si vous ouvrez l’application à partir de la liste d’application, l’activité présentant une liste de courriel sera utilisée comme point d’entrée. Par contre, si l’utilisateur appuie sur une adresse courriel, il aura la possibilité de l’ouvrir dans l’application de courriel. Dans ce dernier cas, l’activité qui permet d’écrire un courriel sera utilisée.

Au niveau fonctionnalité, on peut également voir l’activité comme un pont entre le système applicatif Android et l’application. Par exemple, l’activité permet de savoir si le système Android veut détruire l’application, le mettre en pause, le redémarrer, etc. Également, l’activité permet d’avoir facilement accès à un objet « context » d’Android qui vous permet d’avoir accès aux différents services d’Android (ressources de l’application, service externe, Caméra, localisation, Bluetooth, etc.)

Configuration d’une activité

Les activités de l’application doivent être configurées dans le fichier manifeste de l’application. Il est très important de comprendre que chaque activité doit être spécifiée dans le fichier manifeste afin d’être utilisée. Voici un exemple:

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

Il est important de comprendre que le tag XML « activity » peut avoir beaucoup d’attributs différents qui font une multitude de choses, mais la seule attribut obligatoire est l’attribut « android:name » qui doit contenir le nom de la classe Android. Le point (« . ») au début du nom représente le « package » Java en cours. Si vous vouliez utiliser une activité dont le code Java se trouvait dans le « package » Java « com.autre.package », je pourrais utiliser le tag « android:name » suivant: « com.autre.package.MonActivite ».

Les autres configurations seront présentées dans les différentes sections ci-dessous.

Lancer une activité

Lancer une activité se fait sur 3 étapes.

    • La première étape consiste à configurer les « Intents » de la prochaine activité;
    • Lancer l’activité;
    • À partir du « onCreate » de la nouvelle activité (celle lancée), aller rechercher les « Intents » (si nécessaire).

Voici un exemple de lancement d’activité:

Voici l’activité principale:

public void onClickButton(View vue){
    Intent secondeActiviteIntent = new Intent(this,
        SecondeActivite.class);
    startActivity(secondeActiviteIntent);
}

Dans ce cas, puisqu’aucune valeur n’a été envoyée à la seconde activité, il n’est pas nécessaire de montrer cette dernière. Elle se comporte exactement comme l’activité principale.

Maintenant, disons que j’aimerais envoyer un message de l’activité principale à la seconde activité. Dans ce cas, il faut utiliser la méthode « putExtra ». Cette méthode permet d’envoyer certains types d’objets (types primitifs, array, Bundle, Serialisable, etc.) Voir la documentation de « putExtra » ici: https://developer.android.com/reference/android/content/Intent#putExtra(java.lang.String,%20android.os.Parcelable).

Voici ce que donnerait l’activité principale:

public void onClickButton(View vue){
    Intent secondeActiviteIntent = new Intent(this,
            SecondeActivite.class);
    secondeActiviteIntent.putExtra("MON_MESSAGE", "Salut");
    startActivity(secondeActiviteIntent);
}

Et maintenant l’activité seconde:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_seconde_activite);
    Intent secondeActiviteIntent = getIntent();
    Toast monToast = Toast.makeText(this,
            secondeActiviteIntent.getStringExtra("MON_MESSAGE"),
            Toast.LENGTH_LONG);
    monToast.show();
}

Lancer une activité d’une autre application

Il ne faut pas directement lancer une activité d’une autre application. Il faut demander à Android de lancer une activité qui peut traiter un certain type de donnée (fichier, texte, image, courriel, etc.) Pour se faire, il nous faut utiliser une mécanique de « Intent » particulière. Premièrement, il faut spécifier un type d’action à envoyer à l’activité à lancer. Pour se faire, on utilise la méthode « setAction ». Également, pour qu’Android soit informé du type d’activité à ouvrir, il faut spécifier le type de donnée qui sera envoyé à l’autre activité. Pour se faire, on utilise « setType ». Enfin, puisque plusieurs activités peuvent recevoir le message et que vous ne savez pas quelles activités seront sélectionnées par l’utilisateur, il est important de respecter le standard dans les noms d’extra à utiliser dans la méthode « putExtra ». En général, on utilise « EXTRA_TEXT », mais d’autres types d’extra pourraient être utilisés (« EXTRA_TIME », « EXTRA_EMAIL », « EXTRA_USER », etc.) Par exemple:

public void onClickButton(View vue){
    Intent evoieIntent = new Intent();
    evoieIntent.setAction(Intent.ACTION_SEND);
    evoieIntent.setType("text/plain");
    evoieIntent.putExtra(Intent.EXTRA_TEXT, "La chaîne à envoyer");
    startActivity(evoieIntent);
}

Lancer une activité d’une autre application avec retour de valeur

En plus de lancer une activité d’une autre application telle que vue plus haut, on peut s’attendre à recevoir des données en retour. Par exemple, on peut demander à une activité d’un explorateur de fichier de retourner le nom d’un fichier. Pour se faire, on utilise un « ActivityResultLauncher ». Voici un exemple:

ActivityResultLauncher<Intent> lanceurActivite = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult aResultat) {
                if (aResultat.getResultCode() == Activity.RESULT_OK) {
                    Intent lData = aResultat.getData();
                    String lCheminFichier = lData.getData().getPath();
                    // Faire quelque chose avec lCheminFichier
                }
            }
        }
);

public void boutonClick(View aVue) {
    Intent lIntent = new Intent(Intent.ACTION_GET_CONTENT);
    lIntent.setType("*/*");
    lanceurActivite.launch(lIntent);
}

Dans cet exemple, une activité pouvant retourner un nom de fichier est lancée et lorsque cette activité a terminé, elle retourne le nom de fichier dans l’argument « lData » de l’événement « onActivityResult ».

Permettre aux autres applications de lancer une activité

Si vous désirez que les activités des autres applications puissent lancer une (ou plusieurs) activité de votre application, vous devez utiliser un « Intent filter » dans le « Manifest » de votre application. Dans ce « Intent filter », vous devez spécifier le (ou les) type d’action accepté, le (ou les) type de donnée accepté ainsi qu’une (ou plusieurs) catégorie de transfert. Voici un exemple:

<activity android:name=".SecondeActivite">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
</activity>

Une fois qu’on a spécifié le « Intent filter », nous pouvons envoyer de l’information à l’activité comme spécifié plus haut. Du code de l’activité appelé, on va chercher les informations avec « getIntent » de la même manière que si l’appel avait été fait à partir de l’application en cours (en utilisant (EXTRA_TEXT ou quelque chose comme ça dans l’argument nom de « get*Extra »). Voici un exemple:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_seconde_activite);
    Intent secondeActiviteIntent = getIntent();
    Toast monToast = Toast.makeText(this,
            secondeActiviteIntent.getStringExtra(Intent.EXTRA_TEXT),
            Toast.LENGTH_LONG);
    monToast.show();
}

Il est important de comprendre qu’il existe une très grande quantité d’actions et de catégories d’Intent possible. Il est presque impossible de toutes les expliquer ici. Donc, je vous recommande d’aller voir la documentation suivante afin de rapidement voir quel type d’Intent existe dans Android. Ça pourra vous aider à savoir ce qui existe lors du développement. Voir: https://developer.android.com/reference/android/content/Intent#standard-activity-actions.

Le cycle de vie d’une activité

Une autre connaissance importante dans le contexte d’une activité Android correspond aux différentes étapes du cycle de vie de celle-ci ainsi que les différents événements qui surviennent lors de ces différentes étapes.

    • La première étape correspond à la création de l’activité. Lors de cette création, l’événement onCreate est lancé.
      • Cet événement est le seul événement obligatoire;
      • L’événement onCreate a minimalement la responsabilité d’initialiser le système de ressources en lançant « setContentView ».
      • Il est à noter que cet événement peut lancer la méthode « Finish » pour annuler l’ouverture de l’activité. Dans ce cas, le seul autre événement qui sera appelé est le « onDestroy ».
      • Il est important de lancer « super.onCreate(Bundle) » au début de cet événement.
      • L’argument « Bundle » permet d’aller chercher les données placées en mémoire par la méthode « onSaveInstanceState ». Sachez que cet argument peut être « null »;
        • Cet argument est utile pour garder des données lorsqu’Android met fin à l’activité.
    • Juste après l’événement « onCreate », l’événement « onStart » est lancé.
      • Contrairement à l’événement « onCreate », l’événement « onStart » est lancé après le « onRestart » et n’est pas lancé si le « onCreate » fait un appel à « finish ».
      • Si « onStart » fait un appel à « finish », les méthodes « onStop » et « onDestroy » seront lancés.
      • Il est important de lancer « super.onStart() » au début de cet événement.
      • L’événement « onStart » ne prend aucun argument.
    • L’événement « onResume » est lancé après les événements « onStart », « onRestart » et « onPause ».
      • Il est important de préciser que contrairement au « onCreate », « onStart » et « onRestart », lors de l’appel de cet événement, l’interface utilisateur est opérationnelle.
      • Il est important de lancer « super.onResume() » au début de cet événement.
      • Cet événement ne prend aucun argument.
    • L’événement « onPause » arrive lorsque l’activité perd le focus de l’utilisateur, mais peut potentiellement être toujours visible par l’utilisateur;
      • Généralement appelé lorsque l’utilisateur utilise le bouton « précédent » ou le bouton « Activités récentes » sur son appareil;
      • Il est important de continuer de gérer l’interface graphique après cet événement;
      • L’événement « onResume » sera lancé par la suite si l’utilisateur remet le focus sur l’activité ou l’événement « onStop » dans les autres cas;
      • Cet événement ne doit pas être utilisé pour sauvegarder des données (état de l’activité, données de l’utilisateur, base de données) ou faire des transactions réseau (incluant requête Web). Utiliser l’événement onSaveInstanceStart (que je ne présenterai pas ici) pour sauvegarder des données;
      • Il est important de lancer « super.onPause() » au début de cet événement;
      • Cet événement ne prend aucun argument.
    • L’événement « onStop » est appelé lorsque l’activité en pause n’est plus visible par l’utilisateur.
      • Cela arrive par exemple lorsque l’activité se termine ou lorsqu’une autre activité est en cours (la méthode « onResume » de l’autre activité a été lancée);
      • Cet événement est généralement suivi par un des événements « onRestart » ou « onDestroy »;
      • Lorsqu’une autre activité plus prioritaire nécessite beaucoup de mémoire, il est possible que l’activité arrêtée soit vidée d’une partie de sa mémoire. Dans ce cas, l’événement « onCreate » sera lancé au lieu de « onRestart » et ce, sans que l’événement « onDestroy » ne soit lancé.
      • Cet événement peut être utilisé afin d’arrêter les modifications d’interfaces (animation, vidéo, etc.)
      • Il est important de lancer « super.onStop() » au début de cet événement;
      • Cet événement ne prend aucun argument.
    • L’événement « onRestart » est appelé lorsqu’une activité en arrêt (que l’événement « onStop » a été appelé) est remis en avant-plan par l’utilisateur.
      • Cet événement est toujours suivi par un événement « onStart ».
      • Il est important de lancer « super.onRestart() » au début de cet événement;
      • Cet événement ne prend aucun argument.
    • Avant de détruire définitivement une activité, le système Android appelle l’événement « onDestroy ».
      • Après l’appel de cette méthode, l’activité n’existe plus dans la mémoire du système.

Voici un petit diagramme pour bien voir ce cycle de vie d’une activité. Prendre en note que pour ne pas complexifier inutilement le diagramme, je n’ai pas représenté le cas où la méthode « finish » serait appelée par les événements « onCreate » ou « onStart » (voir plus haut pour les détails).

Et plus encore!!!

Il est important de comprendre que cette théorie présente uniquement une base de ce qu’une activité peut faire. Il existe plein d’autres fonctionnalités et événements qui peuvent vous être utiles dans votre développement. Pour plus de détails, voir la documentation officielle de la classe Activity: ici.

Retour


Auteur: Louis Marchand
Creative Commons License
Sauf pour les sections spécifiées autrement, ce travail est sous licence Creative Commons Attribution 4.0 International.