Vous êtes sur la page 1sur 139

Chapitre 1

Découvrir la plateforme
Android

© JMF (Tous droits réservés) 1


Plan du chapitre 1
❚ La plateforme Android
❚ L'architecture Android
❚ Les outils de développement

© JMF (Tous droits réservés) 2


Android =
❚ Android = un système d'exploitation open source pour smartphones,
PDA, tablettes : systèmes légers
❚ = une startup rachetée en août 2005 par Google
❚ 5 novembre 2007, création de l’OHA (Open Handset Alliance) = un
consortium créé à l’initiative de Google réunissant des entreprises
opérateurs mobiles, constructeurs et éditeurs logiciels
❚ But de l'OHA = favoriser l’innovation sur les appareils mobiles en
fournissant une plate-forme véritablement ouverte et complète
❚ est gratuit

© JMF (Tous droits réservés) 3


Android et Google
❚ A suscité l'engouement des développeurs grâce à deux Android Developer
Challenge en 2008 et 2009 financé par Google
❚ Conçu pour intégrer les applications Google : Gmail, Google Maps, Google
Agenda, YouTube et la géolocalisation
❚ Les différentes versions ont des noms de dessert (qui suivent l'ordre
alphabétique, de A à Z) qui sont sculptés et affichés devant le siège social
de Google (Mountain View)

