Votre première application

Ce contenu est obsolète. Il peut contenir des informations intéressantes mais soyez prudent avec celles-ci.

Ce chapitre est très important. Il vous permettra d'enfin mettre la main à la pâte, mais surtout on abordera la notion de cycle d'une activité, qui est la base d'un programme pour Android. Si pour vous un programme en Java débute forcément par un main, vous risquez d'être surpris. :-°

On va tout d'abord voir ce qu'on appelle des activités et comment les manipuler. Sachant que la majorité de vos applications (si ce n'est toutes) contiendront plusieurs activités, il est indispensable que vous maîtrisiez ce concept ! Nous verrons aussi ce que sont les vues et nous créerons enfin notre premier projet — le premier d'une grande série — qui n'est pas, de manière assez surprenante, un « Hello World! ». Enfin presque ! ;)

Activité et vue

Qu'est-ce qu'une activité ?

Si vous observez un peu l'architecture de la majorité des applications Android, vous remarquerez une construction toujours à peu près similaire. Prenons par exemple l'application du Play Store. Vous avez plusieurs fenêtres à l'intérieur même de cette application : si vous effectuez une recherche, une liste de résultats s'affichera dans une première fenêtre et si vous cliquez sur un résultat, une nouvelle fenêtre s'ouvre pour vous afficher la page de présentation de l'application sélectionnée. Au final, on remarque qu'une application est un assemblage de fenêtres entre lesquelles il est possible de naviguer.

Ces différentes fenêtres sont appelées des activités. Un moyen efficace de différencier des activités est de comparer leur interface graphique : si elles sont radicalement différentes, c'est qu'il s'agit d'activités différentes. De plus, comme une activité remplit tout l'écran, votre application ne peut en afficher qu'une à la fois. La figure suivante illustre ce concept.

Cliquer sur un élément de la liste dans la première activité permet d'ouvrir les détails dans une seconde activité

Je me permets de faire un petit aparté pour vous rappeler ce qu'est une interface graphique : il s'agit d'un ensemble d’éléments visuels avec lesquels peuvent interagir les utilisateurs, ou qui leur fournissent des informations. Tout ça pour vous dire qu'une activité est un support sur lequel nous allons greffer une interface graphique. Cependant, ce n'est pas le rôle de l'activité que de créer et de disposer les éléments graphiques, elle n'est que l’échafaudage sur lequel vont s'insérer les objets graphiques.

De plus, une activité contient des informations sur l'état actuel de l'application : ces informations s'appellent le context. Ce context constitue un lien avec le système Android ainsi que les autres activités de l'application, comme le montre la figure suivante.

Une activité est constituée du contexte de l'application et d'une seule et unique interface graphique

Comme il est plus aisé de comprendre à l'aide d'exemples, imaginez que vous naviguiez sur le Site du Zéro avec votre téléphone, le tout en écoutant de la musique sur ce même téléphone. Il se passe deux choses dans votre système :

  • La navigation sur internet, permise par une interface graphique (la barre d'adresse et le contenu de la page web, au moins) ;
  • La musique, qui est diffusée en fond sonore, mais qui n'affiche pas d'interface graphique à l'heure actuelle puisque l'utilisateur consulte le navigateur.

On a ainsi au moins deux applications lancées en même temps ; cependant, le navigateur affiche une activité alors que le lecteur audio n'en affiche pas.

États d'une activité

Si un utilisateur reçoit un appel, il devient plus important qu'il puisse y répondre que d'émettre la chanson que votre application diffuse. Pour pouvoir toujours répondre à ce besoin, les développeurs d'Android ont eu recours à un système particulier :

  • À tout moment votre application peut laisser place à une autre application, qui a une priorité plus élevée. Si votre application utilise trop de ressources système, alors elle empêchera le système de fonctionner correctement et Android l'arrêtera sans vergogne.
  • Votre activité existera dans plusieurs états au cours de sa vie, par exemple un état actif pendant lequel l'utilisateur l'exploite, et un état de pause quand l'utilisateur reçoit un appel.

Pour être plus précis, quand une application se lance, elle se met tout en haut de ce qu'on appelle la pile d'activités.

Une pile est une structure de données de type « LIFO », c'est-à-dire qu'il n'est possible d'avoir accès qu'à un seul élément de la pile, le tout premier élément, aussi appelé sommet. Quand on ajoute un élément à cette pile, le nouvel élément prendra la première place et deviendra le nouveau sommet. Quand on veut récupérer un élément, ce sera le sommet qui sera récupéré, sorti de la liste et l'objet en deuxième place deviendra le nouveau sommet, comme illustré à la figure suivante.

Fonctionnement de la pile d'activités

L'activité que voit l'utilisateur est celle qui se trouve au-dessus de la pile. Ainsi, lorsqu'un appel arrive, il se place au sommet de la pile et c'est lui qui s'affiche à la place de votre application, qui n'est plus qu'à la deuxième place. Votre activité ne reviendra qu'à partir du moment où toutes les activités qui se trouvent au-dessus d'elle seront arrêtées et sorties de la pile. On retrouve ainsi le principe expliqué précédemment, on ne peut avoir qu'une application visible en même temps sur le terminal, et ce qui est visible est l'interface graphique de l'activité qui se trouve au sommet de la pile.

Une activité peut se trouver dans trois états qui se différencient surtout par leur visibilité :

État

Visibilité

Description

Active (« active » ou « running »)

L'activité est visible en totalité.

Elle est sur le dessus de la pile, c'est ce que l'utilisateur consulte en ce moment même et il peut l'utiliser dans son intégralité. C'est cette application qui a le focus, c'est-à-dire que l'utilisateur agit directement sur l'application.

Suspendue (« paused »)

L'activité est partiellement visible à l'écran. C'est le cas quand vous recevez un SMS et qu'une fenêtre semi-transparente se pose devant votre activité pour afficher le contenu du message et vous permettre d'y répondre par exemple.

Ce n'est pas sur cette activité qu'agit l'utilisateur. L'application n'a plus le focus, c'est l'application sus-jacente qui l'a. Pour que notre application récupère le focus, l'utilisateur devra se débarrasser de l'application qui l'obstrue, puis l'utilisateur pourra à nouveau interagir avec. Si le système a besoin de mémoire, il peut très bien tuer l'application (cette affirmation n'est plus vraie si vous utilisez un SDK avec l'API 11 minimum).

Arrêtée (« stopped »)

L'activité est tout simplement oblitérée par une autre activité, on ne peut plus la voir du tout.

L'application n'a évidemment plus le focus, et puisque l'utilisateur ne peut pas la voir, il ne peut pas agir dessus. Le système retient son état pour pouvoir reprendre, mais il peut arriver que le système tue votre application pour libérer de la mémoire système.

Mais j'ai pourtant déjà vu des systèmes Android avec deux applications visibles en même temps !

Ah oui, c'est possible. Mais il s'agit d'un artifice, il n'y a vraiment qu'une application qui est active. Pour faciliter votre compréhension, je vous conseille d'oublier ces systèmes.

Cycle de vie d'une activité

Une activité n'a pas de contrôle direct sur son propre état (et par conséquent vous non plus en tant que programmeur), il s'agit plutôt d'un cycle rythmé par les interactions avec le système et d'autres applications. Voici un schéma qui présente ce que l'on appelle le cycle de vie d'une activité, c'est-à-dire qu'il indique les étapes que va traverser notre activité pendant sa vie, de sa naissance à sa mort. Vous verrez que chaque étape du cycle est représentée par une méthode. Nous verrons comment utiliser ces méthodes en temps voulu.

Cycle de vie d'une activité

Les activités héritent de la classe Activity. Or, la classe Activity hérite de l'interface Context dont le but est de représenter tous les composants d'une application. On les trouve dans le package android.app.Activity.

Pour rappel, un package est un répertoire qui permet d'organiser notre code source, un récipient dans lequel nous allons mettre nos classes de façon à pouvoir trier votre code et différencier des classes qui auraient le même nom. Concrètement, supposez que vous ayez à créer deux classes X — qui auraient deux utilisations différentes, bien sûr. Vous vous rendez bien compte que vous seriez dans l'incapacité totale de différencier les deux classes si vous deviez instancier un objet de l'une des deux classes X, et Java vous houspillera en déclarant qu'il ne peut pas savoir à quelle classe vous faites référence. C'est exactement comme avoir deux fichiers avec le même nom et la même extension dans un même répertoire : c'est impossible car c'est incohérent.

Pour contrer ce type de désagrément, on organise les classes à l'aide d'une hiérarchie. Si je reprends mon exemple des deux classes X, je peux les placer dans deux packages différents Y et Z par exemple, de façon à ce que vous puissiez préciser dans quel package se trouve la classe X sollicitée. On utilisera la syntaxe Y.X pour la classe X qui se trouve dans le package Y et Z.X pour la classe X qui se trouve dans le package Z. Dans le cas un peu farfelu du code source d'un navigateur internet, on pourrait trouver les packages Web.Affichage.Image, Web.Affichage.Video et Web.Telechargement.

Les vues (que nos amis anglais appellent view), sont ces fameux composants qui viendront se greffer sur notre échafaudage, il s'agit de l'unité de base de l'interface graphique. Leur rôle est de fournir du contenu visuel avec lequel il est éventuellement possible d'interagir. À l'instar de l'interface graphique en Java, il est possible de disposer les vues à l'aide de conteneurs, nous verrons comment plus tard.

Les vues héritent de la classe View. On les trouve dans le package android.view.View.

Création d'un projet

Une fois Eclipse démarré, cliquez sur File, puis New et enfin Android Application Projet, comme montré sur cette image :

Prenez ce chemin là pour créer un nouveau projet pour Android

Une nouvelle fenêtre s'ouvre ; voyons ensemble ce qu'elle contient :

Cet écran vous permettra de créer votre premier projet pour Android

Tous ces champs nous permettent de définir certaines caractéristiques de notre projet :

  • Tout d'abord, vous pouvez choisir le nom de votre application avec Application name. Il s'agit du nom qui apparaîtra sur l'appareil et sur Google Play pour vos futures applications ! Choisissez donc un nom qui semble à la fois judicieux, assez original pour attirer l'attention et qui reste politiquement correct au demeurant.
  • Project name est le nom de votre projet pour Eclipse. Ce champ n'influence pas l'application en elle-même, il s'agit juste du nom sous lequel Eclipse la connaîtra. Le vrai nom de notre application, celui que reconnaîtra Android et qui a été défini dans Application name, peut très bien n'avoir aucune similitude avec ce que vous mettrez dans ce champ. Mais pour vous y retrouver, mieux vaut garder une certaine cohérence.
  • Il faudra ensuite choisir dans quel package ira votre application, je vous ai déjà expliqué l'importance des packages précédemment. Sachez que ce package agira comme une sorte d'identifiant pour votre application sur le marché d'applications, alors faites en sorte qu'il soit unique et il devra être constant pendant toute la vie de votre application. En général on se base sur le nom de domaine de son entreprise pour le constitué, c'est pourquoi il commence par com.siteduzero chez moi.

Et pourquoi tu as omis les accents dans ces champs ?

La programmation est un monde profondément anglophone, et les anglais ne connaissent pas nos caractères avec accent. Mettre un "é" dans un mot c'est comme mettre un caractère chinois pour eux ! Ils ne le connaissent pas. Donc pour être sûr de ne pas avoir de problème, ne mettez pas d'accent.

Vous vous retrouvez ensuite confronté à quatres listes défilantes :

  • Minimum Required SDK est la version minimale pour laquelle votre application est destinée. Cette information sera utilisée sur Google Play pour proposer vos applications à des clients. Ainsi, si vous mettez API 18, seuls les clients avec la toute nouvelle version de Jelly Bean pourront utiliser votre application, c'est-à-dire très très peu de gens. Il faut donc mettre un chiffre assez faible pour viser le plus de gens possible. Par exemple en mettant l'API 8, vous viserez 95% des gens qui vont sur Googe Play. A noter que ce n'est pas vraiment une obligation : si un utilisateur, qui est sous Android 1.6 (API 6), obtient votre application (parce que vous lui envoyez par exemple) et que cette application peut fonctionner sous l'API 6, alors il pourra installer l'application et l'utiliser, même si l'API 6 est plus vieille que l'API 8 et que vous avez précisé API 8 dans Minimum Required SDK.
  • L'option Target SDK est l'inverse de Minimum Required SDK, il s'agit de la version maximale sous laquelle votre application fonctionne. Elle exploite les mêmes règles que Minimum Required SDK.
  • La liste Compile With vous permet de choisir pour quelle version du SDK vous allez compiler votre application. Comme indiqué précédemment, on va choisir l'API 7. Il s'agit cette fois de la version minimale nécessaire pour utiliser votre application.

Cliquez sur Next pour passer à l'écran suivant : L'écran suivant

Cette écran contient beaucoup d'options, mais je vais ne vous parler que de deux :

  • La première, intitulée Create custom launcher icon, ouvrira à la fenêtre suivante un outil pour vous aider à construire une icône pour votre application à partir d'une image préexistante.
  • La seconde, celle qui s'appelle Create activity, permet de vous faciliter le développement de l'application en faisant faire une partie par Eclipse.

Pour passer à la page suivante, cliquez sur Next. Si vous avez cliqué sur Create custom launcher icon, alors c'est la fenêtre visible à la figure suivante qui s'affichera.

Cet outil facilite la création d'icônes

Je vous invite à jouer avec les boutons pour découvrir toutes les fonctionnalités de cet outil. Cliquez sur Next une fois obtenu un résultat satisfaisant et vous retrouverez la page que vous auriez eue si vous n'aviez pas cliqué sur Create custom launcher icon (voir figure suivante) :

Vous pouvez ici choisir une mise en page standard

Il s'agit ici d'un outil qui vous demande si vous voulez qu'Eclipse crée une activité pour vous, et si oui à partir de quelle mise en page. On va déclarer qu'on veut qu'il crée une activité, cliquez sur la case à gauche de Create Activity, mais on va sélectionner BlankActivity parce qu'on veut rester maître de notre mise en page. Cliquez à nouveau sur Next.

Dans la fenêtre représentée à la figure suivante, il faut déclarer certaines informations relatives à notre nouvelle activité :

Permet de créer une première activité facilement

Ici encore une fois, on fait face à trois champs à renseigner :

  • Activity Name permet d'indiquer le nom de la classe Java qui contiendra votre activité, ce champ doit donc respecter la syntaxe Java standard.
  • Le champ suivant, Layout Name, renseignera sur le nom du fichier qui contiendra l'interface graphique qui correspondra à cette activité.
  • Enfin, en ce qui concerne Navigation Type, son contenu est trop complexe pour être analysé maintenant. Sachez qu'il permet de définir facilement comment s'effectueront les transitions entre plusieurs activités.

Pour finaliser la création, cliquez sur Finish.

Un non-Hello world!

Vous trouverez les fichiers créés dans le Package Explorer (voir figure suivante).

Le Package Explorer permet de naviguer entre vos projets

On y trouve notre premier grand répertoire src/, celui qui contiendra tous les fichiers sources .java. Ouvrez le seul fichier qui s'y trouve, chez moi MainActivity.java (en double cliquant dessus). Vous devriez avoir un contenu plus ou moins similaire à celui-ci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.siteduzero.mapremiereapplication;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.support.v4.app.NavUtils;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

Ah ! On reconnaît certains termes que je viens tout juste d'expliquer ! Je vais prendre toutes les lignes une par une, histoire d'être certain de ne déstabiliser personne.

1
package sdz.chapitreUn.premiere.application;

Là, on déclare que notre programme se situe dans le package sdz.chapitreUn.premiere.application, comme expliqué précédemment. Si on veut faire référence à notre application, il faudra faire référence à ce package.

1
2
3
4
5
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.support.v4.app.NavUtils;

On importe des classes qui se trouvent dans des packages différents : les classes Activity, Bundle, Menu et MenuItem qui se trouvent dans le même package, puis NavUtils. Chez moi, deux de ces packages sont inutiles car inutilisés dans le code, comme le montre la figure suivante.

Eclipse souligne les importations inutiles en jaune

Il existe trois manières de résoudre ces problèmes :

  • Vous pouvez tout simplement ignorer ces avertissements. Votre application fonctionnera toujours, et les performances n'en souffrirons pas. Mais je vois au moins deux raisons de le faire tout de même : pour entretenir un code plus lisible et pour éviter d'avoir par inadvertance deux classes avec le même nom, ce qui peut provoquer des conflits.
  • Supprimer les lignes manuellement, mais comme nous avons un outil puissant entre les mains, autant laisser Eclipse s'en charger pour nous !
  • Demander à Eclipse d'organiser les importations automatiquement. Il existe un raccourci qui fait cela : CTRL + SHIFTO. Hop ! Tous les imports inutilisés sont supprimés !
1
2
3
public class MainActivity extends Activity {
  //…
}

On déclare ici une nouvelle classe, MainActivity, et on la fait dériver de Activity, puisqu'il s'agit d'une activité.

1
2
3
4
@Override
public void onCreate(Bundle savedInstanceState) {
  //…
}

Le petit @Override permet d'indiquer que l'on va redéfinir une méthode qui existait auparavant dans la classe parente, ce qui est logique puisque vous saviez déjà qu'une activité avait une méthode void onCreate() et que notre classe héritait de Activity.

L'instruction @Override est facultative. Elle permet au compilateur d'optimiser le bytecode, mais, si elle ne fonctionne pas chez vous, n'insistez pas, supprimez-la.

Cette méthode est la première qui est lancée au démarrage d'une application, mais elle est aussi appelée après qu'une application a été tuée par le système en manque de mémoire ! C'est à cela que sert le paramètre de type Bundle :

  • S'il s'agit du premier lancement de l'application ou d'un démarrage alors qu'elle avait été quittée normalement, il vaut null.
  • Mais s'il s'agit d'un retour à l'application après qu'elle a perdu le focus et redémarré, alors il se peut qu'il ne soit pas null si vous avez fait en sorte de sauvegarder des données dedans, mais nous verrons comment dans quelques chapitres, puisque ce n'est pas une chose indispensable à savoir pour débuter.

Dans cette méthode, vous devez définir ce qui doit être créé à chaque démarrage, en particulier l'interface graphique.

1
super.onCreate(savedInstanceState);

L'instruction super signifie qu'on fait appel à une méthode ou un attribut qui appartient à la superclasse de la méthode actuelle, autrement dit la classe juste au-dessus dans la hiérarchie de l'héritage — la classe parente, c'est-à-dire la classe Activity.

Ainsi, super.onCreate fait appel au onCreate de la classe Activity, mais pas au onCreate de MainActivity. Il gère bien entendu le cas où le Bundle est null. Cette instruction est obligatoire.

L'instruction suivante :

1
setContentView(R.layout.activity_main);

sera expliquée dans le prochain chapitre.

En revanche, l'instruction suivante :

1
2
3
4
5
@Override
public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
}

… sera expliquée bien, bien plus tard.

En attendant, vous pouvez remplacer le contenu du fichier par celui-ci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
//N'oubliez pas de déclarer le bon package dans lequel se trouve le fichier !

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {
    private TextView texte = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        texte = new TextView(this);
        texte.setText("Bonjour, vous me devez 1 000 000€.");
        setContentView(texte);
    } 
}

