Environnement de développement Androïd

Objectifs

L’objectif principal de ce travail pratique et de se familiariser avec l’environnement de développement Androïd, notamment :

  • créer un nouveau projet Androïd,
  • créer une machine virtuelle pour tester le projet,
  • comprendre l’organisation des composants d’une application Androïd,
  • composer une interface graphique basique, et
  • y associer des fonctionnalités.

On verra dans la suite comment faire des interfaces plus complexes.

Démarrer l’environnement de développement Androïd

Dans ce travail pratique, nous utilisons l’environnement de développement Androïd créé par Google. Cet environnement de développement intégré (EDI) est une version modifiée d’IntelliJ, un outil dans la même catégorie qu’Eclipse. Pour le lancer dans les salles de TP, taper en ligne de commande :

/usr/local/nfs_bin/AndroidStudio3 &

Dans les salles de TP, cette commande peut prendre jusqu’à 15 minutes lors du premier lancement. Il est fortement conseillé de la lancer tout de suite puis revenir ici pour lire la suite des consignes.

Lorsqu’on lance Android Studio, l’écran d’accueil nous affiche quelques actions possibles tel qu’ouvrir un projet existant ou créer un nouveau projet (« Start a new Android Studio projet »). C’est ce dernier qu’on va choisir.

Créer un premier projet

Nous allons maintenant créer un premier projet Androïd. Notre application sera un convertisseur de monnaies. Dans sa première version, il y aura trois étiquettes, trois champs de texte, et deux boutons : convertir et RÀZ (remet à zéro). Commençons.

  • Pour le nom de l’application, saisir un nom qui convient, « Sous » par exemple.
  • Pour le nom du domaine de l’entreprise, mettre « votre_nom.enst.fr ».
  • Pour la localisation du projet sur le disque, choisir un dossier raisonnable.
  • Vérifier que la configuration ressemble à celle dessous, puis faire « Next ».
Nouveau projet
  • Pour la version Android, choisir une version minimale à prendre en charge pour faire tourner votre application. Dans les salles de TP, choisissez l’API 26, déjà installé sur les machines. Sur votre machine, vous êtes plus libre. « Next ».
Niveau API et dispositifs cibles
  • Choisir Empty Activity, puis faire « Next ».
Empty Activity
  • Laisser les options par défaut pour nommer l’activité MainActivity, puis faire « Finish ».

Si tout s’est bien déroulé, vous auriez un joli projet Androïd.

Organisation d’un projet Androïd

Regardons un peu plus proche le projet qu’Android Studio nous a créé. Vous avez peut-être remarqué qu’il y a un ou deux million de dossiers dans notre projet, dont quelques uns qui nous concerne aujourd’hui :

  • app — c’est ici où il y aura tous les contenus de notre application, dont src et res, décrits dessous.
  • gradle — l’outil utilisé par Androïd pour compiler et empaqueter nos applications. C’est un concept analogue aux Makefiles que vous auriez vu ou allez voir dans INF224.
  • src — ce dossier contient le code source pour notre application, dont
    • MainActivity.java qui est notre écran principal. Rappelons qu’une activité correspond à peu près à un écran en Androïd.
  • res — contient les ressources non-code de l’application
    • drawable-* — les images brutes à composer dans l’interface. Les versions différentes correspondent à la résolution du dispositif.
    • layout — les descriptions de l’interface sous format XML, dont notre
      • activity_main.xml qui décrit l’interface pour MainActivity.java.
    • values — nous ignorons ces fichiers sauf :
      • strings.xml qui contient des définitions des chaines de caractères qu’on utilise dans l’interface

La première chose qui est un peu bizarre est cette notion de séparation des chaines de caractères dans leur propre fichier. Cet approche nous permet de facilement créer des localisations et traductions du texte dans le projet.