❚ source : http://fr.wikipedia.org/wiki/Android
© JMF (Tous droits réservés) 5
Les différentes versions
(1/2)
❚ 1.0 : Version connue des développeurs : sortie avant le premier téléphone
Android (fin 2007)
❚ 1.1 : Version incluse dans le premier téléphone, le HTC Dream
❚ 1.5 : Cupcake (Petit Gâteau), sortie en avril 2009
❚ 1.6 : Donut (Beignet), sortie en septembre 2009
❚ 2.0 (2.0.1) : A cause de nombreux bugs, remplacée par la la 2.1
❚ 2.1 : Eclair, sortie en janvier 2010
❚ 2.2 : FroYo (Frozen Yogourt : Yaourt glacé), sortie en mai 2010
❚ 2.3 : Gingerbread (Pain d'épice), sortie le 6 décembre 2010

© JMF (Tous droits réservés) 6


Les différentes versions
(2/2)
❚ 3.0 : Honeycomb10 (Rayon de miel), sortie le 26 janvier 2011
❚ 4.0 : Ice Cream Sandwich (Sandwich à la crème glacée), version unifiée
pour Smartphone, Tablette et GoogleTV, combinant Gingerbread et
Honeycomb, sortie le 19 octobre 2011
❚ 4.2.2 : API 17 sortie le 11 février 2013
❚ Voir historique des versions et fonctionnalités de chacunes d'entre elles à
http://fr.wikipedia.org/wiki/Historique_des_versions_d'
Android

© JMF (Tous droits réservés) 7


Parts de chaque version
octobre 2013

❚ Versions des machines Android qui ont accédé à Google Play (ex
Android Market) une semaine avant le 2 octobre 2013
❚ Voir à
http://developer.android.com/about/dashboards/index.html
© JMF (Tous droits réservés) 8
Smartphone != ordinateur
❚ Android tire partie des particularités des smartphones :
❙ interface homme machine adapté (tactile, widget)
❙ divers modes : vibreur, sonnerie, silencieux, alarme
❙ notifications (d'applications, d'emails, de SMS, d'appels en instance)
❙ de boussole, accéléromètre, GPS
❙ divers capteurs (gyroscope, gravité, accélération linéaire, baromètre)
❙ NFC, RFID
❙ téléphonie (GSM) et réseau EDGE, 3G
❚ En plus de ce qu'on peut avoir sur un ordinateur : navigateur, bibliothèques
graphiques 2D, 3D (Open GL), base de données (SQLite), applications de
rendu multimédia (audio, vidéo, image) de divers formats, réseau Bluetooth
et Wi-Fi, caméra

© JMF (Tous droits réservés) 9


Le Google Play (ex Android
Market)
❚ Google Play, est une boutique en ligne créée par Google (le 6 mars 2012) par
fusion des services Android Market et d'autres services Google (location de
films, achat de musique, etc.). Elle permet de télécharger et d'installer de
nouvelles applications ("apps") dans le smartphone
❚ Android market est "né" le 22 octobre 2008
❚ "Au 30 octobre 2012, Google Play est fort de 700 000 applications ce qui le met
à égalité avec iOS" : voir historique à
http://fr.wikipedia.org/wiki/Android_Market
❚ Les développeurs d'applications payantes reçoivent 70 % du prix du logiciel, 30
% allant à Google (redistribués aux développeurs via Google Checkout)
❚ Chaque nouveau développeur paie $25 comme frais de dossier (une seule fois)

© JMF (Tous droits réservés) 10


Le SDK Android
❚ l'Android SDK (Software Development Kit) amène des outils :
❙ un environnement de développement
❙ une machine virtuelle Java adaptée : la Dalvik virtual machine
❙ un environnement debugueur DDMS (Dalvik Debug Monitor
Service) utilisant adb (Android Debug Bridge)
❙ un environnement de construction d'application Android aapt
(Android Asset Packaging Tool)
❙ des émulateurs de téléphones ou de tablettes AVD (Android
Virtual Device)
❚ et une énorme API (voir à
http://developer.android.com/reference/packages.html)

© JMF (Tous droits réservés) 11


L'architecture Android
(1/3)
❚ Architecture en "pile logicielle"

© JMF (Tous droits réservés) 12


L'architecture Android
(2/3)
❚ La couche "Applications" : Android est utilisé dans un ensemble contenant
déjà des applications natives comme, un client de mail, des programmes
pour envoyer des SMS, d'agenda, de navigateur web, de contacts
personnels
❚ La couche "Application Framework" : cette couche permet au programmeur
de construire de nouvelles applications. Cette couche fournit la gestion :
❙ des Views (= IHM)
❙ des ContentProviders = l'accessibillité aux données des autres
applications (ex : les contacts) et donc les partages de données
❙ des ressources = les fichiers non codes comme les images, les écrans
(Resource Manager)
❙ des Notifications (affichage d'alerte dans la barre de titre)
❙ des Activitys = l'enchaînement des écrans

© JMF (Tous droits réservés) 13


L'architecture Android
(3/3)
❚ La couche "Libraries" (bibliothèques) = couche logicielle basse pour
utiliser
❙ les formats multimédia : images, audio et vidéo enregistrement comme
rendu
❙ les dessins 2D et 3D, bitmap et vectoriel
❙ une base de données SQL (SQLite)
❚ L'environnement d'exécution (Android Runtime). Toute application est
éxécutée dans son propre processus, dans sa propre Dalvik virtual machine
❚ Le noyau Linux sur lequel la Dalvik virtual machine s'appuie pour gérer le
multithreading, la mémoire. Le noyau Linux apporte les services de sécurité,
la gestion des processus, etc.

© JMF (Tous droits réservés) 14


La Dalvik virtual machine
(DVM)
❚ Est la machine virtuelle Java pour les applications Android
❚ Conçu pour exécuter du code Java pour des systèmes ayant des contraintes
de place mémoire et rapidité d'exécution
❚ Exécute du code .dex (Dalvik executable) = des .class adaptés à
l'environnement Android
❚ Ecrit par Dan Bornstein d'où le nom (= village islandais dont sont originaires
certains de ses ancêtres)
❚ A été choisi par Google car une machine Android peut être lancé plusieurs
instance de la DVM efficacement
❚ Le code de la DVM est open source
❚ référence :
http://en.wikipedia.org/wiki/Dalvik_virtual_machine

© JMF (Tous droits réservés) 15


Installer l'environnement
de développement Android
❚ Depuis fin 2012, c'est plutôt simple.
Voir en annexe les diverses étapes
avant mi 2012. Désormais, après
avoir installé le JDK Java SE
(en général c'est fait), il suffit
de télécharger l'ADT Bundle for
Windows (400 Mo) à
http://developer.android.com/sdk
❚ Comme indiqué, cet ADT (Android Development Tools) délivre :
Eclipse, le SDK Android, le plug-in Eclipse vers ce SDK Android (= le
ADT plugin)
© JMF (Tous droits réservés) 16
❚ Euh Kesako ?
La pile des outils de
développement pour Android

AVD Manager

ADT Eclipse
SDK Android
Plugin

JDK Java (SE)

© JMF (Tous droits réservés) 17


Fin de l'installation de
l'environnement
❚ Après extraction de adt-bundle-windows-XXX, lancer
SDK Manager.exe
❚ Un répertoire eclipse est construit contenant une version
d'Eclipse avec l'ADT plug-in initialisé correctement sur le SDK
Android téléchargé
❚ Et c'est tout : on peut commencer à faire du développement pour
Android
❚ Remarque :
Si vous avez une ancienne installation de l'environnement Android,
celle ci peut être perturbée par cette nouvelle installation

© JMF (Tous droits réservés) 18


Correspondance num
Android, num API
❚ Vous pouvez éventuellement, charger
plusieurs "SDK Platform Android" et
"Documentation". Pour cela on utilise
l'"Android SDK Manager". On obtient :
❚ Remarquer la correspondance entre les
versions du SDK et les numéros d'API,
par exemple SDK Android 2.2 <-> API 8

❚ Voir aussi à
http://developer.android.com/g
uide/topics/manifest/uses-sdk-
© JMF (Tous droits réservés) 19
element.html#ApiLevels
Le AVD (Android Virtual
Device) (1/2)
❚ Pour exécuter les programmes Android, il suffit d'un émulateur. C'est le
AVD (Android virtual device)
❚ A la première utilisation il faut en obtenir un. Par la suite on pourra
utiliser toujours celui là
❚ Dans Eclipse, on peut construire un nouvel AVD
par le
bouton
de la
barre de
menu :
ou bien par Window | AVD Manager
© JMF (Tous droits réservés) 20
Le AVD (Android Virtual
Device) (2/2)
❚ Dans la fenêtre "Android Virtual Device Manager" cliquer New...

❚ Dans la fenêtre "Create new Android Virtual Device (AVD)", Donner lui
un nom "parlant" puis le chercher dans la liste Target

❚ Cliquez "Create AVD" (bouton


en bas de cette fenêtre). Cet
AVD apparaît alors dans la liste
des AVD
© JMF (Tous droits réservés) 21
Bibliographie pour ce
chapitre
❚ Le site officiel d'Android : http://developer.android.com/
❚ Pour installer l'environnement de développement Android :
http://developer.android.com/sdk

© JMF (Tous droits réservés) 22


Chapitre 2

Développement Android

© JMF (Tous droits réservés) 23


Plan du chapitre 2
❚ Les composants d'une application Android : Activity,
Service, Content Provider, Broadcast Receiver
❚ Les Intent
❚ Le manifeste : AndroidManifest.xml
❚ Développer une application Android
❚ Un premier programme

© JMF (Tous droits réservés) 24


Concepts de base
❚ Les programmes sont écrits en Java (eh oui)
❚ L'Android SDK compile l'ensemble du développement (code Java,
données, fichier de ressources, fichier XML) dans un paquetage
Android : un .apk
❚ Toute une application tient dans un .apk et un .apk = une
application
❚ Les composants fondamentaux d'une application Android sont :
Activity, Service, Content Provider, Broadcast Receiver
❚ Certains de ces composants communiquent entre eux à l'aide
d'Intent

© JMF (Tous droits réservés) 25


Activity, Service,
Content Provider
❚ Une activité (activity) "gère l'affichage et l'interaction d'un écran" (DE). Les
activités sont indépendantes les unes des autres. Une activité est une sous
classe de android.app.Activity
❚ Un service (service) est un composant qui est exécuté en tâche de fond. Il
ne fournit pas d'interface graphique. Exemple de service : jouer de la
musique, rechercher des données sur le réseau. Un service est une sous
classe de android.app.Service
❚ Un fournisseur de contenu (content provider) gère des données
partageables. C'est le seul moyen d'accéder à des données partagées entre
applications. Exemple de fournisseur de contenu : les informations de
contact de l'utilisateur du smartphone. On peut créer un fournisseur de
contenus pour des données qu'on veut partager. On récupère un fournisseur
de contenu pour des données partageables en demandant le
ContentResolver du système et en donnant ensuite, dans les requêtes, l'URI
des données. Par exemple : ContentResolver cr = getContentResolver();
© JMFcr.laRequete(lURIDesDonnees,
(Tous droits réservés) ...); 26
Broadcast Receiver, Intent

❚ Un récepteur d'informations (broadcast receiver) est un composant à


l'écoute d'informations qui lui sont destinées. Un tel récepteur indique le
type d'informations qui l'intéressent et pour lesquelles il se mettra en
écoute. Exemple : appel téléphonique entrant, réseau Wi-Fi connecté,
informations diffusées par des applications
❚ L'application réceptrice d'informations (c'est à dire possédant un récepteur
d'informations) n'a pas besoin d'être lancée. Si elle ne l'est pas, Android la
démarre automatiquement
❚ Un récepteur n'est pas une IHM mais peut en lancer une (éventuellement
petite : une barre de notification), ou peut lancer un service traitant l'arrivée
de l'information
❚ Un récepteur d'informations est une sous classe de
android.content.BroadcastReceiver
❚ Les informations sont des Intent
© JMF (Tous droits réservés) 27
Intent

❚ Un évènement (intent) est une "intention" à faire quelque chose


contenant des informations destinées à un autre composant Android.
C'est un message asynchrone
❚ Les activités, services et récepteurs d'informations utilisent les
Intent pour communiquer entre eux
❚ Un évènement est une sous classe de android.content.Intent

© JMF (Tous droits réservés) 28


Composants applicatifs :
un résumé
❚ Activité = logique associée à un écran
❚ Service = opération s'exécutant en arrière plan
❚ Content Provider = fournisseur de contenu ! c'est à dire gestionnaire
des données partageables et/ou persistentes
❚ Broadcast receiver = gestionnaire des messages systèmes ou
applicatifs
❚ Intent = message indiquant une intention à faire une certaine action

© JMF (Tous droits réservés) 29


Le manifeste :
AndroidManifest.xml
❚ Toute application doit contenir le fichier XML AndroidManifest.xml
❚ Ce fichier déclare, entre autre, les différents composants de l'application. Ils
doivent être fils du premier élément manifest du ce fichier XML
❚ Ce fichier contient aussi :
❙ les permissions nécessaires à l'application (accès internet, accès en
lecture/écriture aux données partagées)
❙ le numéro minimum de la version API utilisée
❙ des logiciels et matériels utilisés par l'application (caméra)
❙ des bibliothèques supplémentaires à l'API de base (Google maps library)
❚ Parmi les composants, seuls les récepteurs d'évènements (broadcast
receiver) peuvent ne pas être indiqués dans le manifeste. Les autres
(activitys, services, content providers) doivent l'être sinon ils ne seront
jamais lancés quel que soit le code écrit !

© JMF (Tous droits réservés) 30


Développer une application
Android
❚ De l'installation de l'environnement à la publication de l'application
❚ Les phases sont :
❙ installation de l'environnement (setup) = installer le SDK et les AVDs
Android Virtual Device
❙ le développement = développer le code et les ressources de
l'application
❙ débuguer et tester = DDMS et JUnit
❙ publier sur le Google Play
❚ On peut faire ces diverses phases en ligne de commande ou avec Eclipse

❚ source : http://developer.android.com/guide/developing/index.html

© JMF (Tous droits réservés) 31


Un premier projet :
Hello World

© JMF (Tous droits réservés) 32


Hello World en Android
❚ On veut obtenir :

❚ Remarque :
Suivant les versions des
environnements que vous
avez, vous pouvez avoir
des fenêtres légèrement
différentes des captures
d'écran des diapos
suivantes

© JMF (Tous droits réservés) 33


Développement du projet
Hello World (1/4)
❚ Dans Eclipse, choisir File | New | Android Application Project

❚ On obtient la fenêtre :

© JMF (Tous droits réservés) 34


Développement du projet
Hello World (2/4)
❚ Mettre :

Le nom de l'application
(qui apparaîtra sur le
smartphone)
Le nom du projet (utile
pour eclipse)

Le nom du paquetage
(utile pour le
développement Java)
Le numéro d'API cible (=
Le numéro d'API minimale de l'application est plutôt
l'application (pour un smartphone de destinée aux smartphones
numéro d'API inférieur, l'application ayant ce numéro d'API)
n'est pas exécutée) © JMF (Tous droits réservés) 35
Développement du projet
Hello World (3/4)
❚ Cliquez Next > sur les écrans suivants pour arriver à :

❚ MainActivity sera le nom de la première classe chargée,


instanciée et sur laquelle est lancée la première méthode
❚ activity_main est le nom de base du fichier xml d'écrivant la
première IHM à afficher
© JMF (Tous droits réservés) 36
❚ Cliquer Finish
Développement du projet
Hello World (4/4)
❚ L'environnement Eclipse et l'Android SDK ont créé
plusieurs répertoires et fichiers :
❚ Sous src le package
(android.jmf.monapplihelloworld) avec les
sources de l'application (MainActivity.java)
❚ Le fichier R.java sous le répertoire gen
❚ Le répertoire res (pour ... ressources) contenant,
entre autre, activity_main.xml (dans le sous
répertoire layout) et strings.xml (dans le
sous répertoire values)
❚ Le fichier AndroidManifest.xml de
configuration de l'application

© JMF (Tous droits réservés) 37


L'activité
L'activité générée générée

• Visiblement on utilise le R.java !


• Remarque : R.java est généré par l'environnement (parfois à la
première compilation) et ne devra pas être édité, ... contrairement au
source de l'activité ci dessus
© JMF (Tous droits réservés) 38
SMBXXX : Programmation Android
Le R.java
Le R.java générégénéré

