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.

Avant de le lancer dans les salles de TME, faites les démarches indiquées ici.

Puis, pour le lancer dans les salles de TME, taper en ligne de commande :

/opt/android-studio/bin/studio.sh &

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 quelque chose comme « Sous ».
  • Pour le nom du projet, laisser « Sous ».
  • Pour le nom du domaine de l’entreprise, mettre « fr.upmc.votre_nom.sous ».
  • Pour la localisation du projet sur le disque, choisir un dossir raisonnable.
  • Vérifier que la configuration ressemble à celle dessous, puis faire « Next ».
  • Laisser les options par défaut, puis faire « Next ».
  • Idem.
  • Choisir Empty Activity, puis faire « Next ».
  • Laisser les options par défaut, puis faire « Finish ».

Si tout s’est bien déroulé, vous auriez un joli projet Androïd. Testons-le en ouvrant notre MainActivity.java dans le dossier src, puis en cliquant le bouton « Run » pour le compiler et lancer. Si tout va bien, Eclipse 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 ».

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. Commençons là.

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.