Vous êtes sur la page 1sur 97

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 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) 4
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) 5


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) 6


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) 7
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) 8


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) 9


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) 10


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

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


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) 12


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) 13


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) 14


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) 15
❚ 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) 16


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) 17


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) 18
element.html
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) 19
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) 20
Chapitre 2

Développement Android

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


Un premier projet :
Hello World

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


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) 23


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) 24


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) 25
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) 26
❚ 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) 27


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) 28
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) 29
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) 30
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) 31


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) 32


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) 33


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) 34


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) 35


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) 36


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) 37
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) 38


SMBXXX : Programmation Android
Le manifeste
Le manifeste

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


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) 40


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) 41


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

• Apparaît alors votre application Android :

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


SMBXXX : Programmation Android
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) 43


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) 44
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) 45
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) 46


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) 47


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) 48
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) 49
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) 50


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) 51
Bibliographie pour ce
chapitre
❚ Pour ce chapitre
http://developer.android.com/guide/components/fundamentals.html

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


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) 53


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

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

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


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) 55


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) 56


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) 57


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) 58


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) 59


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) 60


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) 61
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) 62


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) 63
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) 64
}
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) 65


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) 66
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.)

67
strings.xml
main.xml

68
SMBXXX : Programmation Android
strings.xml
strings.xml

69
SMBXXX : Programmation Android
strings.xml
AndroidManifest.xml

70
SMBXXX : Programmation Android
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) 71
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) 72


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) 73
"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) 74
"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) 75


"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) 76
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) 77
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) 78
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) 79


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) 80
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) 82


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) 83


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) 84


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) 85
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) 86


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) 87
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) 88


La "UI Thread" (2/2)
❚ Donc, 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) 89


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) 90


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é avant le lancement de la tâche
d'arrière plan

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


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) 92


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) 93


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) 94


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) 95


Exercice
❚ Ecrire une activité contenant une ListView alimentée par des
données se trouvant à une URL

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


Fin

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

Vous aimerez peut-être aussi