• Des constantes dont :


• la constante main (R.layout.main)
• app_name (R.string.app_name)
• hello (R.string.hello)
© JMF (Tous droits réservés) 39
SMBXXX : Programmation Android
Remarques sur le R.java
Le R.java généré
(1/4)

• Comme indiqué en tête, il est automatiquement généré (le forcer à se générer à


la première construction du projet)
• Il y a correspondance entre les noms dans le fichier R.java et les noms utilisés
dans le programme Android. Les identificateurs dans R.java font référence à
des fichiers se trouvent dans le répertoire res. Par exemple R.layout.main
indique le fichier main.xml se trouvant dans le répertoire layout (sous
répertoire de res)
• Comme main.xml décrit une interface graphique, on affecte cette IHM à une
activité par setContentView(R.layout.main);
© JMF (Tous droits réservés) 40
Remarques sur le R.java
Le R.java généré
(2/4)

• Les images sont accessibles par R.drawable.nomImage et


corrrespondent à des fichiers images dans le répertoire res/drawable.
Le fichier R.java permet d'associer un int à ce nom (de fichier)

© JMF (Tous droits réservés) 41


Remarques sur le R.java
Le R.java généré
(3/4)

• Les noms sont accessibles par R.string.nom et correspondent à des


chaînes de caractères dans le fichier strings.xml (avec un s !) dans le
répertoire res/values. On récupère ces noms dans le code source par
getResources().getString(R.string.nom);
• Le fichier R.java permet d'associer un int à ce nom (bis)

© JMF (Tous droits réservés) 42


Remarques sur le R.java
Le R.java généré
(4/4)

• Les composants graphiques ont un identifiant dans le fichier xml qui les
contient (par exemple le main.xml). Cet identifiant est la valeur de
l'attribut android:id et est de la forme "@+id/leId". On récupère,
dans le code, le composant graphique grâce à cet identifiant par l'appel
findViewById(R.id.leId);
• Par exemple
Button leBouton = (Button)findViewById(R.id.leBelId);

© JMF (Tous droits réservés) 43


Layout
Layout

• Layout = le placement des composants graphiques


dans l'IHM (cf. Java)
• Avec Android, il peut être décrit dans un fichier XML
• Par exemple le activity_main.xml dans
res/layout/activity_main.xml

© JMF (Tous droits réservés) 44


SMBXXX : Programmation Android
Le activity_main.xml
Le main.xml généré
généré

• Fichier répéré par la constante main (R.layout.activity_main)


• argument de setContentView() dans l'activité
• Son contenu peut être visualisé par :

ou par :

suivant l'onglet choisi © JMF (Tous droits réservés) 45


SMBXXX : Programmation Android
main.xml = ?= ?
activity_main.xml

• Il contient la description de l'IHM


• En général, l'IHM est construite par
glisser-déposer
(onglet Layout) proposant :
• le positionnement (Layout)

• les composants graphiques (View)

© JMF (Tous droits réservés) 46


SMBXXX : Programmation Android
main.xml (suite)
activity_main.xml (suite)

• = un LinearLayout a été utilisé contenant un TextView


• Le texte affiché par le TextView (= une zone de texte ~ Label de
AWT) est la chaîne (@string) de l'élément hello du fichier
strings.xml
(ligne android:text="@string/hello")
© JMF (Tous droits réservés) 47
SMBXXX : Programmation Android
strings.xml
strings.xml

• L'élément hello du fichier strings.xml a pour corps


Hello World, MonActivite!
• C'est la chaîne affichée dans le TextField à l'éxécution

© JMF (Tous droits réservés) 48


SMBXXX : Programmation Android
Le manifeste
Le manifeste

© JMF (Tous droits réservés) 49


SMBXXX : Programmation Android
L'exécution (1/3)
❚ Sélectionner le projet dans l'onglet Package Explorer (clic droit), et,
dans le menu contextuel Run As | 2 Android Application

© JMF (Tous droits réservés) 50


L'éxécution (1/)
L'exécution (2/3)

• La suite des écrans puis

finit par amener :