Les fichiers layout/*.xml sont un peu comme les designs qu’on fait dans Qt Designer. C’est un fichier XML qui décrit l’interface qui sera affichée sur l’écran.

Tester l’appli

La première chose qu’on aimerait faire est probablement de tester notre application. Pour l’instant, il ne ferait pas grande chose, mais comme tous les informaticiens, on commence par notre petit « Coucou au monde !».

Cliquer le bouton « Run », avec son petit triangle vert. La première fois qu’on fait cela, Android Studio nous demandera de créer une machine virtuelle pour émuler un dispositif Androïd. On vera un écran un peu comme le suivant :

Androïd Virtual Device Manager

Nous allons cliquer le bouton en bas pour créer un nouveau dispositif virtuel.

Dispositif Virtuel

Les machines de la salle de TP n’étant pas les plus puissantes, je vous conseille de ne pas choisir le tout dernier modèle. Le Pixel 2 semble un bon compromis.

Ensuite, on doit choisir la version d’Androïd que la machine virtuelle fera tourner. Ce qui est important est que la version des APIs Androïd soit au moins aussi récente (élevé) que ce que vous avez choisi lors de la création du projet (soit 26, sauf si vous avez fait un autre choix). S’il y a une version déjà téléchargée (qui n’a pas de lien « Download ») dont l’API est suffisamment élevé, utilise-là. Sinon, faites un choix qui est ≥ l’API de votre projet.

Si tout va bien, Android Studio lancera notre nouvelle machine virtuelle. Au bout de quelques minutes, une fois la machine bien démarrée (et vous bien marré), vous devrez voir un joli robot qui dit « Hello World ».

Composer une interface

Ouvrir layout/activity_main.xml. Android Studio pourrait nous proposer un éditeur graphique pour composer l’interface. C’est un très bon outil, mais pour mieux apprendre ce qui se passe réellement, nous allons dans un premier temps utiliser l’interface XML. Cliquer l’onglet Text en bas de l’éditeur pour passer à la vue XML.

L’interface qu’on voit corresponde à notre « Hello World », créé automatiquement par Eclipse lorsque l’on crée un nouveau projet. Dans un premier temps, changer le RelativeLayout en LinearLayout et modifier les attributs pour que ça ressemble à :

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="fr.enst.igr201...MainActivity" >

Notre première version de l’interface contiendra quatre rangs : un pour une étiquette et champs de texte pour saisir le montant en euros, un pour saisir le taux d’échange, un pour indiquer la valeur équivalente en dollars, et un pour les deux boutons.

Pour créer ces rangs, il suffit de mettre un layout à l’intérieur du LinearLayout, créant une hiérarchie de widgets. Le LinearLayout que nous avons déjà créé aura une orientation verticale. Pour créer les rangs, ça suffit donc de mettre d’autres LinearLayouts dedans, mais avec un orientation horizontale. (Bien entendu, il y a d’autres layouts possibles.)

Testons la nouvelle version pour assurez que nous n’avons pas cassé l’interface. Si vous ne voyez pas « Hello World », déboguer le layout jusqu’à ce que ça marche.

Ensuite, rajouter un autre LinearLayout dans le premier. Il n’y aura plus besoin des attributs xmlns:* et tools:context. Virer-les, et changer l’orientation en horizontal. De plus, on ne veut plus que la hauteur soit celle du parent. Changer-la donc en wrap_content, nous laissant avec :

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

Déplacer le TextView dans ce rang et changer son texte en @string/euros_label. Si vous essayez de lancer l’application, Android Studio se plaindra que cette valeur n’est pas encore définie. Le compilateur est vigilant, mais nous ne sommes pas esclave à la machine ! On la définira tout à l’heure, quand on le veut. Ensuite, rajouter un champs de texte :

    <EditText android:id="@+id/edit_euros"
            android:inputType="numberDecimal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="@string/euros_label" />

Noter que nous avons donné un android:id attribut à cet item. Cet attribut permettra d’accéder à ce widget dans notre code java. Le + avant id indique que l’on définie un nouvel objet avec cet identifiant.

Tester encore l’interface pour vérifier que ça marche. Normalement, on verra que ça ne compile pas, parce que nous n’avons pas encore définie la @string/euros_label.

Ouvrir le fichier strings.xml dans res/values et y rajouter une entrée pour euros_label avec la valeur « Euros » en suivant le modèle des autres strings définies dans le fichier.

Tester encore et déboguer si nécessaire.

Une fois content que ça marche, rajouter un autre rang pour la taux d’échange. Re-compiler et lancer pour tester. Puis rajouter un rang pour le résultat. Indice : pour créer un champ de texte non-modifiable, utiliser les attributs android:enabled="false" et android:focusable="false".

Tester l’application encore une fois.

Remarquer que la mise-en-place de l’interface n’est pas terrible. Les widgets sont dimensionnés par la taille de leur contenu et non par la place disponible. Il existe une autre option, android:layout_weight qui donne un poids relatif au widget dans le layout. C’est comme faire un cocktail : le poids et relatif aux autres composants (e.g. pour faire une interface délicieuse, faire une part TextView pour deux parts EditText. Miam !). Par défaut, un widget à un poids 0. Quand on utilise un android:layout_weight pour une dimension, on ne veut plus calculer la taille en fonction des contenus, donc on met aussi android:layout_width (ou height, le cas échéant) à 0dp :

    <EditText android:id="@+id/edit_euros"
        android:inputType="numberDecimal"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="@string/euros_label" />

Dans un nouveau rang, rajouter les boutons. Un bouton s’écrit comme ça :

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_convert"
        android:onClick="convert" />

L’attribut android:onClick relie le bouton à une méthode de l’activité associée tout à l’heure avec le tools:context attribut. Nous allons définir cette méthode prochainement. Mais d’abord, ne pas oublier de définir les strings dans strings.xml.

Implementer la fonctionnalité

La méthode de rappel (« callback ») associé à un widget via android:onClick devrait être void et devrait accepter un seule paramètre, la View qui à déclenché l’action :

    public void maMethode(View sender) { ... }

Implementer les méthodes de rappel référencée dans le layout. Pour retrouver un widget défini dans le layout par son identifiant, utiliser :

    EditText editText = (EditText) findViewById(R.id.identifiant_du_widget);

Pour retrouver et modifier la valeur d’un champ de texte, les méthodes editText.getText().toString() et editText.setText(blaBlaString) pourraient être utiles.

Améliorer l’interface

Félicitations, votre application Androïd marche. S’il vous reste du temps, penser à améliorer l’interface. Google propose des bons guides sur le site web Androïd :

(Je n’ai pas trouvé de bonnes traductions en français, mais ça n’empêche pas qu’elles existent !)

Quelles modifications feriez-vous ?

La semaine prochaine, nous verrons comment afficher plusieurs écrans avec plusieurs activités.