Nous avons ajouté un attribut de classe que j'ai appelé coucou. Cet attribut est de type TextView, j'imagine que le nom est déjà assez explicite. :D Il s'agit d'une vue (View)… qui représente un texte (Text). J'ai changé le texte qu'affichera cette vue avec la méthode void setText(String texte).

La méthode void setContentView (View vue) permet d'indiquer l'interface graphique de notre activité. Si nous lui donnons un TextView, alors l'interface graphique affichera ce TextView et rien d'autre.

Lancement de l'application

Souvenez-vous, je vous ai dit précédemment qu'il était préférable de ne pas fermer l'AVD, celui-ci étant long à se lancer. Si vous l'avez fermé, ce n'est pas grave, il s'ouvrira tout seul.

Pour lancer notre application, regardez la barre d'outils d'Eclipse et cherchez l'encart visible à la figure suivante.

Les outils pour exécuter votre code

Il vous suffit de cliquer sur le deuxième bouton (celui qui ressemble au symbole « play »). Si une fenêtre s'ouvre (voir figure suivante), sélectionnez Android Application.

Sélectionnez « Android Application »

Si vous avez un ou plusieurs AVD lancés et/ou un terminal de connecté, alors cette écran apparaîtra : Vous pouvez choisir où lancer l'application

A partir de celui-ci, il vous est possible de choisir où vous souhaitez que l'application soit exécutée. Par exemple, moi je désire qu'elle le soit sur mon téléphone, je clique donc sur samsung-gt puis sur ok.

Et voilà ! L'utilisateur vous doit 1 000 000 € !

Après vérification auprès d'un avocat, ce n'est pas légalement valable :( .

Les couleurs peuvent être différentes chez vous, ce n'est pas grave


  • Pour avoir des applications fluides et optimisées, il est essentiel de bien comprendre le cycle de vie des activités.
  • Chaque écran peut être considéré comme une Activity, qui est constitué d'un contexte et d'une interface graphique. Le contexte fait le lien entre l'application et le système alors que l'interface graphique se doit d'afficher à l'écran des données et permettre à l'utilisateur d'interagir avec l'activité.
  • Pour concevoir une navigation impeccable entre vos différentes activités, vous devez comprendre comment fonctionne la pile des activités. Cette structure retirera en premier la dernière activité qui aura été ajoutée.