• Déplacer alors la glissière (c'est un smartphone !)

© JMF (Tous droits réservés) 51


SMBXXX : Programmation Android
L'éxécution
L'exécution (3/3)(2/)

• Apparaît alors votre application Android :

© JMF (Tous droits réservés) 52


SMBXXX : Programmation Android
Application Android
❚ Pour obtenir cet "Hello World", nous avons besoin de fichiers XML
de configuration (AndroidManifest.xml), de définitions de
constantes (strings.xml), d'interfaces graphiques
(activity_main.xml) en plus de programmes Java (presque)
créé par le programmeur (MonActivite.java) ou par
l'environnement (R.java)
❚ Tout cet ensemble constitue une application Android (Android app)
❚ Pour d'autres applications plus importantes, on aura besoin d'autres
"ressources"

© JMF (Tous droits réservés) 53


Des exemples
d'applications Android (1/2)
❚ L'environnement Android apporte de multiples exemples
d'applications
❚ Pour les exécuter revenir au l'écran "home"
Au besoin cliquez sur :

❚ Cliquez ensuite sur la grille des applications :

© JMF (Tous droits réservés) 54


Des exemples
d'applications Android (2/2)
❚ Sélectionner les "API Demos"

❚ Des applications sont accessibles, rangées par thèmes :

❚ Le code de ces applications est accessible à partir de :


%repInstalAndroidSDK%\samples\android-XXX\ApiDemos
© JMF (Tous droits réservés) 55
Pour exécuter sur un "vrai"
appareil Android (1/3)
❚ Il faut avoir cocher la case "débugage USB" sur l'appareil
❚ L'appareil étant non connecté,
❙ pour une tablette Samsug Galaxy Tab, faire Applications |
Paramêtres | Applications | Développement | Débogage USB,
❙ pour un téléphone Samsug Nexus S, faire Paramêtres | {}
Options pour les développeurs | Débogage USB,
❙ Activer le débugage USB (la case doit être cochée)
❚ En général cette étape est faite une seule fois
❚ Connecter le cable USB au PC
❚ Vérifier dans une fenêtre de commandes, taper
adb devices
doit afficher la tablette et retourner quelque chose comme :
© JMF (Tous droits réservés) 56
Pour exécuter sur un "vrai"
appareil Android (2/3)
❚ Dans Eclipse, se mettre dans la perspective DDMS
❚ Dans l'onglet Devices apparaît la tablette : la sélectionner

❚ Revenir dans la perspective Java. Lancer le programme (Run As


après avoir sélectionné le projet). La sortie est sur la tablette
❚ Remarque : sous Linux c'est un peu plus délicat voir à
http://developer.android.com/guide/developing/device.html

© JMF (Tous droits réservés) 57


Pour exécuter sur un "vrai"
appareil Android (3/3)
❚ Si on n'arrive toujours pas à lancer l'application sur un vrai
smartphone, cliquer doit sur le projet puis Run As | Run
Configurations...
❚ Sélectionner l'application sous Android, puis l'onglet Target, et
sélectionner l'option Manual

❚ A la prochaine exécution il sera demandé la machine (virtuelle ou


pas) d'exécution, plutôt que le lancement automatique

© JMF (Tous droits réservés) 58


Charger un driver USB de
smartphone (1/3)
❚ En général, si la case Débogage USB est cochée, lorsque le cable
USB entre le smartphone et l'ordinateur est mis, tout devrait bien se
passer, l'ordinateur et Eclipse finisse par trouver le smartphone
❚ Si ce n'est pas le cas,
vérifier que le
gestionnaire d'USB Driver
est bien installé dans le
SDK : on doit avoir :

❚ source : http://developer.android.com/sdk/win-usb.html
© JMF (Tous droits réservés) 59
Charger un driver USB de
smartphone (2/3)
❚ Si vous êtes sous windows, voir ensuite à l'URL
http://developer.android.com/sdk/oem-
usb.html#InstallingDriver
❚ Les principales étapes sont :
❙ Connecter le smartphone à l'ordinateur
❙ Sélectionner l'icône de l'ordinateur, cliquer droit, et sélectionner
Gérer

❙ Sélectionner Gestionnaire de
périphériques dans le panneau
gauche, puis Autres périphériques
dans le panneau droit
© JMF (Tous droits réservés) 60
Charger un driver USB de
smartphone (3/3)
❙ Cliquer droit sur l'icône du smartphone puis l'item "Mettre à jour le pilote"
❙ Dans la nouvelle fenêtre cliquer sur "Rechercher un pilote sur mon
ordinateur"
❙ Aller le chercher dans
RepInstallAndroid%\extras\google\usb_driver\
❙ Cliquer le bouton Suivant

© JMF (Tous droits réservés) 61


Pour désinstaller une
application
❚ Sélectionner l'application (en laissant le doigt sur son icône) puis la
glisser sur Uninstall. Confirmer la désinstallation (2 fois OK !)

❚ Une autre solution :


❚ Choisir bouton Menu | Settings (ou Paramêtres) | Applications |
Manage Applications (ou Gérer les applications)
❚ Choisir l'application à désinstaller
❚ Cliquer sur bouton Uninstall (ou Désinstaller)
❚ Cliquer OK
❚ Cliquer OK
❚ C'est fini !
© JMF (Tous droits réservés) 62
Bibliographie pour ce
chapitre
❚ Pour ce chapitre
http://developer.android.com/guide/components/fundamentals.html

© JMF (Tous droits réservés) 63


Chapitre 3

Les interfaces utilisateurs


avec Android

© JMF (Tous droits réservés) 64


Les IHM des smartphones
❚ Pas seulement clavier écran
❚ Mais écran tactile
❚ Accéléromètre
❚ GPS
❚ Enregistrement de messages audio (notes audio)
❚ Prendre des photos, des vidéos, les envoyer par le
réseau (MMS)
❚ SMS
❚ Téléphone

© JMF (Tous droits réservés) 65


Les IHM avec Android
❚ Bibliothèque propre
❚ Pas AWT, ni Swing, ni Java ME / LCDUI
❚ Décrit par fichier XML
❚ Ecran en Android géré par une activité

© JMF (Tous droits réservés) 66


Activité (Activity)
❚ Correspond à une seule classe Java
❚ Une activité gère l’affichage et l’interaction d’un unique écran (IHM)
ou fenêtre flottante
❚ Gère les événements, lance l'affichage d'autres écrans, lance du
code applicatif
❚ Suit un cycle de vie déterminé (cf. applets, midlets, servlets, EJB, ...)
❚ Crée des Intent pour appeler d'autres activités

© JMF (Tous droits réservés) 67


Construction d'une IHM
❚ Plutôt en XML mais
❚ XML ne peut pas être déboggué !
❚ Tout ne peut pas être fait en XML

© JMF (Tous droits réservés) 68


Premier principe des IHM
(1/4)
Quand on voit ceci :

C'est qu'on a programmé celà :

© JMF (Tous droits réservés) 69


Premier principe des IHM
(2/4)
Si on veut : texte

noir

rouge Aire de des s in

vert

Fenetre Principale
On doit programmer comme :
bt_elips
bt_noir bt_texte
bt_rouge bt_trait
bt_vert bt_rect

=> Fenetre principale = un conteneur AireDes s in

© JMF (Tous droits réservés) 70


Premier principe des IHM
(3/4)
Plus sûrement, si on veut : texte

noir

rouge Aire de des s in

vert

texte
on écrit plutôt : c'est à dire : Fenetre Principale
noir
Cont_col Cont_ligne

rouge Aire de des s in


bt_noir bt_vert bt_trait bt_texte
bt_rouge bt_rect bt_elips
vert

AireDes s in

© JMF (Tous droits réservés) 71


Premier principe des IHM
(4/4)
(Premier principe) : construire une IHM, s'est mettre des composants
graphiques les uns à l'intérieur des autres
Il y a donc, dans une IHM à présenter à l'utilisateur, un arbre de
composants graphiques
Les éléments de cet arbre sont des composants graphiques (redite !)
Etre "fils de" dans cet arbre signifie "être contenu dans"

Voilà pour les composants graphiques ! (et le premier principe des


IHM)

© JMF (Tous droits réservés) 72


Second principe des IHM
(1/3)
❚ Les ensembles de composants graphiques sont des classes. On aura la
classe des boutons, la classe des cases à cocher, etc.
❚ Un composant graphique particulier sera une instance particulière d'une
classe. Par exemple le bouton "Quitter" et le bouton ''Sauvegarder" d'une
IHM seront deux instances de la classe des boutons : merci l'OO !
❚ Il y a une famille de conteneurs et une famille
de non conteneurs
❚ D'où les classes de composants graphiques :

❚ Question : Comment sont rangées ces classes ?

❚ Réponse : dans un arbre d'héritage de classe : merci l'OO (bis) !

© JMF (Tous droits réservés) 73


Second principe des IHM
(2/3)
❚ Plus précisément le point de départ de l'arborescence des classes
est :

❚ C'est le design pattern Composite


❚ remarque : travailAFaire() est répercutée sur tout l'arbre des
instances

© JMF (Tous droits réservés) 74


Second principe des IHM
(3/3)
(Second principe) : les bibliothèques pour construire des IHM sont,
en Java, (et souvent !) des classes rangées par arborescence
d'héritage
Les éléments de cette arborescence sont des classes (redite !)
Etre "fils de" dans cette arborescence signifie "hérite de"

Voilà pour les classes (et le second principe des IHM)

© JMF (Tous droits réservés) 75


Les deux principes des
IHM
❚ Lorsqu'on parle d'IHM, il existe deux arborescences et donc deux
"principes"
❚ 1er principe : Une IHM est construite en mettant des composants
graphiques les uns à l'intérieur des autres
❚ 2ième principe : les composants graphiques sont obtenus comme
instances de classes. Ces classes sont rangées dans une
arborescence d'héritage
❚ Remarque : Ces deux arbres (celui des composants graphiques et
celui des classes) ont peu de choses à voir l'un l'autre
❙ Le premier est l'architecture de l'interface i.e. le placement des
divers composants graphiques les uns par rapport aux autres,
❙ le second est un arbre d'héritage de classes donné une bonne
fois par le concepteur de la bibliothèque graphique
© JMF (Tous droits réservés) 76
Un composant IHM =
3 parties
❚ Un composant graphique a 3 parties :
❙ les données qu'il représente : le modèle (model)
❙ le dessin d'affichage : la vue (view)
❙ ce qui prend en charge les actions de l'utilisateur sur ce
composant : le controleur (controler)
❚ C'est l'architecture MVC
❚ "L'idée est de bien séparer les données, la présentation et les
traitements" (*)
❚ Les traitements sont souvent délégués à un objet autre que le
composant graphique lui même (et qui n'est pas, en général, un
composant graphique) : programmation par délégation

❚ (*) source : http://fr.wikipedia.org/wiki/Paradigme_MVC


© JMF (Tous droits réservés) 77
Les fondamentaux
d'Android
❚ La classe "Noyau" de base est la classe android.view.View (~
java.awt.Component de AWT)
❚ La classe de base des conteneurs est android.view.ViewGroup
(~ java.awt.Container de AWT)
❚ On a donc :

❚ En Android, les conteneurs sont souvent appelés les Layout, les


contrôles sont parfois appelés des widgets (window objects)

© JMF (Tous droits réservés) 78


IHM : construction
procédurale vs. déclarative
❚ En Android on peut construire les IHM en codant en Java des
instructions ...
❚ ... ou en décrivant l'IHM par un fichier XML
❚ La première solution est celle habituelle de Java (SE Swing et AWT,
ME) ou d'autres domaines (Motif, Openwin de Sun, ...)
❚ La seconde est courante dans certains domaines (NeXT, ...)

❚ La bonne nouvelle : on peut construire la plupart des IHM en glisser


déposer cf. Interface Builder de NeXT : Jean-Marie Hullot (1989) ,
Visual Basic, ...

© JMF (Tous droits réservés) 79


Un second programme
❚ On veut créer un programme qui affiche un bouton. Lorsque
l'utilisateur actionne le bouton, l'heure est affichée. Le résultat est :

❚ L'heure est mise à jour lorsqu'on


actionne le Bouton

© JMF (Tous droits réservés) 80


Code du second
programme (1/2)
❚ On peut tout coder en Java dans l'activité :
package android.jmf;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.util.Date;
public class BoutonHeureActivite extends Activity implements View.OnClickListener
{
private Button btn;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
btn = new Button(this);
btn.setOnClickListener(this);
updateTime();
setContentView(btn);
}
public void onClick(View view) {
updateTime();
}
private void updateTime() {
© JMF (Tous droits réservés)
btn.setText(new Date().toString()); 81
}
}
Code du second
programme (2/2)
❚ L'activité est le listener du bouton :
public class BoutonHeureActivite extends Activity
implements View.OnClickListener
❚ Ce qui nécessite d'implémenter la méthode :
public void onClick(View view) qui est lancée lorsqu'on
actionne le bouton (technique des listeners cf. événement Java SE)
❚ Le bouton est mis dans l'activité (setContentView(btn))

© JMF (Tous droits réservés) 82


Second programme : une
autre solution (1/5)
❚ En général, pour l'IHM on utilise plutôt les fichiers XML
❚ Créer une nouvelle application Android
❚ Ouvrir le main.xml (dans res/layout/main.xml). Uniquement
des caractères a-z, 0-9 et _ pour les noms de fichiers sous
res\layout
❚ Et on peut construire l'IHM en glisser déposer !

© JMF (Tous droits réservés) 83


Second programme : une
autre solution (2/5)
❚ La fenêtre du main.xml propose deux
onglets : l'onglet Graphical Layout et
l'onglet main.xml
❚ L'onglet main.xml donne le code XML
de ce fichier
❚ L'onglet Graphical Layout (qui met
souvent du temps à s'afficher lors de
sa première ouverture) permet de
visualiser l'IHM correspondant à ce fichier
(partie droite) et de construire cette IHM en
glisser-déposer avec les éléments graphiques
de la partie gauche
❚ Par exemple, on peut sélectionner le
composant Button et l'amener dans
la partie droite
❚ Ce constructeur d'IHM est l'ADT Visual
Designer © JMF (Tous droits réservés) 84
Second programme : une
autre solution (3/5)
❚ L'onglet Outline indique l'arborescence
des composants graphiques de l'application
❚ Lorsqu'on double-clic sur le composant graphique,
apparaît l'onglet Properties : ce sont les propriétés
du bouton qui apparaissent dans cet l'onglet
❚ Sélectionner le composant graphique dans la
fenêtre d'IHM, clic droit puis
Show In | Properties donne le même résultat

© JMF (Tous droits réservés) 85


Second programme : une
autre solution (4/5)
❚ Positionner les propriétés Layout width
et Layout height à fill_parent
❚ fill_parent (renommé match_parent
après l'API 8) indique que le composant
graphique sera aussi grand (en largeur
ou hauteur) que son conteneur le lui
autorise

❚ source :
http://developer.android.com/guide/topics/ui/declaring-layout.html

© JMF (Tous droits réservés) 86


Second programme : une
autre solution (5/5)
❚ L'IHM est alors généré cf. les deux onglets du main.xml :

© JMF (Tous droits réservés) 87


Correspondance attribut -
méthode
❚ Pour positionner une propriété (= valeur d'attribut = données = ...) d'un
composant graphique on peut le faire soit en XML soit par appel d'une
méthode appropriée
❚ Dans le fichier XML, on positionne une propriété d'un composant graphique
à l'aide d'une valeur d'attribut d'une balise XML
❚ Donc il y a une correspondance entre les noms d'attribut d'une balise XML et
une méthode, pour positionner une propriété d'un composant graphique. On
a, par exemple :

© JMF (Tous droits réservés) 88


à http://developer.android.com/reference/android/view/View.html
Identifier les composants =
la méthode "miracle"
❚ Le fichier main.xml repère les composants par android:id

❚ Dans cet exemple il s'agit de Button01


❚ Le composant est manipulé par cet identifiant dans le programme Java à
l'aide de la méthode ("miracle")
findViewById(R.id.nomIdentifiant);
❚ La valeur nomIdentifiant est celle qui apparaît dans le fichier main.xml
après @+id/
❚ Pour cet exemple ce sera findViewById(R.id.Button01);
© JMF (Tous droits réservés) 89
Second programme,
solution 2 : le code
❚ Comme toute l'IHM est faite dans le main.xml, voici le code de l'activité :
package android.jmf;

import java.util.Date;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class BoutonHeure2Activite extends Activity implements View.OnClickListener {


private Button btn;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
btn=(Button)findViewById(R.id.Button01);
btn.setOnClickListener(this);
updateTime();
}
public void onClick(View view) {
updateTime();
}
private void updateTime() {
btn.setText(new Date().toString());
} © JMF (Tous droits réservés) 90
}
Les Layout
❚ Les containeurs Android sont souvent des XXXLayout !
❚ C'est un peu différent de Java AWT ou Swing. Un Layout Android est un
container et un Layout AWT à la fois
❚ Les principaux Layout Android sont :
❙ LinearLayout (~ un containeur AWT géré par un FlowLayout AWT)
❙ RelativeLayout
❙ AbsoluteLayout (déprécié depuis l'API 3 !)
❚ On a donc :

© JMF (Tous droits réservés) 91


LinearLayout
❚ Les composants à l'intérieur d'un LinearLayout sont rangés les
uns à la suite des autres horizontalement ou verticalement
❚ Principales propriétés d'un LinearLayout : l'orientation, le
mode de remplissage (fill model)

© JMF (Tous droits réservés) 92


Orientation d'un
LinearLayout
❚ L'orientation indique si le LinearLayout présente ces contenus
sur une ligne (horizontalement) ou sur une colonne (verticalement)
❚ La propriété d'orientation à utiliser pour un LinearLayout dans le
fichier XML est l'attribut android:orientation de la balise
LinearLayout. Les valeurs possibles pour cette propriété sont
vertical et horizontal
❚ La valeur vertical indique que les contenus seront les uns en
dessous des autres, la valeur horizontal indique qu'ils seront les
uns à la suite des autres
❚ L'orientation peut être modifiée à l'éxécution par la méthode
setOrientation() lancée sur le LinearLayout en précisant la
valeur LinearLayout.HORIZONTAL ou
LinearLayout.VERTICAL
© JMF (Tous droits réservés) 93
Mode de remplissage (fill
model) d'un LinearLayout
❚ Cela concerne les attributs android:layout_width et
android:layout_height à positionner sur les composants
graphiques contenus dans le LinearLayout
❚ Les valeurs possibles de ces propriétés peuvent être :
❙ une valeur exacte de pixel (125px pour 125 pixels) : c'est
fortement déconseillé
❙ wrap_content qui indique que le composant prend la taille
qu'il faut pour s'afficher correctement entièrement
❙ fill_parent (renommé match_parent
après l'API 8) indique que le composant remplit complètement
la dimension indiquée du LinearLayout

© JMF (Tous droits réservés) 94


Les contrôles Android
❚ Ce sont les composants graphiques que voient l'utilisateur, avec
lesquels il agit sur (contrôle) l'interface graphique
❚ Appelés dans certains domaines, les contrôles
❚ En Android ce sont (par exemple) :
❙ les zones de texte non éditable (~ Label AWT) ou éditable (~
TextComponent AWT) : TextView
❙ les boutons (~ Button AWT) : Button
❙ les zones de texte éditables (~ TextField et TextArea de
AWT) : EditText
❙ les cases à cocher (~ Checkbox AWT) : CheckBox et les
boutons radio RadioButton à regrouper dans un ensemble
❚ Toutes ces classes sont dans le package android.widget et
dérivent de android.view.View
© JMF (Tous droits réservés) 95
Arborescence des principaux
contrôles Android
❚ Les classes de composants non conteneurs (contrôles) sont
rangées dans l'arbre d'héritage :

© JMF (Tous droits réservés) 96


TextView
❚ Peut servir de zone de texte non éditable (~ Label AWT) et dans
ce cas, sert souvent pour présenter les widgets qui suivent
❚ Propriétés importantes :
❙ android:text : le texte du TextView
❙ android:typeface : le type de police utilisée
(monospace, ...)
❙ android:textStyle : le style (italic pour l'italique,
bold_italic pour gras et italique, ...)
❙ android:textColor pour la couleur d'affichage du texte.
Les valeurs sont en hexadécimal en unité RGB (par exemple
#FF0000 pour le rouge)

© JMF (Tous droits réservés) 97


Positionner les
propriétés d'une
widget
❚ On peut positionner les
propriétés d'un composant
graphique à l'aide de l'outil de
développement

© JMF (Tous droits réservés) 98


Arborescence des
composants graphiques dans
une IHM
❚ Faire une IHM c'est mettre des composants dans des composants dans des
composants ... On peut le faire par programmation en utilisant
addView(View) d'un ViewGroup ou dans un fichier XML
❚ Par exemple le fichier :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
</LinearLayout>

= un TextView et un Button dans


un LinearLayout représente l'IHM :
© JMF (Tous droits réservés) 99
Une conclusion : les 3
principaux fichiers XML
❚ Les 3 (types de) fichiers xml : les fichiers sous layout,
values\strings.xml, AndroidManifest.xml
❚ Les fichiers sous layout sont les fichiers xml décrivant des
(parties) d'IHM
❚ Le fichier values\strings.xml contient des valeurs de
chaines de caractères
❚ Le fichier AndroidManifest.xml contient la configuration
de l'application Android (sa description, ses demandes
d'autorisation, etc.)

100
strings.xml
main.xml

101
SMBXXX : Programmation Android
strings.xml
strings.xml

102
SMBXXX : Programmation Android
strings.xml
AndroidManifest.xml

103
SMBXXX : Programmation Android
Si problème avec le R.java
❚ Envisager les traitements suivants :
❚ 1°) faire File | Refresh et/ou Project | Clean dans Eclipse
❚ 2°) Vérifier les fichiers XML sous res
❚ 3°) Enlever import android.R; dans le code
❚ 4°) Détruire le fichier R.java et attendre qu'il se reconstruise

© JMF (Tous droits réservés) 104


La gestion des
événements
❚ Deux moyens :
❙ 1°) créer un auditeur d'événements (classe qui implémente une
interface connue) et l'enregistrer auprès du composant (View)
❙ 2°) les View sont elles mêmes auditrices de certains
événements : (touché de l'écran). Spécialiser la méthode
adaptée et lancée lorsque l'événement survient
❚ 1°) est classique (Java SE, Java ME). Les interfaces sont des
interfaces internes à la classe View et de nom OnXXXListener
(donc des interfaces de nom View.OnXXXListener). Cela
nécessite d'implémenter une méthode de nom onXXX(). On
enregistre un auditeur par
setOnXXXListener(View.OnXXXListener l)
❚ 2°) permet d'écrire directement la gestion de certains événements
qui peuvent se produire dans la View
© JMF (Tous droits réservés) 105
Créer un auditeur
d'événements : exemple
❚ Le code peut être :
private OnClickListener lAuditeurDuBouton = new OnClickListener() {
public void onClick(View v) {
// code lancé lorsque le bouton est cliqué
}
};

protected void onCreate(Bundle savedValues) {


...
// Récupération du Button à partir de l'IHM en XML
Button button = (Button)findViewById(R.id.leBeauBouton);
// Enregistrer l'auditeur auprès du bouton
button.setOnClickListener(lAuditeurDuBouton);
...
}

© JMF (Tous droits réservés) 106


Méthodes lancées par les
auditeurs d'événements
❚ onClick() (de View.OnClickListener) est lancée lorque
l'utilisateur touche le composant graphique, ou après appui sur enter
alors que le composant a le focus
❚ onLongClick() (de View.OnLongClickListener) : idem que
si dessus mais après un appui de plus de 1 seconde
❚ onKey() (de View.OnKeyListener) est lancée après appui et
relachement d'un touche clavier
❚ onTouch() (de View.OnTouchListener) est lancée pour toute
action de toucher (appui, relachement, mouvement de l'utilisateur
sur l'écran)
❚ onCreateContextMenu() (de
View.OnCreateContextMenuListener) est lancée après
création d'un menu contextuel
© JMF (Tous droits réservés) 107
"Enchaîner" les écrans
(1/3)
❚ Pour passer d'un écran à un autre, il faut écrire le code
Intent i0 = new Intent(this, NouvelleActivity.class); //1
startActivity(i0);

et déclarer la nouvelle activité NouvelleActivity.class (le


futur écran) dans AndroidManifest.xml
❚ public void startActivity (Intent intent) est une
méthode de la classe Activity permettant de lancer une autre
Activity. intent est l'Intent (l'intention) qui prépare ce lancement
❚ Remarque : le premier argument du constructeur de l'Intent doit
être le Context. Si l'appel est fait dans une Activity, this
convient car Activity dérive de Context
❚ On utilise souvent Activity.this quand on est dans un listener
d'événement. Sinon, la méthode getApplicationContext()
convient souvent
© JMF (Tous droits réservés) 108
"Enchaîner" les écrans
(2/3)
❚ Pour ajouter la déclaration de la nouvelle Activity
dans AndroidManifest.xml, double cliquer
sur ce fichier et choisir son onglet Application
❚ Cliquez sur Add..., et choisir Activity au besoin
choisir l'item "Create a new element at the top
level ...", cliquez OK

© JMF (Tous droits réservés) 109


"Enchaîner" les écrans
(3/3)
❚ Une nouvelle Activity apparaît dans la liste. Indiquer son nom complet de
classe (après Name:). Si cette classe est dans le même paquetage que
l'activity qui la lance écrire .NouvelleActivity (ce nom suffixera le nom
du paquetage courant)

❚ Vérifier que tout s'est bien passé dans l'onglet AndroidManifest.xml. Il doit y
avoir la ligne
<activity android:name=".AProposActivity"></activity>

❚ Euh, il suffisait de n'écrire que cela !


© JMF (Tous droits réservés) 110
Créer une nouvelle activité
❚ Dans un projet, on peut créer une nouvelle activité comme indiqué
dans les diapos précédentes : écrire une classe dérivant de
Activity, redéfinir les méthodes onCreate(), ... et déclarer cette
activité dans l'AndroidManifest.xml
❚ Avec le nouvel environnement de développement, si on utilise New |
Other...,

suivi de Android Activity

en complétant les écrans qui suivent, l'activité est en partie créée et


sa déclaration dans l'AndroidManifest.xml aussi !
© JMF (Tous droits réservés) 111
Passer de données entre
activité grâce aux Intent
❚ Les Intent servent parfois d'enveloppes pour passer des informations
d'une Activity à une autre. On utilise pour cela une des méthodes
public Intent putExtra(String nomDeLExtra, unType valeur)
❚ Par exemple : Intent i = new Intent(leContexte, MapStationActivity.class);
i.putExtra("latitude", latitudeDuPointCourant);
i.putExtra("longitude", longitudeDuPointCourant);
startActivity(i);

❚ Dans une Activity, on récupére l'Intent qui a lancé l'Activity par


getIntent(). On peut alors récupérer tous les extras de l'Intent par
getExtras(), et, par la suite, un extra associé à une entrée par
getTypeEntrée(nomEntrée, valeurParDefaut),
valeurParDefaut est la valeur retournée si il n'y a pas d'extra associé à
nomEntrée dans l'Intent
❚ Par exemple : double laLatitudeDeLaStation =
getIntent().getExtras().getDouble("latitude", 0);

© JMF (Tous droits réservés) 112


Un simple avertissement :
Toast
❚ Une fenêtre de dialogue qui affiche un message pendant 2
(Toast.LENGTH_SHORT) ou 5 (Toast.LENGTH_LONG) secondes est un
composant graphique Android : le Toast
❚ On le construit et on l'affiche avec le code
Toast leToast = Toast.makeText(leContexte, "texteAAfficher", Toast.LENGTH_LONG);
leToast.show();

❚ Les méthodes qui construisent le Toast sont les méthodes statiques :


public static Toast makeText (Context context, int resId, int duree)
ou
public static Toast makeText (Context context, CharSequence text, int
duree)
context est le contexte à utiliser. En général on passe l'activité courante
text est la chaîne de caractères à afficher resId est l'id de la chaîne à afficher
(à définir dans strings.xml)
duree est la durée d'affichage LENGTH_SHORT ou LENGTH_LONG
❚ Attention construire le Toast ne l'affiche pas : il faut utiliser show() pour cela
© JMF (Tous droits réservés) 113
Code de "trace" en Android
❚ La classe android.util.Log propose plusieurs méthodes de trace (de Log)
hierarchisées. Ces méthodes ont pour nom une seule lettre. Ce sont, dans
l'ordre les méthodes v() (verbose), d() (debug), i() (information), w()
(warning) et e() (erreur)
❚ Ces méthodes ont deux arguments : (String tag, String msg)
❚ Elles permettent de visualiser des traces lors de l'exécution en utilisant la
perspective DDMS. On peut filtrer ces traces en ne laissant afficher que les log
de balise tag @Override
public boolean onOptionsItemSelected(MenuItem item) {
❚ Par exemple le code : // Handle item selection
switch (item.getItemId()) {
case R.id.new_game:
Log.v("JMF", "Une nouvelle partie ?");
Log.d("JMF", "Une nouvelle partie ?");
Log.i("JMF", "Une nouvelle partie ?");
permet de voir les Log.w("JMF", "Une nouvelle partie ?");
Log.e("JMF", "Une nouvelle partie ?");
sorties dans la return true;
perspective DDMS // ...
}
} © JMF (Tous droits réservés) 114
Traces (log) en Android
❚ Dans l'onglet LogCat de la perspective DDMS, on peut créer des filtres de
balises et ne faire afficher que les traces associées à ces balises

❚ On indique le niveau de trace : le niveau verbose affichera toutes les traces de


cette balise (cf. ci dessus), le niveau info n'affichera que les trace info, warning
et erreur (cf. ci dessous)

© JMF (Tous droits réservés) 115


Bibliographie pour ce
chapitre
❚ Pour ce chapitre
http://developer.android.com/guide/topics/ui/index.html
❚ The Busy Coder's Guide to Android Development, Mark L. Murphy ;
editions CommonsWare
❚ Android Application Development, Rick Rogers, John Lombardo,
Zigurd Mednieks and Blake Meike ; editions O'Reilly, 2009

© JMF (Tous droits réservés) 116


Chapitre 3 bis

Les interfaces utilisateurs


avancés avec Android

© JMF (Tous droits réservés) 117


Composants IHM avancés
❚ Certains composants graphiques permettent d'afficher beaucoup d'items
par des mécanismes de défilement. Ce sont :
❙ les Spinner, les Gallery, les GridView, les ListView

❙ Il y en a d'autres. Voir© à Apis


JMF Demos
(Tous | Views
droits réservés) 118
AdapterView et Adapter
❚ Les composants graphiques qui affichent un ensemble d'items sont
des AdapterViews
❚ Ces composants sont très utiles si les données qu'ils affichent ne sont
pas connues à la création du programme mais seront chargées
dynamiquement
❚ Pour fournir les items à ces composants graphiques, on utilise des
Adapter
❚ Comme AdapterView est en fait AdapterView<T extends
android.widget.Adapter>, un AdapterView est toujours
associé à un Adapter
❚ L'Adapter sert de lien avec les données à afficher et
l'AdapterView. Bref c'est le design pattern adapter
❚ Les AdapterView gèrent l’affichage de ces items
© JMF (Tous droits réservés) 119
AdapterView, Adapter et
compagnie ! (1/2)
❚ android.widget.AdapterView<T extends
android.widget.Adapter> est une classe abstraite générique
❚ android.widget.Adapter est une interface. Beaucoup de classes
implémentent cette interface : ArrayAdapter<T>, BaseAdapter
❚ SpinnerAdapter et ListAdapter sont des interfaces qui héritent
de Adapter
❚ Spinner, Gallery, GridView, ListView sont des sous classes
concrètes d'AdapterView
❚ L'association entre un AdapterView et un Adapter est faite à
l'aide de la méthode
public void setAdapter (T adapter)
❚ Question : Où est indiqué que le paramêtre T est un type
implémentant Adapter ?
❚ Réponse : Dans la définition de ladroits
© JMF (Tous classe AdapterView
réservés) 120
AdapterView, Adapter et
compagnie ! (2/2)
❚ On a donc :

© JMF (Tous droits réservés) 121


Tutoriaux pour les
AdapterView
❚ Beaucoup de documentation existe pour les AdapterView
❚ Dans la documentation "officielle", on a des tutoriaux sur ces composants à
partir de la définition de leur classe :
❙ Spinner :
http://developer.android.com/guide/topics/ui/controls/
spinner.html
❙ Gallery : est, en fait, dépréciée à partir de l'API 16. Il faut utiliser des
HorizontalScrollView et des ViewPager
❙ GridView :
http://developer.android.com/guide/topics/ui/layout/gr
idview.html
❙ ListView :
http://developer.android.com/guide/topics/ui/layout/li
stview.html

© JMF (Tous droits réservés) 122


Le composant ListView
❚ "A (List)view (that) shows items in a vertically scrolling
list. The items come from the ListAdapter associated
with this view." (*)
❚ Parfois les items proviennent d'un accès distant
❚ Héritage de ListView :

❚ Une ListView est un AdapterView qui est


"a view whose children are determined by an Adapter." (**)
❚ sources : (*)
http://developer.android.com/reference/android/widget/ListView.html
(**)
http://developer.android.com/reference/android/widget/AdapterView.ht
© JMF (Tous droits réservés) 123
ml
Le composant ListView
❚ Il permet d'afficher une (grande) liste d'items, accessible par défilement
mais aussi par filtre : l'utilisateur tape les premières lettres, le ListView
n'affiche plus que les items qui commencent par ces lettres
❚ Pour définir un ListView, on commence par indiquer comment sera
affiché chaque item du ListView. Par exemple sous forme de
TextView. On construit donc le fichier res/layout/list_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" >
</TextView>

❚ Une démo : projet HelloListView

© JMF (Tous droits réservés) 125


L'activité ListActivity
❚ Une ListView peut occuper tout l'écran. Dans ce cas, elle peut être
construite à partir d'une android.app.ListActivity (qui hérite de
android.app.Activity)
❚ Lorsqu'on construit une classe qui hérite de ListActivity, on peut
alors utiliser plusieurs méthodes de la classe ListActivity :
❙ public ListView getListView() qui retourne le composant
graphique ListView associé à cette activité
❙ public void setListAdapter(ListAdapter adapter)
positionne le ListAdapter associé à la ListView de cette activité
ListActivity
❚ Et on spécialise la méthode onCreate() (comme d'hab) et on a une
Activity qui présente une ListView

© JMF (Tous droits réservés) 126


ListView : 1er exemple à
l'aide de ListActivity
public class HelloListViewActivity extends ListActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, COUNTRIES));

ListView lv = getListView();
lv.setTextFilterEnabled(true);

lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// le code lancé lors de la sélection d'un item
}
});
}
static final String[] COUNTRIES = new String[] { ... }
}

© JMF (Tous droits réservés) 127


ArrayAdapter<T> pour
ListView
❚ On construit le ListAdapter à partir d'un
ArrayAdapter<String>. En fait on a l'arborescence
(d'interfaces, de classe abstraite et de classe
générique !) suivante :
❚ On a utilisé le constructeur :
public ArrayAdapter (Context context,
int textViewResourceId,
T[] objects)
car :
Activity dérive de Context :
textViewResourceId repère l'IHM qui modélise un
item
objects est le tableau de données à afficher
❚ La ListView construite à partir de l'activité et récupérée
par getListView(), est sensible à la sélection par
préfixe grâce à l'appel
setTextFilterEnabled(true);
© JMF (Tous droits réservés) 128
Views "standards" pour les
items d'une ListView
❚ Le second argument du constructeur ArrayAdapter est l'identificateur
du fichier xml décrivant l'aspect de chaque item de la ListView (aspect
qui peut être ensuite enrichi par la programmation)
❚ Certains de ces aspects sont donnés par android lui même ce sont :
android.R.layout.simple_list_item_1 et
android.R.layout.simple_list_item_2
❚ Si, dans le programme précédent, on remplace par
R.layout.list_item (notre propre fichier XML)
par android.R.layout.simple_list_item_1
(une des IHM standard d'android), on obtient :

© JMF (Tous droits réservés) 129


L'aspect
android.R.layout.simple_list_item_1

❚ Il y a peu de différence avec notre list_item.xml


❚ En fait le fichier associé à l'identificateur
android.R.layout.simple_list_item_1 est :
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:paddingLeft="6dip"
android:minHeight="?android:attr/listPreferredItemHeight"
/>

❚ Voir à REP_INSTALL_ANDROID\android-sdk\platforms\android-
XXX\data\res\layout\simple_list_item_1.xml
❚ Ce fichier est encodé dans android.jar
❚ Bref les items sont des TextView
© JMF (Tous droits réservés) 130
La "UI Thread" (1/2)
❚ Lorsqu'une application Android est lancée, un seul processus est
créé qui contient une seule thread pour l'application
❚ Cette thread est dite la thread principale
❚ Elle s'occupe, entre autre, de l'affichage et de l'interaction sur les
divers écrans
❚ Voilà pourquoi cette thread principale est appelée la UI Thread (User
Interface Thread) : "As such, the main thread is also sometimes
called the UI thread."
❚ source :
http://developer.android.com/guide/components/processes-
and-threads.html

© JMF (Tous droits réservés) 131


La "UI Thread" (2/2)
❚ De plus, dans une application Android, il existe une et une seule
thread qui gère l'interface graphique : la UI Thread (User Interface
Thread)
❚ Tout ce qui concerne l'affichage est (et doit être) géré par cette
Thread. Si une autre Thread s'occupe de faire de l'affichage
graphique, il y a erreur à l'exécution
❚ Lorsqu'un travail demandant du temps est lancé, il faut le faire dans
une Thread autre que la UI Thread. Au besoin en créé une !
❚ Mais lorsque autre thread demande à afficher dans l'IHM, cette
autre thread doit contacter l'UI Thread !
❚ Au lieu de créer de telles threads et de les gérer, Android propose
une classe qui gère correctement cela. C'est la classe (générique !)
android.os.AsyncTask<Params, Progress, Result>

© JMF (Tous droits réservés) 132


La classe
android.os.AsyncTask<Params, Progress, Result>

❚ Elle est faite pour gérer correctement la gestion entre une thread
(de traitement long) et la UI Thread
❚ Elle permet de lancer un traitement en arrière plan et de mettre à
jour (éventuellement de temps en temps) l'interface graphique de
l'application
❚ Les paramètres génériques sont utilisés pour :
❙ Params : le type des paramètres nécessaires à la tâche en
arrière plan
❙ Progress : le type des paramètres reçus par la méthode de
mise à jour
❙ Result : le type du résultat retourné par la tâche en arrière
plan

© JMF (Tous droits réservés) 133


Les méthodes de AsyncTask<Params,
Progress, Result> (1/2)
❚ Cette classe contient 4 méthodes dont trois d'entre elles sont
exécutées dans la UI Thread. Ce sont :
protected void onPreExecute ()
protected void onProgressUpdate (Progress...
values)
protected void onPostExecute (Result result)
qui sont exécutées dans la UI Thread et
protected abstract Result doInBackground
(Params... params) lancée dans une autre thread
❚ onPreExecute() est exécutée avant le lancement de la tâche
d'arrière plan

© JMF (Tous droits réservés) 134


Les méthodes de AsyncTask<Params,
Progress, Result> (2/2)
❚ doInBackground(Params...) est lancé après
onPreExecute() dans une thread autre que la UI Thread : c'est le
traitement en arrière plan. Les paramêtres de type Params sont
passés à cette méthode. Cette méthode retourne un résultat de type
Result (qui sera exploité par onPostExecute(Result))
❚ Cette méthode peut lancer publishProgress(Progress...)
qui permet de lancer onProgressUpdate(Progress...) dans la
UI Thread et mettre ainsi à jour l'IHM de l'application, tout en
continuant la tâche en arrière plan
❚ onPostExecute(Result) est lancée après la fin de la tâche en
arrière plan. Cette méthode reçoit le paramêtre de type Result
qu'a renvoyé doInBackground(Params...)

© JMF (Tous droits réservés) 135


Utilisation de
AsyncTask<Params, Progress, Result>
❚ Pour utiliser cette classe, il faut la sous classer, construire une instance de
cette sous-classe et lancer la méthode execute(Params ...) sur cette
instance
❚ Il faut au moins redéfinir la méthode doInBackground(Params...) (bon
sens !)
❚ La sous classe créée est souvent une sous-classe interne à une méthode
❚ La création de l'instance de cette sous classe doit être faite dans la UI
Thread et execute(Params ...) doit être lancée sur cette instance une
seule fois dans la UI Thread
❚ Les méthodes onPreExecute(), doInBackground(Params...),
onProgressUpdate(Progress...), onPostExecute(Result) ne
doivent pas être lancées explicitement : c'est la méthode execute() qui
déclenche le tout

© JMF (Tous droits réservés) 136


Exemple de code de
AsyncTask<Params, Progress, Result>
class ChargementDesStationsTache extends AsyncTask<String, String, String> {
protected void onPreExecute() {
progress = ProgressDialog.show(ListingDesStationsActivity.this,
getResources().getString(R.string.app_name),
getResources().getString(R.string.chargement_message),
true);
}
protected String doInBackground(String ... urls) {
// charger les stations
try {
sp = new StationsParser(getBaseContext());
} catch (Exception e) { e.printStackTrace(); }
leStationsAdapter = new StationsAdapter(getBaseContext(),
ListingDesStationsActivity.this, sp.getArrList()) ;
return null;
}
protected void onProgressUpdate(String... aAfficher) { }
protected void onPostExecute(String result) {
// arréter le progressDialog
progress.dismiss();
// mettre à jour la ListView des stations
listing.setAdapter(leStationsAdapter);
}
}
new ChargementDesStationsTache().execute();

© JMF (Tous droits réservés) 137


Configuration de
l'AndroidManifest.xml
❚ Comme l'application demande à utilliser l'internet, il faut l'indiquer dans le
fichier AndroidManifest.xml par :
<uses-permission android:name="android.permission.INTERNET" />
fils de l'élément manifest
❚ Comme l'application va utiliser une nouvelle Activity, il faut l'indiquer dans
le fichier AndroidManifest.xml par :
<activity android:name=".ListingDesStationsActivity" />
fils de l'élément application
❚ Par exemple : <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=... >
...
<uses-permission android:name="android.permission.INTERNET" />
<application ...
...
<activity android:name=".ListingDesStationsActivity" />
</application>
</manifest>

© JMF (Tous droits réservés) 138


Fin

© JMF (Tous droits réservés) 139