Cours de base avec exemples pour apprendre à créer une application Android


Télécharger Cours de base avec exemples pour apprendre à créer une application Android

★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Télécharger aussi :


 

 

Table des matières

I.        Les bases indispensables à toute application                                                          12

1.   L’univers Android 13

1.1.    Lacréationd’Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

1.2.    Laphilosophieetlesavantagesd’Android . . . . . . . . . . . . . . . . . . . . . 14

1.3.    Lesdifficultésdudéveloppementpourdessystèmesembarqués . . . . . . . . . . 16

1.4.    LelangageJava . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.4.1.    Lesvariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.4.2.    L’héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

1.4.3.    Lacompilationetl’exécution . . . . . . . . . . . . . . . . . . . . . . . . 21

1.5.    Enrésumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.   Installation et configuration des outils  22

2.1.    Conditionsinitiales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.2.    LeJavaDevelopmentKit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.3.    Eclipse,l’ADTetleSDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.4.    L’émulateurdetéléphone:AndroidVirtualDevice . . . . . . . . . . . . . . . . 29

2.5.    Testetconfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

2.6.    Configurationduvraiterminal . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

2.6.1.    Configurationduterminal . . . . . . . . . . . . . . . . . . . . . . . . . . 38

2.6.2.    PourlesutilisateursdeWindows . . . . . . . . . . . . . . . . . . . . . . 39

2.6.3.    PourlesutilisateursdeMac . . . . . . . . . . . . . . . . . . . . . . . . . 39

2.6.4.    PourlesutilisateursdeLinux . . . . . . . . . . . . . . . . . . . . . . . . 39

2.6.5.    Etaprès? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

3.   Votre première application        49

3.1.    Activitéetvue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

3.1.1.    Qu’est-cequ’uneactivité? . . . . . . . . . . . . . . . . . . . . . . . . . . 49

3.1.2.    Étatsd’uneactivité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

3.1.3.    Cycledevied’uneactivité . . . . . . . . . . . . . . . . . . . . . . . . . . 52

3.2.    Créationd’unprojet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

3.3.    Unnon-Helloworld! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

3.4.    Lancementdel’application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

4.   Les ressources      69

4.1.    LeformatXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

4.1.1.    Leslangagesdebalisage . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

4.1.2.    LasyntaxeXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

4.2.    Lesdifférentstypesderessources . . . . . . . . . . . . . . . . . . . . . . . . . . 72

4.3.    L’organisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

4.3.1.    Exemplesetrèglesàsuivre . . . . . . . . . . . . . . . . . . . . . . . . . 77

4.3.2.    Mesrecommandations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

4.4.    AjouterunfichieravecEclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

4.4.1.    Petitexercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.5.    Récupéreruneressource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.5.1.    LaclasseR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.5.2.    Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

4.5.3.    Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

II. Création d’interfaces graphiques                                                                                       90

5.   Constitution des interfaces graphiques 91

5.1.    L’interfaced’Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5.1.1.    Présentationdel’outil . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

5.1.2.    Utilisation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

5.2.    Règlesgénéralessurlesvues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

5.2.1.    Différenciationentreunlayoutetunwidget . . . . . . . . . . . . . . . . 98

5.2.2.    Attributsencommun . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

5.3.    Identifieretrécupérerdesvues . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

5.3.1.    Identification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

5.3.2.    InstanciationdesobjetsXML . . . . . . . . . . . . . . . . . . . . . . . . 104

6.   Les widgets les plus simples        108

6.1.    Leswidgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

6.1.1.    TextView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

6.1.2.    EditText . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

6.1.3.    Button. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

6.1.4.    CheckBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

6.1.5.    RadioButtonetRadioGroup. . . . . . . . . . . . . . . . . . . . . . . . . 112

6.1.6.    Utiliserladocumentationpourtrouveruneinformation. . . . . . . . . . 113

6.1.7.    Calculdel’IMC-Partie1 . . . . . . . . . . . . . . . . . . . . . . . . . . 117

6.2.    Gérerlesévènementssurleswidgets . . . . . . . . . . . . . . . . . . . . . . . . 120

6.2.1.    Leslisteners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

6.2.2.    Parhéritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

6.2.3.    Paruneclasseanonyme . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

6.2.4.    Parunattribut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

6.2.5.    Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

6.2.6.    Calculdel’IMC-Partie2 . . . . . . . . . . . . . . . . . . . . . . . . . . 128

7.   Organiser son interface avec des layouts           134

7.1.    LinearLayout:placerlesélémentssuruneligne . . . . . . . . . . . . . . . . . . 134

7.1.1.    Calculdel’IMC-Partie3.1 . . . . . . . . . . . . . . . . . . . . . . . . . 142

7.2.    RelativeLayout:placerlesélémentslesunsenfonctiondesautres . . . . . . . . 145

7.2.1.    Calculdel’IMC-Partie3.2 . . . . . . . . . . . . . . . . . . . . . . . . . 150

7.3.    TableLayout:placerlesélémentscommedansuntableau. . . . . . . . . . . . . 153

7.3.1.    Calculdel’IMC-Partie3.3 . . . . . . . . . . . . . . . . . . . . . . . . . 157

7.4.    FrameLayout:unlayoutunpeuspécial . . . . . . . . . . . . . . . . . . . . . . 159

7.5.    ScrollView:fairedéfilerlecontenud’unevue . . . . . . . . . . . . . . . . . . . 160

8.   Les autres ressources       161

8.1.    Aspectgénéraldesfichiersderessources . . . . . . . . . . . . . . . . . . . . . . 161

8.1.1.    Référenceàuneressource . . . . . . . . . . . . . . . . . . . . . . . . . . 164

8.2.    Leschaînesdecaractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

8.2.1.    Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

8.2.2.    Formaterdeschaînesdecaractères . . . . . . . . . . . . . . . . . . . . . 166

8.3.    Lesdrawables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

8.3.1.    Lesimagesmatricielles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

8.3.2.    Lesimagesextensibles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

8.4.    Lesstyles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173

8.5.    Lesanimations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

8.5.1.    DéfinitionenXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

8.5.2.    Undernierraffinement:l’interpolation . . . . . . . . . . . . . . . . . . . 179

8.5.3.    L’évènementieldanslesanimations . . . . . . . . . . . . . . . . . . . . . 181

9.   TP : un bloc-notes 182

9.1.    Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182

9.1.1.    Lemenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

9.1.2.    L’éditeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

9.2.    Spécificationstechniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

9.2.1.    Fichiersàutiliser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

9.2.2.    LeHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

9.2.3.    L’animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

9.2.4.    Liens. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

9.3.    DéboguerdesapplicationsAndroid . . . . . . . . . . . . . . . . . . . . . . . . . 189

9.4.    Masolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

9.4.1.    Lesressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

9.4.2.    Lecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

9.5.    Objectifssecondaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206

9.5.1.    Boutonsàplusieursétats . . . . . . . . . . . . . . . . . . . . . . . . . . 206

9.5.2.    Internationalisation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

9.5.3.    Gérercorrectementlemodepaysage . . . . . . . . . . . . . . . . . . . . 207

widgets plus avancés et des boîtes de dialogue                                                                   208

10.  1.Leslistesetlesadaptateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

10.1.1.   Lesadaptateurs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209

10.1.2.   Lesvuesresponsablesdel’affichagedeslistes:lesAdapterView . . . . . 214

10.2.Pluscomplexe:lesadaptateurspersonnalisés . . . . . . . . . . . . . . . . . . . 224

10.2.1. Amélioration:lepattern ViewHolder . . . . . . . . . . . . . . . . . . . . 228

10.3.Lesboîtesdedialogue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

10.3.1.   Généralités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230

10.3.2.   Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

10.3.3.   Laboîtededialoguedebase. . . . . . . . . . . . . . . . . . . . . . . . . 233

10.3.4.   AlertDialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

10.4.Lesautreswidgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

10.4.1.   Dateetheure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

10.4.2.   Afficherdesimages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238

10.4.3.   Autocomplétion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240

11.Gestion des menus de l’application                                                                                             242

11.  1.Menud’options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242

11.1.1.   Créerunmenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242

11.1.2.   Réagirauxclics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246

11.2.Menucontextuel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247

11.  3.Maintenantquevousmaîtrisezlesmenus,oublieztout . . . . . . . . . . . . . . 247

éation de vues personnalisées                                                                                                  249

12.  1.Règlesavancéesconcernantlesvues . . . . . . . . . . . . . . . . . . . . . . . . . 249

12.1.1.   Dimensionsetplacementd’unevue . . . . . . . . . . . . . . . . . . . . . 249

12.1.2.   Ledessin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252

12.  2.Méthode1:àpartird’unevuepréexistante . . . . . . . . . . . . . . . . . . . . 253

12.3.Méthode2:unevuecomposite . . . . . . . . . . . . . . . . . . . . . . . . . . . 255

12.4.Méthode3:créerunevueenpartantdezéro . . . . . . . . . . . . . . . . . . . 256

12.4.1.   Laconstructionprogrammatique . . . . . . . . . . . . . . . . . . . . . . 256

12.4.2.   Laconstructionparinflation . . . . . . . . . . . . . . . . . . . . . . . . 257

12.4.3.   onMeasure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

12.4.4.   onDraw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258

III.   Vers des applications plus complexes  260

éambule : quelques concepts avancés                                                                                     261

13.  1.Généralitéssurlenœud<manifest> . . . . . . . . . . . . . . . . . . . . . . . . 261

13.1.1.   <manifest> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261

13.1.2.   <uses-sdk> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262

13.1.3.   <uses-feature> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263

13.1.4.   <supports-screens> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264

œud<application> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264

13.2.1.   Lesthèmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264

13.2.2.   <activity> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

13.3.Lespermissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266

13.3.1.   Utiliserlespermissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266

13.3.2.   Créersespermissions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

13.4.Gérercorrectementlecycledesactivités . . . . . . . . . . . . . . . . . . . . . . 267

13.4.1.   Souslesfeuxdelarampe:périodesuspendue . . . . . . . . . . . . . . . 269

13.4.2.   Convoquerleplanetl’arrière-plan:périodearrêtée . . . . . . . . . . . . 269

13.4.3.   Delanaissanceàlamort . . . . . . . . . . . . . . . . . . . . . . . . . . 270

13.4.4.   L’échangeéquivalent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271

13.  5.Gérerlechangementdeconfiguration . . . . . . . . . . . . . . . . . . . . . . . . 272

communication entre composants                                                                                          277

14.  1.Aspecttechnique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

14.1.1. Injecterdesdonnéesdansunintent . . . . . . . . . . . . . . . . . . . . . 279

14.  2.Lesintentsexplicites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280

14.2.1.   Sansretour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281

14.2.2.   Avecretour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282

14.3.Lesintentsimplicites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284

14.3.1.   Lesdonnées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284

14.3.2.   L’action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

ésolutiondesintents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

14.4.1.   L’action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

14.4.2.   Lacatégorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

14.4.3.   Lesdonnées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

14.5.Pourallerplusloin:navigationentredesactivités. . . . . . . . . . . . . . . . . 291

14.5.1.   Modifierl’activitédansleManifest . . . . . . . . . . . . . . . . . . . . . 292

14.5.2.   Aveclesintents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

14.  6.Pourallerplusloin:diffuserdesintents . . . . . . . . . . . . . . . . . . . . . . 294

stockage de données                                                                                                                298

15.  1.Préférencespartagées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298

15.1.1.   Lesdonnéespartagées . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298

15.1.2.   Despréférencesprêtesàl’emploi . . . . . . . . . . . . . . . . . . . . . . 300

15.  2.Manipulationdesfichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305

15.2.1.   Rappelssurl’écritureetlalecturedefichiers. . . . . . . . . . . . . . . . 305

15.2.2.   Eninterne. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305

15.2.3.   Enexterne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306

15.2.4.   Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307

: un explorateur de fichiers                                                                                                     309

16.  1.Objectifs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309

16.1.1.   Contenud’unrépertoire . . . . . . . . . . . . . . . . . . . . . . . . . . . 309

16.1.2.   Navigationentrelesrépertoires . . . . . . . . . . . . . . . . . . . . . . . 310

16.1.3.   Préférences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310

16.1.4.   Actionsurlesfichiers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312

écificationstechniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313

16.2.1.   Activitéprincipale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313

16.2.2.   Préférences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315

16.2.3.   Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316

16.2.4.   Navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316

16.2.5.   Visualiserunfichier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316

16.3.Masolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

16.3.1.   Interfacegraphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

16.3.2.   ChoisirunecouleuravecColorPickerPreferenceDialog . . . . . . . . . . . 317

16.3.3.   L’activitéprincipale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318

éliorationsenvisageables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319

16.4.1.   Quandlalisteestvideoulepériphériqueexterneestindisponible . . . . 319

16.4.2.   DétectionautomatiquedutypeMIME . . . . . . . . . . . . . . . . . . . 319

16.4.3.   Détecterleschangementsd’étatdupériphériqueexterne . . . . . . . . . 320

bases de données                                                                                                                   321

17.  1.Généralités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321

17.1.1.   Surlesbasesdedonnées . . . . . . . . . . . . . . . . . . . . . . . . . . . 321

17.1.2.   SurSQLite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323

17.1.3.   SurSQLitepourAndroid . . . . . . . . . . . . . . . . . . . . . . . . . . 323

éationetmiseàjour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324

érationsusuelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325

17.3.1.   Récupérerlabase. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325

17.3.2.   Réfléchir,puisagir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326

17.3.3.   Ajouter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327

17.3.4.   Supprimer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328

17.3.5.   Miseàjour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329

17.3.6.   Sélection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329

17.4.Lescurseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330

17.4.1.   Manipulerlescurseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330

17.4.2.   L’adaptateurpourlescurseurs . . . . . . . . . . . . . . . . . . . . . . . 331

IV.  Concepts avancés     333

travail en arrière-plan                                                                                                              334

18.  1.LagestiondumultitâcheparAndroid. . . . . . . . . . . . . . . . . . . . . . . . 334

18.1.1.   Processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335

18.1.2.   Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336

18.2.Gérercorrectementlesthreadssimples . . . . . . . . . . . . . . . . . . . . . . . 336

18.2.1.   Labase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336

18.2.2.   Lesmessagesetleshandlers . . . . . . . . . . . . . . . . . . . . . . . . . 338

18.2.3.   Application:unebarredeprogression . . . . . . . . . . . . . . . . . . . 339

18.2.4.   Sécurisersesthreads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341

18.3.AsyncTask. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342

18.3.1. Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344

services                                                                                                                                    346

19.  1.Qu’est-cequ’unservice? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346

19.2.Gérerlecycledevied’unservice . . . . . . . . . . . . . . . . . . . . . . . . . . 347

19.2.1.   Lesserviceslocaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348

19.2.2.   Lesservicesdistants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352

éerunservice. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353

19.3.1.   DansleManifest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353

19.3.2.   EnJava . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353

19.4.Lesnotificationsetservicesdepremierplan . . . . . . . . . . . . . . . . . . . . 354

19.4.1.   Distribuerdesautorisations . . . . . . . . . . . . . . . . . . . . . . . . . 354

19.4.2.   Notifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355

19.4.3.   Lesservicesdepremierplan . . . . . . . . . . . . . . . . . . . . . . . . . 358

19.5.Pourallerplusloin:lesalarmes . . . . . . . . . . . . . . . . . . . . . . . . . . . 359

19.5.1.   Lesalarmesuniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359

19.5.2.   Lesalarmesrécurrentes . . . . . . . . . . . . . . . . . . . . . . . . . . . 360

19.5.3.   Annulerunealarme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361

partage de contenus entre applications                                                                                  362

20.  1.Côtéclient:accéderàdesfournisseurs . . . . . . . . . . . . . . . . . . . . . . . 362

20.1.1.   Accéderàunfournisseur . . . . . . . . . . . . . . . . . . . . . . . . . . . 363

20.1.2.   L’URIdesfournisseursdecontenu . . . . . . . . . . . . . . . . . . . . . 364

20.1.3.   Effectuerdesopérationssurunfournisseurdecontenu . . . . . . . . . . 366

éerunfournisseur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

20.2.1.   L’URI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369

20.2.2.   LetypeMIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370

20.2.3.   Lestockage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371

20.2.4.   LeManifest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371

20.2.5.   Laprogrammation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371

éer un AppWidget                                                                                                                     375

21.  1.L’interfacegraphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375

21.2.Définirlespropriétés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377

21.3.Lecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377

21.3.1.   Lereceiver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377

21.3.2.   L’activitédeconfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . 379

21.4.Déclarerl’AppWidgetdansleManifest . . . . . . . . . . . . . . . . . . . . . . . 379

21.5.Application:unAppWidgetpouraccéderauxtutorielsduSiteduZéro . . . . . 380

21.5.1.   Résultatattendu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380

21.5.2.   Aspecttechnique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380

21.5.3.   Masolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

V.     Exploiter les fonctionnalités d’Android           383

connectivité réseau                                                                                                                  384

22.  1.Surveillerleréseau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384

22.2.AfficherdespagesWeb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385

22.2.1.   ChargerdirectementduHTML . . . . . . . . . . . . . . . . . . . . . . . 385

22.2.2.   Chargerunepagesurinternet . . . . . . . . . . . . . . . . . . . . . . . . 386

22.3.EffectuerdesrequêtesHTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

22.3.1.   RappelssurleprotocoleHTTP . . . . . . . . . . . . . . . . . . . . . . . 388

22.3.2.   LeHTTPsousAndroid . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

23.Apprenez à dessiner                                                                                                                      391

23.  1.Latoile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391

23.1.1.   Latoile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

23.1.2.   Lepinceau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

23.1.3.   Lepeintre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

23.2.Affichernotretoile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394

23.2.1.   Surunevuestandard . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394

23.2.2.   Surunesurfacedédiéeàcetravail . . . . . . . . . . . . . . . . . . . . . 394

localisation et les cartes                                                                                                           397

24.  1.Lalocalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397

24.1.1.   Préambule. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397

24.1.2.   Lesfournisseursdeposition . . . . . . . . . . . . . . . . . . . . . . . . . 398

24.1.3.   Obtenirdesnotificationsdufournisseur . . . . . . . . . . . . . . . . . . 398

24.1.4.   Lesalertesdeproximité . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

24.2.Afficherdescartes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400

24.2.1.   ObteniruneclépourutiliserGoogleMaps . . . . . . . . . . . . . . . . . 401

24.2.2.   L’activitéquicontiendralacarte . . . . . . . . . . . . . . . . . . . . . . 402

24.2.3.   Lacarteenelle-même . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402

24.2.4.   Lecontrôleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

24.2.5.   Utiliserlescalquespourafficherdesinformationscomplémentaires. . . . 404

24.2.6.   Quelquescalquesspécifiques . . . . . . . . . . . . . . . . . . . . . . . . . 405

téléphonie                                                                                                                                 407

25.  1.Téléphoner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407

25.1.1.   Obtenirdesinformations. . . . . . . . . . . . . . . . . . . . . . . . . . . 407

25.1.2.   Téléphoner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409

25.2.EnvoyeretrecevoirdesSMSetMMS . . . . . . . . . . . . . . . . . . . . . . . . 409

25.2.1. L’envoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409

multimédia                                                                                                                               412

26.  1.Lelecteurmultimédia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412

26.1.1.   Oùtrouverdesfichiersmultimédia? . . . . . . . . . . . . . . . . . . . . 412

26.1.2.   Formatsdesfichiersquipeuventêtrelus . . . . . . . . . . . . . . . . . . 412

26.1.3.   Lelecteurmultimédia . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413

26.1.4.   Lalecturedevidéos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415

26.2.Enregistrement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416

26.2.1.   Enregistrementsonorestandard . . . . . . . . . . . . . . . . . . . . . . . 416

26.2.2.   Enregistrerdusonauformatbrut . . . . . . . . . . . . . . . . . . . . . 417

26.2.3.   Prendredesphotos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418

26.2.4.   Enregistrerdesvidéos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420

capteurs                                                                                                                                   423

27.  1.Lesdifférentscapteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423

érationsgénériques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425

27.2.1.   Demanderlaprésenced’uncapteur . . . . . . . . . . . . . . . . . . . . . 425

27.2.2.   Identifierlescapteurs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425

27.2.3.   Détectiondeschangementsdescapteurs . . . . . . . . . . . . . . . . . . 426

27.3.Lescapteursdemouvements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427

27.4.Lescapteursdeposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428

27.  5.Lescapteursenvironnementaux . . . . . . . . . . . . . . . . . . . . . . . . . . . 430

: un labyrinthe                                                                                                                          431

28.  1.Objectifs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431

28.  2.Spécificationstechniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432

28.2.1.   Organisationducode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432

28.2.2.   Lesmodèles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433

28.2.3.   Lemoteurgraphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434

28.2.4.   Lemoteurphysique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436

28.2.5.   Lelabyrinthe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437

28.3.Masolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438

28.3.1.   LeManifest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438

28.3.2.   Lesmodèles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438

28.3.3.   Lemoteurgraphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438

28.3.4.   Lemoteurphysique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439

28.3.5.   L’activité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439

éliorationsenvisageables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439

28.4.1.   Proposerplusieurslabyrinthes . . . . . . . . . . . . . . . . . . . . . . . . 439

28.4.2.   Ajouterdessons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440

VI.  Annexes           442

29.Publier et rentabiliser une application                                                                                        443

29.  1.Préparezvotreapplicationàunedistribution. . . . . . . . . . . . . . . . . . . . 443

29.1.1.   Modificationsetvérificationsd’usage . . . . . . . . . . . . . . . . . . . . 443

29.1.2.   Signerl’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446

29.2.Lesmoyensdedistribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450

29.2.1.   GooglePlay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450

29.2.2.   Lesapplications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451

29.2.3.   Informationssuruneapplication . . . . . . . . . . . . . . . . . . . . . . 454

29.2.4.   Lesautrestypesdedistribution . . . . . . . . . . . . . . . . . . . . . . . 457

29.3.Rentabilisezvotreapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457

29.3.1.   CréeruncomptemarchandpourGoogleCheckout . . . . . . . . . . . . 459

29.3.2.   Fairepayerl’application . . . . . . . . . . . . . . . . . . . . . . . . . . . 459

29.3.3.   Ajouterdelapublicité . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460

29.3.4.   Freemium:abonnementouventedeproduitsintégrés . . . . . . . . . . 462

30.L’architecture d’Android                                                                                                               463

30.  1.LenoyauLinux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463

30.2.Lemoteurd’exécutiond’Android . . . . . . . . . . . . . . . . . . . . . . . . . . 464

31.Remerciements                                                                                                                             467

Bonjour à tous et bienvenue dans le monde merveilleux du développement d’applications Android!

 

Figure 0.1.–Bugdroid,lamascotted’Android

Avec l’explosion des ventes de smartphones ces dernières années, Android a pris une place importantedanslaviequotidienne.Cesystèmed’exploitationpermetd’installerdesapplications detoutessortes:jeux,bureautique,multimédia,etc.Quediriez-vousdedéveloppervospropres applications pour Android, en les proposant au monde entier via le Play Store, le marché d’applicationsdeGoogle?Ehbienfigurez-vousquec’estjustementlebutdececours:vous apprendreàcréerdesapplicationspourAndroid!

Cependant,poursuivrececours,ilvousfaudraquelquesconnaissances:

— Les applications Android étant presque essentiellement codées en Java, il vous faut connaîtrecelangage.

— Connaîtreunminimumde SQL pourlesrequêtes.Sivousneconnaissezabsolumentrien enSQL,vouspourreztoutdemêmesuivrelecoursdanssonintégralité,maisconstituer votreproprebasededonnéessansthéoriemesemblerisqué.

— Et enfin, être un minimum autonome en informatique : vous devez par exemple être capablesd’installerEclipsetoutseul(vousvoyez,jenevousdemandepaslalune).

Riendebienméchant,commevouspouvezlevoir.MaisledéveloppementpourAndroidestdéjà assezcompletcommecela,ceseraitbientroplongderevenirsurcesbases-là.Cecoursdébutera cependantendouceuretvousprésenterad’abordlesbasesessentiellespourledéveloppement Androidafinquevouspuissiezeffectuerdesapplicationssimplesetcompatiblesaveclamajorité desterminaux.Puisnousverronstoutcequevousavezbesoindesavoirafindecréerdebelles interfacesgraphiques;etenfinonaborderadesnotionsplusavancéesafind’exploiterlesmultiples facettes que présente Android, dont les différentes bibliothèques de fonctions permettant de mettreàprofitlescapacitésmatériellesdesappareils.

Àlafindececours,vousserezcapablesderéaliserdesjeux,desapplicationsdegéolocalisation, un navigateur Web, des applications sociales, et j’en passe. En fait, le seul frein sera votre imagination!

 

Figure 0.2.–OpenHandsetAlliance

 

Figure 0.3.–Installationdesversionsd’Android

 

Figure 0.4.–LeblocnotesquenousallonsdévelopperdansunTP


Première partie Les bases indispensables à toute application

1. L’univers Android

Danscetoutpremierchapitre,jevaisvousprésentercequej’appellel’«universAndroid»!Le système,danssagenèse,partd’uneidéedebasesimple,ettrèsvitesonsuccèsfuttelqu’ilasu devenirindispensablepourcertainsconstructeursetutilisateurs,enparticulierdanslasphère delatéléphoniemobile.Nousallonsrapidementrevenirsurcetteaventureetsurlaphilosophie d’Android,puisjerappellerailesbasesdelaprogrammationenJava,pourceuxquiauraient besoind’unepetitepiqûrederappel

1.1. La création d’Android

QuandonpenseàAndroid,onpenseimmédiatementàGoogle,etpourtantilfautsavoirque cettemultinationalen’estpasàl’initiativeduprojet.D’ailleurs,ellen’estmêmepaslaseule àcontribueràpleintempsàsonévolution.Àl’origine,«Android»étaitlenomd’unePME américaine, créée en 2003 puis rachetée par Google en 2005, qui avait la ferme intention de s’introduiresurlemarchédesproduitsmobiles.Lagageure,derrièreAndroid,étaitdedévelopper un système d’exploitation mobile plus intelligent, qui ne se contenterait pas uniquement de permettred’envoyerdesSMSettransmettredesappels,maisquidevaitpermettreàl’utilisateur d’interagir avec son environnement (notamment avec son emplacement géographique). C’est pourquoi,contrairementàunecroyancepopulaire,iln’estpaspossiblededirequ’Androidest uneréponsedeGoogleàl’iPhoned’Apple,puisquel’existencedecederniern’aétérévéléeque deuxannéesplustard.

C’est en 2007 que la situation prit une autre tournure. À cette époque, chaque constructeur équipaitsontéléphoned’unsystèmed’exploitationpropriétaire.Chaquetéléphoneavaitainsi unsystèmeplusoumoinsdifférent.Cesystèmeentravaitlapossibilitédedévelopperfacilement desapplicationsquis’adapteraientàtouslestéléphones,puisquelabaseétaitcomplètement différente. Un développeur était plutôt spécialisé dans un système particulier et il devait se contenterdelangagesdebasniveauxcommeleCouleC++.Deplus,lesconstructeursfaisaient ensortedelivrerdesbibliothèquesdedéveloppementtrèsréduitesdemanièreàdissimulerleurs secretsdefabrication.Enjanvier2007,Appledévoilaitl’iPhone,untéléphonetoutsimplement révolutionnaire pour l’époque. L’annonce est un désastre pour les autres constructeurs, qui doivent s’aligner sur cette nouvelle concurrence. Le problème étant que pour atteindre le niveaud’iOS(iPhoneOS),ilauraitfalludesannéesderechercheetdéveloppementàchaque constructeur

C’estpourquoiestcrééeennovembredel’année2007l’Open Handset Alliance(quej’appellerai désormais par son sigle OHA), et qui comptait à sa création 35 entreprises évoluant dans l’univers du mobile, dont Google. Cette alliance a pour but de développer un système open source (c’est-à-diredontlessourcessontdisponibleslibrementsurinternet)pourl’exploitation surmobileetainsiconcurrencerlessystèmespropriétaires,parexempleWindowsMobileetiOS.

CetteallianceapourlogicielvedetteAndroid,maisilnes’agitpasdesaseuleactivité.

L’OHAcompteàl’heureactuelle80membres.

 

Figure 1.1.–Lelogodel’OHA,uneorganisationquichercheàdévelopperdesstandardsopen sourcepourlesappareilsmobiles

Depuis sa création, la popularité d’Android a toujours été croissante. C’est au quatrième trimestre2010qu’Androiddevientlesystèmed’exploitationmobileleplusutiliséaumonde, devançant Symbian (le système d’exploitation de Nokia avant qu’ils optent pour Windows Phone).Désormais,onleretrouvenonseulementdanslestablettesetsmartphones,maisaussi danslestéléviseurs,lesconsolesdejeux,lesappareilsphotos,etc.

1.2. La philosophie et les avantages d’Android

1.2.0.1. Opensource

LecontratdelicencepourAndroidrespectelesprincipesdel’open source,c’est-à-direquevous pouvezàtoutmomenttéléchargerlessourcesetlesmodifierselonvosgoûts!Bon,jenevous lerecommandevraimentpas,àmoinsquevoussachiezcequevousfaites Notezaupassage qu’Androidutilisedesbibliothèquesopen source puissantes,commeparexempleSQLitepour lesbasesdedonnéesetOpenGLpourlagestiond’images2Det3D.


1.2.0.2. Gratuit (ou presque)

Androidestgratuit,autantpourvousquepourlesconstructeurs.S’ilvousprenaitl’enviede produire votre propre téléphone sous Android, alors vous n’auriez même pas à ouvrir votre porte-monnaie(maisboncouragepourtoutletravailàfournir!).Enrevanche,pourpostervos applicationssurlePlayStore,ilvousencoûteralamodiquesommede25$.Ces25$permettent depublierautantd’applicationsquevouslesouhaitez,àvie!

1.2.0.3. Facile à développer

Toutes les API mises à disposition facilitent et accélèrent grandement le travail. Ces APIs sont très complètes et très faciles d’accès. De manière un peu caricaturale, on peut dire que vous pouvez envoyer un SMS en seulement deux lignes de code (concrètement, il y a un peu d’enrobageautourdececode,maispastellement). i

Une API, ou « interface de programmation » en français, est un ensemble de règles à suivrepourpouvoirdialogueravecd’autresapplications.DanslecasdeGoogleAPI,il permetenparticulierdecommuniqueravecGoogleMaps.

1.2.0.4. Facile à vendre

LePlay Store (anciennementAndroid Market)estuneplateformeimmenseettrèsvisitée;c’est doncunemined’opportunitéspourquiconquepossèdeuneidéeoriginaleouutile.

1.2.0.5. Flexible

Le système est extrêmement portable, il s’adapte à beaucoup de structures différentes. Les smartphones, les tablettes, la présence ou l’absence de clavier ou de trackball, différents processeurs Ontrouvemêmedesfoursàmicro-ondesquifonctionnentàl’aided’Android!Non seulementc’estuneimmensechanced’avoirautantd’opportunités,maisenplusAndroidest construitdemanièreàfaciliterledéveloppementetladistributionenfonctiondescomposants en présence dans le terminal (si votre application nécessite d’utiliser le Bluetooth, seuls les terminauxéquipésdeBluetoothpourrontlavoirsurlePlayStore).

1.2.0.6. Ingénieux

L’architectured’Androidestinspiréeparlesapplicationscomposites,etencourageparailleurs leurdéveloppement.Cesapplicationssetrouventessentiellementsurinternetetleurprincipe est que vous pouvez combiner plusieurs composants totalement différents pour obtenir un résultatsurpuissant.Parexemple,sioncombinel’appareilphotoavecleGPS,onpeutposter lescoordonnéesGPSdesphotosprises.

1.3. Les difficultés du développement pour des systèmes embarqués

Il existe certaines contraintes pour le développement Android, qui ne s’appliquent pas au développementhabituel!

Prenons un cas concret : la mémoire RAM est un composant matériel indispensable. Quand vouslancezunlogiciel,votresystèmed’exploitationluiréservedelamémoirepourqu’ilpuisse créerdesvariables,tellesquedestableaux,deslistes,etc.Ainsi,surmonordinateur,j’ai4Go deRAM,alorsquejen’aique512Mosurmontéléphone,cequisignifiequej’enaihuitfois moins.Jepeuxdonclancermoinsdelogicielsàlafoisetceslogicielsdoiventfaireensortede réservermoinsdemémoire.C’estpourquoivotretéléphoneestditlimité,ildoitsupporterdes contraintesquifontdoucementsourirevotreordinateur.

Voicilesprincipalescontraintesàprendreencomptequandondéveloppepourunenvironnement mobile:

— Ilfautpouvoirinteragiravecunsystèmecompletsansl’interrompre.Androidfaitdes chosespendantquevotreapplicationestutilisée,ilreçoitdesSMSetdesappels,entre autres.Ilfautrespecterunecertaineprioritédansl’exécutiondestâèrement, vousallezbloquerlesappelsdel’utilisateurpourqu’ilpuisseterminersapartiedevotre jeudesudoku?

— Commejel’aidéjàdit,lesystèmen’estpasaussipuissantqu’unordinateurclassique, il faudra exploiter tous les outils fournis afin de débusquer les portions de code qui nécessitentdesoptimisations.

— La taille de l’écran est réduite, et il existe par ailleurs plusieurs tailles et résolutions différentes. Votre interface graphique doit s’adapter à toutes les tailles et toutes les résolutions,ouvousrisquezdelaisserdecôtéunbonnombred’utilisateurs.

— Autre chose qui est directement lié, les interfaces tactiles sont peu pratiques en cas d’utilisationavecunstyletet/oupeuprécisesencasd’utilisationaveclesdoigts,d’oùdes contraintesliéesàlaprogrammationévénementielleplusrigides.Eneffet,ilestpossible quel’èssouvents’iladegrosdoigts.

— Enfin,enplusd’avoirunevariétéauniveaudelatailledel’écran,onaaussiunevariété au niveau de la langue, des composants matériels présents et des versions d’Android. Ilyaunevariabilitéentrechaquetéléphoneetmêmeparfoisentrecertainstéléphones identiques.C’estuntravailenplusàprendreencompte.

Les conséquences de telles négligences peuvent être terribles pour l’utilisateur. Saturez le processeuretilnepourraplusrienfaireexceptéredémarrer!Fairecrasheruneapplicationne feraengénéralpascomplètementcrasherlesystème,cependantilpourraitbiens’interrompre quelquestempsetirriterprofondémentl’utilisateur.

Ilfautbiencomprendrequedansleparadigmedelaprogrammationclassiquevousêtesdans votrepropremondeetvousn’avezvraimentpasgrand-choseàfairedurestedel’universdans lequelvousévoluez,alorsquelàvousfaitespartied’unsystèmefragilequiévoluesansanicroche tantquevousn’intervenezpas.Votrebutestdefournirdesfonctionnalitésdeplusàcesystème etfaireensortedenepasleperturber.

Bon, cela paraît très alarmiste dit comme ça, Android a déjà anticipé la plupart des âneries que vous commettrez et a pris des dispositions pour éviter des catastrophes qui conduiront aublocagetotaldutéléphone.Sivousêtesuntantinetcurieux,jevousinviteàlirel’annexe sur l’architecture d’Android pour comprendre un peu pourquoi il faut être un barbare pour vraimentréussiràsaturerlesystème.

1.4. Le langage Java

CettepetitesectionpermettraàceuxfâchésavecleJavadeseremettreunpeudanslebainet surtoutderéviserlevocabulairedebase.Notezqu’ilnes’agitqued’unrappel,ilestconseillé deconnaîtrelaprogrammationenJavaauparavant;jenefaisiciquerappelerquelquesnotions de base pour vous rafraîchir la mémoire! Il ne s’agit absolument pas d’une introduction à la programmation.

1.4.1. Les variables

ra

dis

ca

rotte

 

ra

dis + ca

rotte

La seule chose qu’un programme sait faire, c’est des calculs. Il arrive qu’on puisse lui faire afficher des formes et des couleurs, mais pas toujours. Pour faire des calculs, on a besoin de variables.Cesvariablespermettentdeconserverdesinformationsaveclesquellesonvapouvoir fairedesopérations.Ainsi,onpeutavoirunevariablequivaudra4pourindiquerqu’ona quatreradis.Sionaunevariable           quivaut2,onpeutfairelecalcul demanièreàpouvoirdéduirequ’onasixlégumes.

1.4.1.1. Les primitives

boo

lean

EnJava,ilexistedeuxtypesdevariable.Lepremiertypes’appelleles primitives.Cesprimitives permettentderetenirdesinformationssimplestellesquedesnombressansvirgule(auquelcas lavariableestunentier,int),deschiffresàvirgule(desréels,float)oudesbooléens(variable quinepeutvaloirquevrai (true)oufaux (false),avecles).

 

1.4.1.2. Les objets

vi

tesse

car

ros

se

rie

Lesecondtype,cesontles objets.Eneffet,àl’opposédesprimitives(variablessimples),les objetssontdesvariablescompliquées.Enfait,uneprimitivenepeutcontenirqu’uneinformation, parexemplelavaleurd’unnombre;tandisqu’unobjetestconstituéd’uneouplusieursautres variables,etparconséquentd’uneouplusieursvaleurs.Ainsi,unobjetpeutlui-mêmecontenirun objet!Unobjetpeutreprésenterabsolumentcequ’onveut:unechaise,unevoiture,unconcept philosophique,uneformulemathématique,etc.Parexemple,pourreprésenterunevoiture,je créeraiunobjetquicontientunevariablerouequivaudra4,unevariablequivariera enfonctiondelavitesseetunevariablepourlacouleurdelacarrosserieetqui pourravaloir«rouge»,«bleu»,quesais-je!D’ailleurs,unevariablequireprésenteunecouleur? Çanepeutpasêtreuneprimitive,cen’estpasunevariablefacileça,unecouleur!Donccette variableseraaussiunobjet,cequisignifiequ’unobjetpeutcontenirdesprimitivesoud’autres objets.

Voi

ture

Mais dans le code, comment représenter un objet? Pour cela, il va falloir déclarer ce qu’on appelleune classe.Cetteclasseauraunnom,pournotrevoitureonpeutsimplementl’appeler ,commececi:

1       // On déclare une classe Voiture avec cette syntaxe

2       class Voiture {

3       // Et dedans on ajoute les attributs qu'on utilisera, par exemple le nombre de roues

4       int roue = 4;

5       // On ne connaît pas la vitesse, alors on ne la déclare pas

6       float vitesse;

7       // Et enfin la couleur, qui est représentée par une classe de nom

Couleur

8       Couleur carrosserie;

9       }

Lesvariablesainsiinséréesauseind’uneclassesontappeléesdes attributs.

Ilestpossiblededonnerdesinstructionsàcettevoiture,commed’accéléreroudes’arrê instructionss’appellentdes méthodes,parexemplepourfreiner:

 

Enrevanche,pourchangerdevitesse,ilfautquejedisesij’accélèreoudécélèreetdecombien la vitesse change. Ces deux valeurs données avant l’exécution de la méthode s’appellent des paramètres.Deplus,jeveuxquelaméthoderendeàlafindesonexécutionlanouvellevitesse. Cettevaleurrendueàlafindel’exécutiond’uneméthodes’appelleune valeur de retour.Par exemple:

1         // On dit ici que la méthode renvoie un float et qu'elle a besoin d'un float et d'un boolean pour s'exécuter

2         float changer_vitesse(float facteur_de_vitesse, boolean acceleration)

3         // S'il s'agit d'une accelération

4         if(acceleration == true) {

5         // On augmente la vitesse

6         vitesse = vitesse + facteur_de_vitesse;

7         }else {

 

Voi

ture

 

Voi

ture

Parmilesdifférentstypesdeméthode,ilexisteuntypeparticulierqu’onappelleles constructeurs.Cesconstructeurssontdesméthodesquiconstruisentl’objetdésigné exemple,leconstructeurdelaclasse renvoieunobjetdetype :

1       // Ce constructeur prend en paramètre la couleur de la carrosserie

2       Voiture(Couleur carros) {

3       // Quand on construit une voiture, elle a une vitesse nulle

4       vitesse = 0;

5       carrosserie = carros;

6       }

Onpeutensuiteconstruireunevoitureaveccettesyntaxe:

 

Construireunobjets’appellel’instanciation.

1.4.2. L’héritage

hi

cule

Ilexistecertainsobjetsdontl’instanciationn’auraitaucunsens.Parexemple,unobjetdetype n’existepasvraimentdansunjeudecourse.Enrevancheilestpossibled’avoirdes

véhiculesdecertainstypes,parexempledesvoituresoudesmotos.Sijeveuxunemoto,ilfaut qu’elleaitdeuxroueset,sij’instancieunevoiture,elledoitavoir4roues,maisdanslesdeux cas elles ont des roues. Dans les cas de ce genre, c’est-à-dire quand plusieurs classes ont des attributsencommun,onfaitappelàl’héritage.QuanduneclasseAhérited’uneclasseB,on ditquelaclasseAestla fille delaclasseBetquelaclasseBestle parent (oula superclasse) delaclasseA.

   

abs

tract

Lemot-clésignifiequ’uneclassenepeutêtreinstanciée. i

Une méthode peut aussi être abstract, auquel cas pas besoin d’écrire son corps. En revanche,touteslesclasseshéritantdelaclassequicontientcetteméthodedevrontdécrire uneimplémentationdecetteméthode.

Pourcontrôlerlescapacitésdesclassesàutiliserlesattributsetméthodeslesunesdesautres, onaaccèsàtroisniveauxd’accessibilité:

pu

blic

—,pourqu’unattributouuneméthodesoitaccessibleàtous.

pro

tec

ted

—,pourquelesélémentsnesoientaccessiblesqu’auxclassesfilles.

pri

vate

— Enfin,pourquelesélémentsnesoientaccessiblesàpersonnesicen’estlaclasse elle-même.

Ontrouveparexemple:

1       // Cette classe est accessible à tout le monde

2       public abstract class Vehicule {

3       // Cet attribut est accessible à toutes les filles de la classe

Vehicule

4       protected roue;

5

6       // Personne n'a accès à cette méthode.

7       abstract private void decelerer();

8       }

abs

tract

Enfin,ilexisteuntypedeclassemèreparticulier:les interfaces.Uneinterfaceestimpossible àinstancierettouteslesclassesfillesdecetteinterfacedevrontinstancierlesméthodesdecette interface—ellessonttoutesforcément.

 

1.4.3. La compilation et l’exécution

Votre programme est terminé et vous souhaitez le voir fonctionner, c’est tout à fait normal. Cependant,votreprogrammeneserapasimmédiatementcompréhensibleparl’ effet,pourqu’unprogrammefonctionne,ildoitd’abordpasserparuneétapede compilation, quiconsisteàtraduirevotrecodeJavaen bytecode.Danslecasd’Android,cebytecodesera ensuiteluparunlogicielquis’appellela machine virtuelle Dalvik.Cettemachinevirtuelle interprète les instructions bytecode et va les traduire en un autre langage que le processeur pourracomprendre,afindepouvoirexécutervotreprogramme.

 

1.5. En résumé

— Googlen’estpasleseulàl’initiativeduprojetAndroid.C’esten2007quel’OpenHandset Alliance(OHA)aétécrééetellecomptait35entreprisesàsesdébuts.

— La philosophie du système réside sur 6 points importants : il fallait qu’il soit open source,gratuitdanslamesuredupossible,facileàdévelopper,facileàvendre,flexibleet ingénieux.

— Il ne faut jamais perdre à l’esprit que vos smartphones sont (pour l’instant) moins puissantsetpossèdentmoinsdemémoirequevosordinateurs!

— Ilexisteuncertainnombredebonnespratiquesqu’ilfautabsolumentrespecterdansle développementdevosapplications.Sansquoi,l’utilisateurauratendanceàvouloirles désinstaller.

— Nebloquezjamaislesmartphone.N’oubliezpasqu’ilfaitaussiautrechoselorsque vousexécutezvosapplications.

— Optimisezvosalgorithmes:votresmartphonen’estpascomparableàvotreordinateur entermedeperformance.

— Adaptezvosinterfacesàtouslestypesd’écran:lesterminauxsontnombreux.

— Pensezvosinterfacespourlesdoigtsdel’utilisateurfinal.S’ilpossèdedesgrosdoigts etquevousfaitesdespetitsboutons,l’expérienceutilisateurenseraaltérée.

— Sipossible,testezvosapplicationssurunlargechoixdesmartphones.Ilexistedes variationsentrelesversions,lesconstructeursetsurtoutentrelesmatériels.

— UnebonnecompréhensiondulangageJavaestnécessairepoursuivrececours,etplus généralementpourdéveloppersurAndroid.


2. Installation et configuration des outils

Avantdepouvoirentrerdanslevifdusujet,nousallonsvérifierquevotreordinateurestcapable de supporter la charge du développement pour Android, puis, le cas échéant, on installera touslesprogrammesetcomposantsnécessaires.Vousaurezbesoindeplusde 1 Go pourtout installer.EtsivouspossédezunappareilsousAndroid,jevousmontreraicommentleconfigurer defaçonàpouvoirtravaillerdirectementavec.

Encoreunpeudepatience,leschosessérieusesdémarrerontdèsleprochainchapitre.

2.1. Conditions initiales

Demanièregénérale,n’importequelmatérielpermetdedéveloppersurAndroiddumomentque vousutilisezWindows,MacOSXouunedistributionLinux.Ilyabiensûrcertaineslimitesà nepasfranchir.

Voyons si votre système d’exploitation est suffisant pour vous mettre au travail. Pour un environnementWindows,sonttolérésXP(enversion32bits),Vista(enversion32et64bits) et7(aussien32et64bits).Officieusement(eneffet,Googlen’ariencommuniquéàcesujet), Windows8estaussisupportéen32et64bits.

?

EtcommentsavoirquelleversiondeWindowsj’utilise?

Win

dows

mar

rer

 

Exé

cu

ter

 

win

ver

Win

dows 7

 

Win

dows Vista

 

Win

dows XP

C’est simple, si vous utilisez Windows 7 ou Windows Vista, appuyez en même temps sur la toucheet sur la touche R . Si vous êtes sous Windows XP, il va falloir cliquer sur puissur           .Danslanouvellefenêtrequis’ouvre,tapez        .Silafenêtre quis’ouvreindique            ou           ,c’estbon,maiss’ilestécrit        ,

alorsvousdevezvérifierqu’iln’estécritàaucunmoment64 ’estlecas,alorsvousne pourrezpasdévelopperpourAndroid.

SousMac,ilvousfaudraMac OS 10.5.8ouplusrécent et unprocesseurx86.

SousGNU/Linux,Googleconseilled’utiliserunedistributionUbuntuplusrécentequela8.04. Enfindemanièregénérale,n’importequelledistributionconvientàpartirdumomentoùvotre bibliothèqueGNU C (glibc)estaumoinsàlaversion2.7.Sivousavezunedistribution64 bits,elledevraêtrecapabledelancerdesapplications32bits.

i

2.2. Le Java Development Kit

En tant que développeur Java vous avez certainement déjà installé le JDK (pour « Java DevelopmentKit»),cependantonnesaitjamais!Jevaistoutdemêmevousrappelercomment l’installer. En revanche, si vous l’avez bien installé et que vous êtes à la dernière version, ne perdezpasvotretempsetfilezdirectementàlaprochainesection!

Unpetitrappeltechniquenefaitdemalàpersonne.IlexistedeuxplateformesenJava:

— Le JRE (Java Runtime Environment), qui contient la JVM (Java Virtual Machine, rappelez-vous,j’aiexpliquéleconceptdemachinevirtuelledanslepremierchapitre),les bibliothèquesdebasedulangageainsiquetouslescomposantsnécessairesaulancement d’applicationsoud’appletsJava.Engros,c’estl’ensembled’outilsquivouspermettra d’exécuterdesapplicationsJava.

— Le JDK (Java Development Kit),quicontientleJRE(afind’exécuterlesapplications Java), mais aussi un ensemble d’outils pour compiler et déboguer votre code! Vous trouverez un peu plus de détails sur la compilation dans l’annexe sur l’architecture d’Android .

Figure 2.1.–OnabesoinduJDK,pasduJRE

Ac

cept Li

cense Agree

ment

 

De

cline Li

Onvousdemandeensuited’accepter(                                                           )oudedécliner(

cense Agree

ment

)uncontratdelicence,vousdevezacceptercecontratavantdecontinuer.

Choisissezensuitelaversionadaptéeàvotreconfiguration.Unefoisletéléchargementterminé, vouspouvezinstallerletoutlàoùvousledésirez.Vousaurezbesoinde 250 Mo delibresurle disqueciblé.

2.3. Eclipse, l’ADT et le SDK

Onvamaintenanttéléchargerunfichierquicontientunensembled’outilsindispensablespour développernosapplicationsAndroid.Cepaquetcontient:

— Eclipse,unenvironnementdedéveloppementspécialisédansledéveloppementJavamais quin’estpascapablededévelopperdesapplicationsAndroidsanslecomposantsuivant;

— Le plugin ADT, qui est une extension d’Eclipse afin de développer des applications Android;

— Desoutilspourgérerl’installationd’Androidsurvotresystème.

Down

load the SDK

Pourseprocurercesoutils,rendez-vousici  etcliquezsur                                                       :

 

Figure 2.2.–Cliquezicipourvousprocurerlesoutils

Pendantqueletélécharges’effectue,jevaisrépondreauxquestionséventuellesquevouspourriez avoir:

C’estquoiunenvironnementdedéveloppement?

Vousconnaissezpeut-êtreplutôtlemotIDE.UnIDEestunlogicieldontl’objectifestdefaciliter ledéveloppement,géné’autrestermes,il vousestpossible dedévelopper sansun IDE,maisen utiliserun estbeaucoupplus pratique. En effet, il contient un certain nombre d’outils, dont au moins un éditeur de texte - souvent étendu pour avoir des fonctionnalités avancées telles que l’auto-complétion ou la génération automatiquedecode-desoutilsdecompilationetundébogueur.Danslecasdudéveloppement Android,unIDEesttrèspratiquepourceuxquisouhaitentnepasavoiràutiliserleslignesde commande.

CetutorielsebasesurEclipse:eneffetilestfournitpardéfautparGoogledanslepaquetage quenoustéléchargeons.Vouspouvezaussiopterpourd’autresIDEcompétentstelsqueIntelliJ  ou  Jeneprésenteraiqu’Eclipse,vousaurezàexplorervous-mêmesles autresoutilssivousêtesintéressé.

Enfincequevousdevezcomprendre,c’estquelecodeserapareilquelquesoitl’IDEquevous choisirez,l’IDEn’estqu’unoutil,ilneferapasdetravaildedéveloppementàvotreplace,ilne feraquevousaiderdanscettetâche.

 

EclipseestutilisépardéfautpourdévelopperdesprogrammesJava,cequiestbienpuisquele langagedeprogrammationd’AndroidestleJava.MaisenplusduJava,nousallonsutiliserdes fonctionnalitésquisontuniquesàAndroid,etpourqu’Eclipsecomprennecesfonctionnalités,il abesoind’unlogicielquil’aideàlescomprendre.Celogiciel,c’estl’ADT.

 

Je viens tout juste de vous dire que nos applications seront en Java, mais qu’on utilisera des fonctionnalités que n’a pas le Java. Et bien le SDK d’Android, c’est-à-dire un kit de développement dansnotrelangue,c’estunensembled’outilsquemetàdispositionGoogle afindevouspermettrededévelopperdesapplicationspourAndroid.

Une fois le téléchargement terminé et l’archive décompressée rendez vous dans le répertoire

 

Figure 2.3.–Lesplashscreen

Toutd’abord,unefenêtrevas’ouvrirpourvousdemanderoùvoussouhaitezinstallerleworkspace, c’est-à-direl’endroitoùvoussouhaitezquevosprojetssoientsauvegardés:

 

Figure 2.4.–Leworkspaceestl’endroitoùvossourcesserontenregistréespardéfaut

Cette fenêtre va s’ouvrir à chaque fois si vous ne cliquez pas sur Use this as the de fault and do not ask again,alorsjevousconseilledelefaire.Unefoislelogicielouvert, jevousinviteàregardertoutd’abordlabarred’outils:

 

Figure 2.5.–Labarred’outilsd’Eclipse

An

droid SDK Ma

na

ger

Cliquez maintenant sur le boutonpour ouvrir l’outil de gestion du

SDKd’Android:

 

Figure 2.6.–LeboutonAndroidSDKManagerestceluidegauche

An

droid SDK Ma

na

ger

Les’ouvreetvoustomberezsurunécransimilaireàcelui-ci:

 

Figure 2.7.–LeboutonAndroidSDKManagerestceluidegauche

An

droid SDK Tools

 

ins

tal

led

 

Do

cu

men

ta

tion for An

Chaquelignecorrespondàunpaquet,c’est-à-diredesfichiersquiseronttéléchargéspourajouter denouvellesfonctionnalitésauSDKd’Android.Parexemplevouspouvezvoirquelepaquet est déjà installé (         ). En revanche,

Not ins

tal

led

droid SDKn’estpasinstallé().

Jevousdemandemaintenantdebienregarderlenomdespaquets,vousremarquerezquecertains

An

droid [un nombre] (API [un autre nombre])

suiventuncertainmotif.Ilestécritàchaquefois.

Laprésencedecesnombress’expliqueparlefaitqu’ilexisteplusieursversionsdelaplateforme Android qui ont été développées depuis ses débuts et qu’il existe donc plusieurs versions différentes en circulation. Le premier nombre correspond à la version d’Android et le second à laversiondel’APIAndroidassociée.Quandondéveloppeuneapplication,ilfautprendreen comptecesnuméros,puisqu’uneapplicationdéveloppéepouruneversionprécised’Androidne fonctionnerapaspourlesversionsprécédentes.J’aichoisidedélaisserlesversionsprécédantla version2.1(l’API7),defaçonàcequel’applicationpuissefonctionnerpour2.2,3.1,4.2.2,… maispasforcémentpour1.6ou1.5!

!

Les API dont le numéro est compris entre 11 et 13 sont normalement destinées aux éorie,vousn’avezpasàvousensoucier,lesapplicationsdéveloppéesavec lesAPInumériquementinférieuresfonctionneront,maisilyauradespetitseffortsàfournir enrevancheencequiconcernel’interfacegraphique(voustrouverezplusdedétailsdans

 

Vous penserez peut-être qu’il est injuste de laisser de côté les personnes qui sont contraintes d’utiliser encore ces anciennes versions, mais sachez qu’ils ne représentent que 5 % du parc mondial des utilisateurs d’Android. Ainsi, toutes les applications que nous développerons fonctionnerontsousAndroid2.1minimum.

Pourchoisirlesmêmesfichiersquenous,ilvoussuffitdecliquersurlescasessuivantes:

 

Figure 2.8.–Choisissezcespaquetslà

Ins

tall xx pa

ckages

Puiscliquezsur.Ilvousfaudraensuitevaliderleslicencespourles fichiersquevousalleztélécharger:

 

Figure 2.9.–ChoisissezAcceptLicensepourchaquepackagepuiscliquezsurInstall

Sivousinstalleztouscespaquets,vousaurezbesoinde 1 Go surledisquededestination.

2.4. L’émulateur de téléphone : Android Virtual Device

L’AndroidVirtualDevice,aussiappeléAVD,estunémulateurdeterminalsousAndroid,c’est-àdirequec’estunlogicielquisefaitpasserpourunappareilsousAndroidàvotreordinateur.C’est laraisonpourlaquellevousn’avezpasbesoind’unpériphériquesousAndroidpourdévelopper ettesterlaplupartdevosapplications!Eneffet,uneapplicationquiafficheuncalendrierpar exemplepeuttrèsbiensetesterdansunémulateur,maisuneapplicationquiexploiteleGPS doitêtreéprouvéesurleterrainpourquel’onsoitcertaindesoncomportement.

LancezànouveauEclipsesivousl’avezfermé.Repérezànouveauoùsetrouvelabarred’outils. Vousvoyezlecoupled’icônesreprésentédanslafiguresuivante?

 

Figure 2.10.–LesdeuxicônesréservéesauSDKetàl’AVD

Celledegauchepermetd’ouvrirlesoutilsduSDKetcellededroitepermetd’ouvrirl’interface degestiond’AVD.Vousaurezainsiunécranquiressembleàcelui-ci:

 

Figure 2.11.–CetécranvouspermettradecréerdesAVD

An

droid

Vir

tual

De

vices

 

De

vice

De

fi

ni

tions

Vous pouvez voir deux onglets : et . Le premier onglet recense tous vos AVD et vous permet d’en créer avec précision, alors que le second onglet vous permet de créer des onglets qui ressemblent à des machines qui existent réellement, par exemple le Nexus S de Google. Vous pouvez donc créer facilement un AVD commeça,maisjevaisaussivousprésenterleméthodecompliquée,parcequ’onestdesvrais ici!

Donc,danslepremieronglet,cliquezsurceluidedroitepuissurNewpourajouterunnouvel AVD.

Une fenêtre s’ouvre (voir figure suivante), vous proposant de créer votre propre émulateur. OnvacommencerparindiquerunnompournotreAVDdansAVD Name,histoiredepouvoir différencier vos AVD. Pour ma part, j’ai choisi 3.2_QVGA_API_7 : la taille de l’écran et la versiondel’APIsouslaquellefonctionneracetAVD.Notezquecertainscaractèrescommeles caractèresaccentuésetlesespacesnesontpasautorisés.Vouspouvezchoisirlatailledel’écran àl’aidedeDevice.Parexemple,j’aichoisiunécranquifait3.2”pourunerésolutionde320* 480.

Tar

get

 

An

droid 2.1

-

 API Le

vel 7

Dans   ,choisissez       ,puisquej’aidécidéquenousferons nosapplicationsaveclaversion7del’APIetsansleGoogleAPI.Laissezlesautresoptionsà leurvaleurpardéfaut,nousyreviendronsplustardquandnousconfectionneronsd’autresAVD.

CliquezenfinsurOKetvousaurezunemachineprêteàl’emploi!

 

Figure 2.12.–Créezvotrepropreémulateur

SivousutilisezWindowsetquevotrenomdesessioncontientuncaractèrespécial,parexemple un accent, alors Eclipse vous enverra paître en déclarant qu’il ne trouve pas le fichier de configurationdel’AVD.Parexemple,undenoslecteuravaitunesessionquis’appelait«Jérémie

» et avait ce problème. Heureusement, il existe une solution à ce problème. Si vous utilisez

mar

rer

 

Exé

cu

ter

Windows7ouWindowsVista,appuyezenmêmetempssurlatouche Windows etsurlatouche .SivousêtessousWindowsXP,ilvafalloircliquersur        puissur .

Ad

mi

nis

tra

tor

AD

MINI~1

Dans la nouvelle fenêtre qui s’ouvre, tapez « cmd » puis appuyez sur la touche Entrée de votreclavier.Unenouvellefenêtrevas’ouvrir,ellepermetdemanipulerWindowsenlignede commande.Tapezcd ..puis Entrée .Maintenant,tapezdir /x.Cettecommandepermetde listertouslesrépertoiresetfichiersprésentsdanslerépertoireactueletaussid’afficherlenom abrégédechaquefichierourépertoire.Parexemple,pourlasessiononobtient lenomabrégé,commelemontrelafiguresuivante.

 

Figure 2.13.–Lavaleuràgaucheestlenomréduit,alorsquecellededroiteestlenomentier

X:\Uti

li

sa

teurs\<Votre ses

sion>\.an

droid\avd\<nom_de_votre_avd>.ini

Maintenant,repérezlenomréduitquicorrespondàvotrepropresession,puisdirigez-vousversle fichieret ouvrezcefichier.Ildevraitressembleraucodesuivant:

 

tar

get=an

droid

-7

path=X:\Users\<Votre

ses

S’iln’yapasderetouràlaligneentre                                                     et

sion>\.an

droid\avd\

, c’est que vous n’utilisez pas un bon éditeur de texte.

<Votre ses

sion>

Utilisez le lien que j’ai donné ci-dessus. Enfin, il vous suffit de remplacer

Ad

mi

nis

tra

tor

parlenomabrégédelasessionquenousavionstrouvéprécédemment.Parexemplepourlecas delasession,jechange:

 

en

 

2.5. Test et configuration

Bien,maintenantquevousavezcrééunAVD,onvapouvoirvérifierqu’ilfonctionnebien.

 

Figure 2.14.–LalistedesémulateursqueconnaîtvotreAVDManager

Vousyvoyezl’AVDquenousvenonstoutjustedecréer.Cliquezdessuspourdéverrouillerle menudedroite.Commejen’aipasl’intentiondevraimentdétaillercesoptionsmoi-même,je vaisrapidementvousexpliqueràquoiellescorrespondentpourquevoussachiezlesutiliseren casdebesoin.Lesoptionsdumenudedroitesontlessuivantes:

— Editvouspermetdechangerlescaractéristiquesdel’AVDsélectionné.

De

lete

Re

pair

—vouspermetdesupprimerl’AVDsélectionné.

—nevousserapeut-êtrejamaisd’aucuneutilité,ilvouspermetderéparerunAVD quandlegestionnairevousindiquequ’ilfautlefaire.

De

tails

—lanceraunenouvellefenêtrequilisteralescaractéristiquesdel’AVDsélectionné. — Startestleboutonquinousintéressemaintenant,ilvouspermetdelancerl’AVD.

CliquonsdoncsurleboutonStartetunenouvellefenêtreselance,quidevraitressemblerpeu ouprouàlafiguresuivante.

 

Laissezlesoptionsvierges,onn’aabsolumentpasbesoindecegenrededétails!Cliquezjuste surLaunch.

Enfin,votreterminalselancera. i

Ilsepeutquel’émulateursoittrèslent.C’estnormal!Cen’estpasfacilepourunordinateur d’émuleruntélé’estpasparcequevotreordinateurestdixfoispluspuissant qu’untéléphonequ’êtreexact,vousdemandezàvotre ordinateur d’exécuter des instructions processeurs qui respectent l’architecture ARM

(parcequelesprocesseursdestéléphonesutilisentengrandemajoritécettearchitecture) alorsquevotreprocesseurn’utilisepaslamêmearchitecture.Parexemple,quandvous demandezàvotreprocesseurdefaireuneaddition,ilsauralefairedirectementparceque vousluidemandezdanssonarchitecturenormale.Quandl’émulateurluidemandedefaire uneaddition,illuidemandeavecdesinstructionsARM,qu’ildevradoncensuitetraduire eneninstructionqu’ilpeutcomprendre:c’estdoncterriblementpluslent.

Voustrouverezàdroiteunelistedeboutonspermettantd’imiterlesboutonsqu’auraitentemps normal un téléphone, mais que votre ordinateur n’a pas bien sûr! Ils sont divisés en deux catégories.Lapremièresontlescontrôlesdebase:

— :Diminuerlevolume.

          —                       :Augmenterlevolume.

Mais!L’émulateurn’estpasàl’heure!Enplusc’estdel’anglais!

Lamaîtrisedel’anglaisdevientviteindispensabledanslemondedel’informatique…!Ensuite, lesmachinesquevousachetezdanslecommercesontdéjàconfiguréespourlepaysdanslequel vous les avez acquises, et, comme ce n’est pas une machine réelle ici, Android a juste choisi les options par défaut. Nous allons devoir configurer la machine pour qu’elle réponde à nos exigences.Vouspouvezmanipulerlapartiedegaucheavecvotresouris,cequisimuleraletactile. Faitesglisserleverrousurlagauchepourdéverrouillerlamachine.Vousvousretrouverezsur l’accueil.CliquezsurleboutonMENUàdroitepourouvrirunpetitmenuenbasdel’écrande l’émulateur,commeàlafiguresuivante.

 

Figure 2.15.–Ouvrelemenupouraccéderauxoptions

Set

tings

Re

tour

Cliquezsurl’optionpourouvrirlemenudeconfigurationd’Android.Vouspouvezy naviguersoitenfaisantglisseraveclasouris(unclic,puisenlaissantappuyéondirigelecurseur vers le haut ou vers le bas), soit avec la molette de votre souris. Si par mégarde vous entrez dansunmenunondésiré,appuyezsurleboutonprésentéprécédemment(uneflèche quieffectueundemi-tour).

Lan

guage & key

board

Cliquezsurl’option(voirfiguresuivante);c’estlemenuquivouspermet dechoisirdansquellelangueutiliserleterminaletqueltypedeclavierutiliser(parexemple, vous avez certainement un clavier dont les premières lettres forment le mot AZERTY, c’est ce qu’ons’,oui,lesinformaticiensontbeaucoupd’imagination

).

 

Figure 2.16.–OnvasélectionnerLanguage&keyboard

Se

lect lo

cale

Puis, vous allez cliquer sur. Dans le prochain menu, il vous suffit de sélectionner la langue dans laquelle vous préférez utiliser Android. J’ai personnellement choisi

Fran

çais (France)

. Voilà, un problème de réglé! Maintenant j’utiliserai les noms français

Re

tour

desmenuspourvousorienter.Pourrevenirenarrière,ilfautappuyersurleboutondu menudedroite.

Au

to

ma

tique

fi

nir fu

seau ho

raire

Votreprochainemission,sivousl’acceptez,seradechangerl’heurepourqu’elles’adapteàla zone dans laquelle vous vous trouvez, et ce, par vous-mêmes. En France, nous vivons dans la zone GMT + 1. À l’heure où j’écris ces lignes, nous sommes en heure d’été, il y a donc uneheureencoreàrajouter.Ainsi,sivousêtesenFrance,enBelgiqueouauLuxembourget en heure d’été, vous devez sélectionner une zone à GMT + 2. Sinon GMT + 1 pour l’heure d’hiver. Cliquez d’abord sur Date & heure, désélectionnez, puis cliquez sur etsélectionnezlefuseauquivousconcerne.

 

Figure 2.17.–Decettemanière,votreterminalseraàl’heure

Sivouscomptezfaireimmédiatementleprochainchapitrequivouspermettradecommencer— enfin — le développement, ne quittez pas la machine. Dans le cas contraire, il vous suffit de resterappuyésurleboutonpourarrêterl’émulateurpuisdevouslaisserguider.

2.6. Configuration du vrai terminal

Maintenantonvas’occuperdenotrevraioutil,sivousenavezun!

2.6.1. Configuration du terminal

Confi

gu

ra

tion > Ap

pli

ca

tion > Source in

con

nue

Toutnaturellement,vousdevezconfigurervotretéléphonecommeonaconfigurél’é plus,vousdevezindiquerquevousacceptezlesapplicationsquineproviennentpasduMarket dans.

2.6.2. Pour les utilisateurs de Windows

\an

droid

-

sdk\ex

tras\google\usb_dri

ver

Toutd’abord,vousdeveztéléchargerlesdriversadaptésàvotreterminal.Jepeuxvousdonnerla marcheàsuivrepourcertainsterminaux,maispaspourtous…Eneffet,chaqueappareilabesoin dedriversadaptés,etceseradoncàvousdelestélécharger,souventsurlesiteduconstructeur. Cependant,ilexistedespilotesgéné suivant ma démarche, ils sont déjà téléchargés, mais rien n’assure qu’ils fonctionnent pour votreappareil.EnpartantdurépertoireoùvousavezinstalléleSDK,onpeutlestrouveràcet emplacement:.Voustrouverezl’emplacement

despilotesàtéléchargerpourtouteslesmarquesdansletableauquisetrouvesurcettepage

.

2.6.3. Pour les utilisateurs de Mac

Àlabonneheure,vousn’avezabsolumentrienàfairedespécialpourquetoutfonctionne!

2.6.4. Pour les utilisateurs de Linux

SUB

SYS

TEM=="usb", ATTR{id

Ven

dor}=="XXXX", MODE="0

an

droid.rules

LagestiondesdriversUSBdeLinuxétantbeaucoupmoinschaotiquequecelledeWindows, vousn’avezpasàtéléchargerdedrivers.Ilyacependantunepetitedémarcheà eneffetdevoirajouteraugestionnairedepériphériquesunerèglespécifiquepourchaqueappareil qu’onvoudrarelier.Jevaisvousdécrirecettedémarchepourlesutilisateursd’Ubuntu: 1. On va d’abord créer le fichier qui contiendra ces règles à l’aide de la commande sudo touch /etc/udev/rules.d/51-.touchestlacommandequi permet de créer un fichier, et udev est l’emplacement des fichiers du gestionnaire de périphériques.udevconservesesrèglesdanslerépertoire./rules.d.

2.    Lesystèmevousdemanderadevousidentifierentantqu’utilisateurroot.

an

droid.rules

3.    Puisonvamodifierlesautorisationssurlefichierafind’autoriserlalectureetl’écriture àtouslesutilisateurschmod a+rw /etc/udev/rules.d/51-.

4.    Enfin,ilfautrajouterlesrèglesdansnotrefichiernouvellementcréé.Pourcela,onvaajouteruneinstructionquiressembleraà: dev".Attention,onn’écrirapasexactement cettephrase.

 

SUB

SYS

TEM

estlemodedeconnexionentrelepériphériqueetvotreordinateur,dansnotrecas

ATTR{id

Ven

dor}

onutiliserauneinterfaceUSB.MODEdéterminequipeutfairequoisurvotrepériphérique,et la valeur « 0666 » indique que tous les utilisateurs pourront lire des informations mais aussi en écrire. GROUP décrit tout simplement quel groupe UNIX possède le périphérique. Enfin, estlalignequ’ilvousfaudramodifierenfonctionduconstructeurdevotre

périphérique.Onpeuttrouverquellevaleurindiquersurladocumentation .Parexemplepour monHTCDesire,j’indiquelalignesuivante:

1 SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", MODE="0666", GROUP="plugdev" …cequientraînequejetapedanslaconsole:

1 echo "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0bb4\", MODE=\"0666\", GROUP=\"plug

Sicetteconfigurationnevouscorrespondpas,jevousinviteàlireladocumentationdeudev afindecréervotreproprerègle.

2.6.5. Et après?

Maintenantquevotreordinateurpeutreconnaîtrevotretéléphone,onvafaireensortequevotre téléphone puisse exécuter des applications que vousavezdéveloppé et exécuter un debugger. Pourcela,faitescommepourl’AVDetallezdanslesoptions.

!

Enfonctiondevotreversiond’Android,lamanipulationseradifférente.

2.6.5.1. Pour les versions les plus anciennes d’Android

Ap

pli

ca

tion

Commencezparvousdirigerversl’option:

 

Figure 2.18.–Choisissezl’optionApplications

Sources

In

con

nues

ve

lop

pe

ment

Dans le menu qui vient de s’ouvrir, il vous faudra activer les. Une fois quec’estfait,allezdanslemenu:

 

Figure 2.19.–ActivezlesSourcesInconnuesetallezdanslemenuDéveloppement

Enfin, dans l’écran qui s’ouvre, sélectionnez les options pour que votre écran ressemble à celui-là:

 

Figure 2.20.–Votreécrandoitressembleràcelui-là

2.6.5.2. Pour les autres, avec une version plus récente

cu

rité

Vousvoustrouvezaussidanslesoptions,maisellesontunlookdifférent.Dirigez-vousversle menu:

 

Figure 2.21.–LemenuressembleàçasousAndroidJellyBean

C’esticiquevouspourrezactiverlesapplicationsdesourcesinconnuesencliquantsurl’option prévuesàceteffet:

 

Op

tions

pour

les

ve

lop

peurs

A

pro

pos

du

phone

Retournezmaintenantaumenudesoptions.Attentionçavadevenirunpeubizarre.Sivousne voyezpasl’option           ,sélectionnez   , ledernieritemdelaliste:

 

Figure 2.22.–Il s’agit de la toute dernière option du menu, mais pas besoin de l’ouvrir si Optionspourlesdéveloppeursestdéjàlà

Nu

méro

de

Build

Navigueztoutenbasdecettepageetappuyezsur.Septfois.C’estpasune blague,appuyezsurceboutonseptfois:

 

Figure 2.23.–Ilfautappuyerseptfoissurceboutonlà,mêmesic’estbizarre

Op

tions

pour

les

ve

lop

peurs

Félicitations! Votre téléphone vous considère comme un développeur! On va maintenant lui montrerquiestlepatron(vouspourceuxquisuiventpas).Retournezdanslemenuprécédent etunenouvelleoptionestapparue:.C’estvotreprochaine destination:

 

Figure 2.24.–Cenouveaumenuestouvert,entrez-y

bo

gage

USB

Etenfin,danscemenu,sélectionnezl’optionetvousserezprêt:

 

Figure 2.25.–Activezcetteoptionetvousaurezfini

 

— Ilestessentield’installerl’environnementJavasurvotreordinateurpourpouvoirdéveloppervosapplicationsAndroid.

— VousdevezégalementinstallerleSDKd’Androidpourpouvoirdéveloppervosapplications. Cekitdedéveloppementvousoffrira,entreautres,lesoutilspourtéléchargerlespaquets delaversiond’Androidpourlequelvousvoulezdévelopper.

— Eclipsen’estpasl’environnementdetravailobligatoirepourdéveloppervosapplications mais c’est une recommandation de Google pour sa gratuité et sa puissance. De plus, le SDK d’Android est prévu pour s’y intégrer et les codes sources de ce cours seront développésgrâceàcetIDE.

— Si vous n’avez pas de smartphone Android, Google a pensé à vous et mis à votre disposition des AVD pour tester vos applications. Ces machines virtuelles lancent un véritablesystèmeAndroidmaisprenezgardeànepasvousyfierà100%,iln’yariende plusconcretquelestestssurdesterminauxphysiques.


3.   Votre première application

Cechapitreesttrèsimportant.Ilvouspermettrad’enfinmettrelamainàlapâte,maissurtout onaborderalanotiondecycled’uneactivité,quiestlabased’ pourvousunprogrammeenJavadébuteforcémentparunmain,vousrisquezd’êtresurpris.

On va tout d’abord voir ce qu’on appelle des activités et comment les manipuler. Sachant quelamajoritédevosapplications(sicen’esttoutes)contiendrontplusieursactivités,ilest indispensablequevousmaîtrisiezceconcept!Nousverronsaussicequesontlesvuesetnous créeronsenfinnotrepremierprojet—lepremierd’unegrandesérie—quin’estpas,demanière assezsurprenante,un«HelloWorld!».Enfinpresque!

3.1.    Activité et vue

3.1.1. Qu’est-ce qu’une activité?

Sivousobservezunpeul’architecturedelamajoritédesapplicationsAndroid,vousremarquerez uneconstructiontoujoursàpeuprèssimilaire.Prenonsparexemplel’applicationduPlayStore. Vous avez plusieurs fenêtres à l’intérieur même de cette application : si vous effectuez une recherche,unelistederésultatss’afficheradansunepremièrefenêtreetsivouscliquezsurun résultat,unenouvellefenêtres’ouvrepourvousafficherlapagedeprésentationdel’application sélectionnée. Au final, on remarque qu’une application est un assemblage de fenêtres entre lesquellesilestpossibledenaviguer.

Cesdifférentesfenêtressontappeléesdesactivités.Unmoyenefficacededifférencierdesactivités estdecomparerleurinterfacegraphique:siellessontradicalementdifférentes,c’estqu’ils’agit d’activitésdifférentes.Deplus,commeuneactivitéremplittoutl’écran,votreapplicationne peutenafficherqu’uneàlafois.Lafiguresuivanteillustrececoncept.

 

Figure 3.1.–Cliquersurunélémentdelalistedanslapremièreactivitépermetd’ouvrirles détailsdansunesecondeactivité Jemepermetsdefaireunpetitapartépourvousrappelercequ’estuneinterfacegraphique:il s’agitd’unensembled’élémentsvisuelsaveclesquelspeuventinteragirlesutilisateurs,ouqui leur fournissent des informations. Tout ça pour vous dire qu’une activité est un support sur lequelnousallonsgrefferuneinterfacegraphique.Cependant,cen’estpaslerôledel’activité quedecréeretdedisposerlesélémentsgraphiques,ellen’estquel’échafaudagesurlequelvont s’insérerlesobjetsgraphiques.

Deplus,uneactivitécontientdesinformationssurl’étatactueldel’application:cesinformations s’appellent le context. Ce context constitue un lien avec le système Android ainsi que les autresactivitésdel’application,commelemontrelafiguresuivante.

 

Figure 3.2.–Uneactivitéestconstituéeducontextedel’applicationetd’uneseuleetunique interfacegraphique

Commeilestplusaisédecomprendreàl’aided’exemples,imaginezquevousnaviguiezsurle SiteduZéroavecvotretéléphone,letoutenécoutantdelamusiquesurcemêmetélé sepassedeuxchosesdansvotresystème:

— Lanavigationsurinternet,permiseparuneinterfacegraphique(labarred’adresseetle contenudelapageweb,aumoins);

— Lamusique,quiestdiffuséeenfondsonore,maisquin’affichepasd’interfacegraphique àl’heureactuellepuisquel’utilisateurconsultelenavigateur.

Onaainsiaumoinsdeuxapplicationslancéesenmêmetemps;cependant,lenavigateuraffiche uneactivitéalorsquelelecteuraudion’enaffichepas.

3.1.2. États d’une activité

Siunutilisateurreçoitunappel,ildevientplusimportantqu’ilpuisseyrépondrequed’émettre la chanson que votre application diffuse. Pour pouvoir toujours répondre à ce besoin, les développeursd’Androidonteurecoursàunsystèmeparticulier:

— Àtoutmomentvotreapplicationpeutlaisserplaceàuneautreapplication,quiaune priorité plus élevée. Si votre application utilise trop de ressources système, alors elle empêcheralesystèmedefonctionnercorrectementetAndroidl’arrêterasansvergogne.

— Votreactivitéexisteradansplusieursétatsaucoursdesavie,parexempleunétatactif pendantlequell’utilisateurl’exploite,etunétatdepausequandl’utilisateurreçoitun appel.

Pour être plus précis, quand une application se lance, elle se met tout en haut de ce qu’on appellelapiled’activités.

i

Unepileestunestructurededonnéesdetype«LIFO»,c’est-à-direqu’iln’estpossible d’avoiraccèsqu’àunseulélémentdelapile,letoutpremierélément,aussiappelé sommet. Quandonajouteunélémentàcettepile,lenouvelélémentprendralapremièreplaceet deviendralenouveausommet.Quandonveutrécupérerunélément,ceseralesommetqui serarécupéré,sortidelalisteetl’objetendeuxièmeplacedeviendralenouveausommet, commeillustréàlafiguresuivante.

Figure 3.3.–Fonctionnementdelapiled’activités

L’activitéquevoitl’utilisateurestcellequisetrouveau-dessusdelapile.Ainsi,lorsqu’unappel arrive,ilseplaceausommetdelapileetc’estluiquis’afficheàlaplacedevotreapplication,qui n’estplusqu’àladeuxièmeplace.Votreactiviténereviendraqu’àpartirdumomentoùtoutes les activités qui se trouvent au-dessus d’elle seront arrêtées et sorties de la pile. On retrouve ainsileprincipeexpliquéprécédemment,onnepeutavoirqu’uneapplicationvisibleenmême tempssurleterminal,etcequiestvisibleestl’interfacegraphiquedel’activitéquisetrouveau sommetdelapile.

Uneactivitépeutsetrouverdanstroisétatsquisedifférencientsurtoutparleurvisibilité:

État

Visibilité

Description

Active

ac

tive

 

run

ning

(«                    » ou «

»)

L’activité est visible en totalité.

Elle est sur le dessus de la pile, c’est ce que

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

Suspendue

pau

sed

(«»)

L’activitéestpartiellement visibleàl’écran.

C’estlecasquandvousrecevez unSMSetqu’unefenêtre semi-transparentesepose devantvotreactivitépour afficherlecontenudumessage etvouspermettred’yrépondre parexemple.

Cen’estpassurcetteactivité qu’agitl’utilisateur.

L’applicationn’apluslefocus,

c’estl’applicationsus-jacente quil’a.Pourquenotre applicationrécupèrelefocus, l’utilisateurdevrase débarrasserdel’applicationqui l’obstrue,puisl’utilisateur pourraànouveauinteragir avec.

Silesystèmeabesoinde mémoire,ilpeuttrèsbientuer l’application(cetteaffirmation n’estplusvraiesivousutilisez unSDKavecl’API11 minimum).

Arrêtée

stop

ped

(«»)

L’activité est tout simplement oblitéréeparuneautreactivité, onnepeutpluslavoirdutout.

L’application n’a évidemment plus le focus, et puisque l’utilisateurnepeutpaslavoir,ilne peutpasagirdessus.

Lesystèmeretientsonétatpour pouvoirreprendre,maisilpeut arriverquelesystèmetuevotre application pour libérer de la mémoiresystème.

?

Maisj’aipourtantdéjàvudessystèmesAndroidavecdeuxapplicationsvisiblesenmême temps!

Ahoui,c’estpossible.Maisils’agitd’unartifice,iln’yavraimentqu’uneapplicationquiest active.Pourfacilitervotrecompréhension,jevousconseilled’oubliercessystèmes.

3.1.3. Cycle de vie d’une activité

Uneactivitén’apasdecontrôledirectsursonpropreétat(etparconséquentvousnonplusen tantqueprogrammeur),ils’agitplutôtd’uncyclerythméparlesinteractionsaveclesystèmeet d’autresapplications.Voiciunschémaquiprésentecequel’onappelle le cycle de vie d’une activité,c’est-à-direqu’ilindiquelesétapesquevatraversernotreactivitépendantsavie,de sanaissanceàsamort.Vousverrezquechaqueétapeducycleestreprésentéeparuneméthode.

Nousverronscommentutilisercesméthodesentempsvoulu.

 

Figure 3.4.–Cycledevied’uneactivité

i

LesactivitéshéritentdelaclasseActivity .Or,laclasseActivityhéritedel’interface Context dontlebutestdereprésentertouslescomposantsd’uneapplication.Onles .Activity.

Pourrappel,unpackageestunrépertoirequipermetd’organisernotrecodesource,unrécipient danslequelnousallonsmettrenosclassesdefaçonàpouvoirtriervotrecodeetdifférencierdes classesquiauraientlemêmenom.Concrètement,supposezquevousayezàcréerdeuxclassesX —quiauraientdeuxutilisationsdifférentes,biensûr.Vousvousrendezbiencomptequevous seriezdansl’incapacitétotalededifférencierlesdeuxclassessivousdeviezinstancierunobjet de l’une des deux classes X, et Java vous houspillera en déclarant qu’il ne peut pas savoir à quelleclassevousfaitesréférence.C’estexactementcommeavoirdeuxfichiersaveclemême nometlamêmeextensiondansunmêmerépertoire:c’estimpossiblecarc’estincohérent.

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

fi

chage.Image

fi

deo

 

le

char

ge

ment

codesourced’unnavigateurinternet,onpourraittrouverlespackages, et       .

Les vues (quenosamisanglaisappellent view),sontcesfameuxcomposantsquiviendrontse greffersurnotreéchafaudage,ils’agitdel’unitédebasedel’interfacegraphique.Leurrôleest defournirducontenuvisuelaveclequelilestéventuellementpossibled’interagir.Àl’instarde l’interfacegraphiqueenJava  ,ilestpossiblededisposerlesvuesàl’aidedeconteneurs,nous verronscommentplustard.

i

Lesvueshé.

3.2. Création d’un projet

UnefoisEclipsedémarré,cliquezsurFile,puisNewetenfinAndroidApplicationProjet,comme montrésurcetteimage:

 

Figure 3.5.–PrenezcecheminlàpourcréerunnouveauprojetpourAndroid Unenouvellefenêtres’ouvre;voyonsensemblecequ’ellecontient:

 

Figure 3.6.–CetécranvouspermettradecréervotrepremierprojetpourAndroid

Tousceschampsnouspermettentdedéfinircertainescaractéristiquesdenotreprojet:

Ap

pli

ca

tion name

— Toutd’abord,vouspouvezchoisirlenomdevotreapplicationavec. Il s’agit du nom qui apparaîtra sur l’appareil et sur Google Play pour vos futures applications!Choisissezdoncunnomquisembleàlafoisjudicieux,assezoriginalpour attirerl’attentionetquirestepolitiquementcorrectaudemeurant.

Pro

ject name

—est le nom de votre projet pour Eclipse. Ce champ n’influence pas l’application en elle-même, il s’agit juste du nom sous lequel Eclipse la connaîtra. Le vrai nom de notre application, celui que reconnaîtra Android et qui a été défini dans

Ap

pli

ca

tion name

,peuttrèsbienn’avoiraucunesimilitudeaveccequevousmettrez

danscechamp.Maispourvousyretrouver,mieuxvautgarderunecertainecohérence.

te

du

zero

— Ilfaudraensuitechoisirdansquelpackageiravotreapplication,jevousaidéjàexpliqué l’importancedespackagesprécédemment.Sachezquecepackageagiracommeunesorte d’identifiantpourvotreapplicationsurlemarchéd’applications,alorsfaitesensortequ’il soituniqueetildevraêénéral onsebasesurlenomdedomainedesonentreprisepourleconstitué,c’estpourquoiil commenceparchezmoi.

Etpourquoituasomislesaccentsdansceschamps?

Laprogrammationestunmondeprofondémentanglophone,etlesanglaisneconnaissentpas noscaractèresavecaccent.Mettreun”é”dansunmotc’estcommemettreuncaractèrechinois poureux!Ilsneleconnaissentpas.Doncpourêtresûrdenepasavoirdeproblème,nemettez pasd’accent.

Vousvousretrouvezensuiteconfrontéàquatreslistesdéfilantes:

Mi

ni

mum Re

qui

red SDK

Mi

ni

mum Re

qui

red SDK

—est la version minimale pour laquelle votre application est destinée.CetteinformationserautiliséesurGooglePlaypourproposervosapplications àdesclients.Ainsi,sivousmettezAPI18,seulslesclientsaveclatoutenouvelleversion deJellyBeanpourrontutiliservotreapplication,c’est-à-diretrèstrèspeudegens.Ilfaut doncmettreunchiffreassezfaiblepourviserleplusdegenspossible.Parexempleen mettantl’API8,vousviserez95%desgensquivontsurGoogePlay.Anoterquecen’est pasvraimentuneobligation:siunutilisateur,quiestsousAndroid1.6(API6),obtient votreapplication(parcequevousluienvoyezparexemple)etquecetteapplicationpeut fonctionnersousl’API6,alorsilpourrainstallerl’applicationetl’utiliser,mêmesil’API6 estplusvieillequel’API8etquevousavezpréciséAPI8dans.

Tar

get SDK

 

Mi

ni

mum Re

qui

red SDK

— L’option est l’inverse de , il s’agit de la version maximalesouslaquellevotreapplicationfonctionne.Elleexploitelesmêmesrèglesque

Mi

ni

mum Re

qui

red SDK

.

Com

pile With

— LalistevouspermetdechoisirpourquelleversionduSDKvousallez compilervotreapplication.Commeindiquéprécédemment,onvachoisirl’’agit cettefoisdelaversionminimalenécessairepourutiliservotreapplication.

CliquezsurNextpourpasseràl’écransuivant:

Cetteécrancontientbeaucoupd’options,maisjevaisnevousparlerquededeux:

Create cus

tom laun

cher icon

— Lapremière,intitulée,ouvriraàlafenêtresuivante un outil pour vous aider à construire une icône pour votre application à partir d’une imagepréexistante.

Create ac

ti

vity

— Laseconde,cellequis’appelle,permetdevousfaciliterledéveloppementdel’applicationenfaisantfaireunepartieparEclipse.

Create cus

tom laun

Pourpasseràlapagesuivante,cliquezsurNext.Sivousavezcliquésur cher icon,alorsc’estlafenêtrevisibleàlafiguresuivantequis’affichera.

 

Figure 3.7.–Cetoutilfacilitelacréationd’icônes

Create cus

tom laun

cher icon

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

 

Figure 3.8.–Vouspouvezicichoisirunemiseenpagestandard

Create Ac

ti

vity

 

Blan

kAc

ti

vity

Ils’agiticid’unoutilquivousdemandesivousvoulezqu’Eclipsecréeuneactivitépourvous, et si oui à partir de quelle mise en page. On va déclarer qu’on veut qu’il crée une activité, cliquez sur la case à gauche de , mais on va sélectionner parcequ’onveutrestermaîtredenotremiseenpage.CliquezànouveausurNext.

Danslafenêtrereprésentéeàlafiguresuivante,ilfautdéclarercertainesinformationsrelatives ànotrenouvelleactivité:

 

Figure 3.9.–Permetdecréerunepremièreactivitéfacilement

Iciencoreunefois,onfaitfaceàtroischampsàrenseigner:

Ac

ti

vity Name

—permetd’indiquerlenomdelaclasseJavaquicontiendravotreactivité, cechampdoitdoncrespecterlasyntaxeJavastandard.

— Le champ suivant, Layout Name, renseignera sur le nom du fichier qui contiendra l’interfacegraphiquequicorrespondraàcetteactivité.

Na

vi

ga

tion Type

— Enfin,encequiconcerne,soncontenuesttropcomplexepourêtre analysémaintenant.Sachezqu’ilpermetdedéfinirfacilementcomments’effectuerontles transitionsentreplusieursactivités.

Fi

nish

Pourfinaliserlacréation,cliquezsur.

3.3. Un non-Hello world!

Pa

ckage Ex

plo

rer

Voustrouverezlesfichierscréésdansle(voirfiguresuivante).

 

Figure 3.10.–LePackageExplorerpermetdenaviguerentrevosprojets

Mai

nAc

ti

Onytrouvenotrepremiergrandrépertoiresrc/,celuiquicontiendratouslesfichierssources .java.Ouvrezleseulfichierquis’ytrouve,chezmoi(endoublecliquant dessus).Vousdevriezavoiruncontenuplusoumoinssimilaireàcelui-ci:

1 package com.siteduzero.mapremiereapplication;

2

3    import .Bundle;

4    import .Activity;

5    import ;

6    import .MenuItem;

7    import .NavUtils;

8

9 public class MainActivity extends Activity {

10

11            @Override

12            protected void onCreate(Bundle savedInstanceState) {

13            super.onCreate(savedInstanceState);

 

Ah!Onreconnaîtcertainstermesquejevienstoutjusted’expliquer!Jevaisprendretoutesles lignesuneparune,histoired’êtrecertaindenedéstabiliserpersonne.

 

pi

Là,ondéclarequenotreprogrammesesituedanslepackage

pli

ca

tion

,commeexpliquéprécédemment.Sionveutfaireréférenceànotreapplication,il

faudrafaireréférenceàcepackage.

1    import .Bundle;

2    import .Activity;

3    import ;

4    import .MenuItem;

5    import .NavUtils;

Ac

ti

vity

Me

nuI

tem

 

Na

vU

tils

On importe des classes qui se trouvent dans des packages différents : les classes, Bundle, Menu et qui se trouvent dans le même package, puis . Chez moi,deuxdecespackagessontinutilescarinutilisésdanslecode,commelemontrelafigure suivante.

 

Figure 3.11.–Eclipsesoulignelesimportationsinutilesenjaune

Ilexistetroismanièresderésoudrecesproblèmes:

— Vouspouveztoutsimplementignorercesavertissements.Votreapplicationfonctionnera toujours, et les performances n’en souffrirons pas. Mais je vois au moins deux raisons delefairetoutdemême:pourentreteniruncodepluslisibleetpouréviterd’avoirpar inadvertancedeuxclassesaveclemêmenom,cequipeutprovoquerdesconflits.

— Supprimerleslignesmanuellement,maiscommenousavonsunoutilpuissantentreles mains,autantlaisserEclipses’enchargerpournous!

— DemanderàEclipsed’organiserlesimportationsautomatiquement.Ilexisteunraccourci

 

s’agitd’uneactivité.

 

@Over

ride

void

on

Create()

 

Ac

ti

vity

Lepetitpermetd’indiquerquel’onvaredéfiniruneméthodequiexistaitauparavant dans la classe parente, ce qui est logique puisque vous saviez déjà qu’une activité avait une méthode    etquenotreclassehéritaitde    .

i

L’instruction@Overrideestfacultative.Ellepermetaucompilateurd’optimiserlebytecode,mais,siellenefonctionnepaschezvous,n’insistezpas,supprimez-la.

Cetteméthodeestlapremièrequiestlancéeaudémarraged’uneapplication,maiselleestaussi appeléeaprèsqu’uneapplicationaététuéeparlesystèmeenmanquedemémoire!C’estàcela quesertleparamètredetypeBundle:

— S’ils’agitdupremierlancementdel’applicationoud’undémarragealorsqu’elleavait étéquittéenormalement,ilvautnull.

— Mais s’il s’agit d’un retour à l’application après qu’elle a perdu le focus et redémarré, alorsilsepeutqu’ilnesoitpasnullsivousavezfaitensortedesauvegarderdesdonnées dedans,maisnousverronscommentdansquelqueschapitres,puisquecen’estpasune choseindispensableàsavoirpourdébuter.

Danscetteméthode,vousdevezdéfinircequidoitêtrecrééàchaquedémarrage,enparticulier l’interfacegraphique.

 

su

per

Ac

ti

vity

L’instructionsignifiequ’onfaitappelàuneméthodeouunattributquiappartientàla superclassedelaméthodeactuelle,autrementditlaclassejusteau-dessusdanslahiérarchiede l’héritage—laclasseparente,c’est-à-direlaclasse.

su

Create

 

on

Create

 

Ac

ti

vity

 

on

Create

Ainsi,                                    faitappelau                      delaclasse                      ,maispasau

Mai

nAc

ti

vity

de. Il gère bien entendu le cas où le Bundle est null. Cette instruction est obligatoire.

L’instructionsuivante:

 

seraexpliquéedansleprochainchapitre. Enrevanche,l’instructionsuivante:

 

…seraexpliquéebien,bienplustard.

Enattendant,vouspouvezremplacerlecontenudufichierparcelui-ci:

1 //N'oubliez pas de déclarer le bon package dans lequel se trouve le fichier !

2

3    import .Bundle;

4    import .Activity;

5    import ;

6    import android.widget.TextView;

7

8         public class MainActivity extends Activity {

9         private TextView texte = null;

10

11            @Override

12            protected void onCreate(Bundle savedInstanceState) {

13            super.onCreate(savedInstanceState);

14

15            texte = new TextView(this);

16            texte.setText("Bonjour, vous me devez 1 000 000€.");

17            setContentView(texte);

18            }

19            }

cou

cou

void

set

Text(String

Nousavonsajoutéunattributdeclassequej’aiappelé.CetattributestdetypeText View,j’imaginequelenomestdéjà’agitd’unevue(View)…quireprésenteun texte(Text).J’aichangéletextequ’afficheracettevueaveclaméthode texte).

void

set

Con

tent

View

(View

vue)

Text

View

La méthodepermet d’indiquer l’interface graphique de notreactivité.Sinousluidonnonsun,alorsl’interfacegraphiqueafficheraceText Viewetriend’autre.

3.4. Lancement de l’application

Souvenez-vous,jevousaiditprécédemmentqu’ilétaitpréférabledenepasfermerl’AVD,celui-ci étantlongàselancer.Sivousl’avezfermé,cen’estpasgrave,ils’ouvriratoutseul.

Pourlancernotreapplication,regardezlabarred’outilsd’Eclipseetcherchezl’encartvisibleà lafiguresuivante.

 

Figure 3.12.–Lesoutilspourexécutervotrecode

An

droid Ap

pli

ca

tion

Ilvoussuffitdecliquersurledeuxièmebouton(celuiquiressembleausymbole«play »).Si unefenêtres’ouvre(voirfiguresuivante),sélectionnez.

 

Figure 3.13.–Sélectionnez«AndroidApplication»

SivousavezunouplusieursAVDlancéset/ouunterminaldeconnecté,alorscetteécranapparaîtra:

i

Aprèsvérificationauprèsd’unavocat,cen’estpaslégalementvalable.

 

Figure 3.14.–Lescouleurspeuventêtredifférenteschezvous,cen’estpasgrave

 

— Pouravoirdesapplicationsfluidesetoptimisées,ilestessentieldebiencomprendrele cycledeviedesactivités.

Ac

ti

vity

— Chaqueécranpeutêtreconsidérécommeune,quiestconstituéd’uncontexte et d’une interface graphique. Le contexte fait le lien entre l’application et le système alors que l’interface graphique se doit d’afficher à l’écran des données et permettre à l’utilisateurd’interagiravecl’activité.

— Pour concevoir une navigation impeccable entre vos différentes activités, vous devez comprendrecommentfonctionnelapiledesactivités.Cettestructureretireraenpremier ladernièreactivitéquiauraétéajoutée.


4. Les ressources

Jevousaidéjàprésentélerépertoiresrc/quicontienttouteslessourcesdevotreprogramme. Onvamaintenants’intéresseràunautregrandrépertoire:res/.Vousl’aurezcompris,c’est danscerépertoirequesontconservéeslesressources,autrementditlesélémentsquis’afficheront àl’écranouaveclesquelsl’utilisateurpourrainteragir.

Androidestdestinéàêtreutilisésuruntrèsgrandnombredesupportsdifférents,etilfautpar conséquents’adapteràcessupports.Imaginonsqu’uneapplicationaità onprendunepetiteimage,ilfautl’agrandirpourqu’ellen’aitpasunedimensionridiculesurun grandécran.Maisenfaisantcela,l’imageperdraenqualité.Unesolutionseraitdoncd’avoirune imagepourlespetitsécrans,unepourlesécransmoyensetunepourlesgrandsécrans.C’estce genredeprécautionsqu’ilfautprendrequandonveutdévelopperpourlesappareilsmobiles.

Undesmoyensd’adapternosapplicationsàtouslesterminauxestd’utiliserles ressources.Les ressourcessontdesfichiersorganisésd’unemanièreparticulièredefaçonàcequ’Androidsache quelleressourceutiliserpours’adapteraumatérielsurlequels’exécutel’application.Commeje l’aiditprécédemment,adapternosapplicationsàtouslestypesdeterminauxestindispensable. Cetteadaptationpasseparlamaîtrisedesressources.

Pourdéclarerdesressources,onpassetrèssouventparleformatXML,c’estpourquoiunpoint surcelangageestnécessaire.

4.1. Le format XML

i

SivousmaîtrisezdéjàleXML,vouspouvezpasserdirectementàlasuite.

4.1.1. Les langages de balisage

Le XML est un langage de balisage un peu comme le HTML — le HTML est d’ailleurs indirectementundérivéduXML.Leprinciped’unlangagedeprogrammation(Java,C++,etc.) estd’effectuerdescalculs,puiséventuellementdemettreenformelerésultatdecescalculsdans uneinterfacegraphique.Àl’opposé,unlangagedebalisage(XML,donc)n’effectuenicalcul,ni affichage,maissecontentedemettreenformedesinformations.Concrètement,unlangagede balisageestunesyntaxeàrespecter,defaçonàcequ’onsachedemanièreexactelastructuration d’un fichier. Et si on connaît l’architecture d’un fichier, alors il est très facile de retrouver l’emplacementdesinformationscontenuesdanscefichieretdepouvoirlesexploiter.Ainsi,il estpossiblededévelopperunprogrammeappelé interpréteur quirécupéreralesdonnéesd’un fichier(structuréàl’aided’unlangagedebalisage).

ParexemplepourleHTML,c’estunnavigateurquiinterprètelecodeafindedonnerunsens aux instructions; si vous lisez un document HTML sans interpréteur, vous ne verrez que les sources,pasl’interprétationdesbalises.

4.1.1.1. Un exemple pratique

Imaginonsunlangagedebalisagetrèssimple,quej’utilisepourstockermescontactstéléphoniques:

 

Ce langage est très simple : les prénoms de mes contacts sont séparés par une espace. Ainsi, quandjedemanderaiàmoninterpréteurdelirelefichier,ilsauraquej’ai4contactsparceque lesprénomssontséparéspardesespaces.Illitunesuitedecaractèresetdèsqu’iltombesur uneespace,ilsaitqu’onvapasseràunautreprénom.

Onvamaintenantrendreleschosespluscomplexespourintroduirelesnumérosdetéléphone:

 

Là,l’interpréteursaitquepourchaqueligne,lapremièresuitedecaractèrescorrespondàun prénomquisetermineparundeux-points,puisontrouvelenumérodetéléphonequisetermine parunretourà,sij’aibiencodémoninterpréteur,ilsaitquelepremierprénomest « Anaïs » sans prendre l’espace à la fin, puisque ce n’est pas un caractère qui rentre dans la compositiond’unprénom.

Sij’avaisécritmonfichiersanssyntaxeparticulièreàrespecter,alorsilm’auraitétéimpossible dedévelopperuninterpréteurquipuisseretrouverlesinformations.

4.1.2. La syntaxe XML

CommepourleformatHTML,unfichierXMLdébuteparunedéclarationquipermetd’indiquer qu’onsetrouvebiendansunfichierXML.

 

Cettelignepermetd’indiquerque:

ver

sion 1.0

— OnutiliseladeXML.

— Onutilisel’encodagedescaractèresquis’appelleutf-8;c’estunefaçondedécrireles caractèresquecontiendranotrefichier.

JevaismaintenantvousdétaillerunfichierXML:

1        <?xml version="1.0" encoding="utf-8"?>

2        <bibliotheque>

3        <livre style="fantaisie">

4        <auteur>George R. R. MARTIN</auteur>

5        <titre>A Game Of Thrones</titre>

6        <langue>klingon</langue>

7        <prix>10.17</prix>

8        </livre>

9        <livre style="aventure">

10       <auteur>Alain Damasio</auteur>

11       <titre>La Horde Du Contrevent</titre>

12       <prix devise="euro">9.40</prix>

13       <recommandation note="20"/>

14       </livre>

15       </bibliotheque>

<bi

blio

theque>

L’élémentdebaseduformatXMLestlabalise.Ellecommenceparunchevronouvrant < etse termineparunchevronfermant >.Entrecesdeuxchevrons,ontrouveauminimumunmot. Par exemple. Cette balise s’appelle balise ouvrante, et autant vous le dire toutdesuite:ilvafalloirlafermer!Ilexistedeuxmanièresdefermerunebaliseouvrante:

</bi

blio

theque>

— Soitparunebalisefermante,auquelcasvouspourrezavoirducontenu entre la balise ouvrante et la balise fermante. Étant donné que notre bibliothèque est destinéeàcontenirplusieurslivres,nousavonsoptépourcettesolution.

<bi

blio

theque

/>

<re

com

man

da

tion

note="20"/>

— Soit on ferme la balise directement dans son corps :. La seule différenceestqu’onnepeutpasmettredecontenuentredeuxbalises…puisqu’iln’yena qu’une.Dansnotreexemple,nousavonsmislabalise

<re

com

man

da

tion>20</re

com

man

da

tion>

souscetteformeparchoix,maisnousaurionstoutaussibienpuutiliser ,celan’auraitpasétéuneerreur.

Cetyped’informations,qu’ilsoitferméparunebalisefermanteouqu’iln’enn’aitpasbesoin,

bi

blio

theque

s’appelleunnœud.Vousvoyezdoncquel’onaunnœudappelé,deuxnœuds appeléslivre,etc.

!

Un langage de balisage n’a pas de sens en lui-même. Dans notre exemple, notre nœud s’appellebibliotheque,onendéduit,noushumainsetpeut-être,s’ilsnouslisent,vous Cylons,qu’ilreprésenteunebibliothèque,maissionavaitdécidédel’appelerfkldjsd fljsdfkls,ilauraitautantdesensauniveauinformatique.C’estàvousd’attribuerun sensàvotrefichierXMLaumomentdel’interprétation.

<bi

blio

theque>

Le nœud, qui est le nœud qui englobe tous les autres nœuds, s’appelle la racine.IlyadansunfichierXMLaumoins une racine etauplus une racine.Ouiçaveutdire qu’ilyaexactementuneracineparfichier.

OnpeutétablirtouteunehiérarchiedansunfichierXML.Eneffet,entrelabaliseouvranteetla balisefermanted’unnœud,ilestpossibledemettred’autresnœœudsquisetrouvent dansunautrenœuds’appellentdes enfants,etlenœudencapsulants’appellele parent.

de

vise

<prix

de

vise="euro">9.40</prix>

de

vise

de

vise

de

vise

Lesnœudspeuventavoirdes attributs pourindiquerdesinformations.Dansnotreexemple, le nœud <prix> a l’attributafin de préciser en quelle devise est exprimé ce prix : pour La Horde Du Contrevent, qui vaut donc 9€40. Vous remarquerez que pour A Game Of Thrones on a aussi le nœud prix, mais il n’a pas l’attribut!C’esttoutàfaitnormal:dansl’interpréteur,siladeviseestprécisée,alors jeconsidèrequeleprixestexpriméencettedevise;maissil’attributn’estpasprécisé, alorsleprixestendollars.A Game Of Thrones vautdonc$10.17.LeformatXMLenlui-même nepeutpasdétectersil’absencedel’attributestuneanomalie,celaretireraittoutela libertéquepermetleformat.

Enrevanche,leXMLestintransigeantsurlasyntaxe.Sivousouvrezunebalise,n’oubliezpas delafermerparexemple!

4.2. Les différents types de ressources

Les ressources sont des éléments capitaux dans une application Android. On y trouve par exempledeschaînesdecaractèresoudesimages.CommeAndroidestdestinéàêtreutilisésur unegrandevariétédesupports,ilfallaittrouverunesolutionpourpermettreàuneapplication des’afficherdelamêmemanièresurunécran7”quesurunécran10”,oufaireensortequeles textess’adaptentàlalanguedel’utilisateur.C’estpourquoilesdifférentsélémentsquidoivent s’adapter de manière très précise sont organisés de manière tout aussi précise, de façon à ce qu’Androidsachequelsélémentsutiliserpourquelstypesdeterminaux.

On découvre les ressources à travers une hiérarchie particulière de répertoires. Vous pouvez remarquer qu’à la création d’un nouveau projet, Eclipse crée certains répertoires par défaut, commelemontrelafiguresuivante.

 

Figure 4.1.–L’emplacementdesressourcesauseind’unprojet

Je vous ai déjà dit que les ressources étaient divisées en plusieurs types. Pour permettre à

Android de les retrouver facilement, chaque type de ressources est associé à un répertoire particulier.Voiciuntableauquivousindiquelesprincipalesressourcesquel’onpeuttrouver, aveclenomdurépertoireassocié.Vousremarquerezqueseulslesrépertoireslespluscourants sontcrééspardéfaut.

Type

Description

Analyse syntaxique

Dessin et image

res/dra

wable

                   (                           )

On y trouve les images matricielles (les images de type PNG, JPEG ou

encore GIF) ainsi que des fichiers XML qui

permettent de décrire des dessins simples (par

exemple des cercles ou des carrés).

Oui

Miseenpageouinterface

graphique

(res/layout)

LesfichiersXMLqui représententladispositiondes vues(onaborderacetaspect, quiesttrèsvaste,dansla prochainepartie).

Exclusivement

Menu

Les fichiers XML pour pouvoir constituerdesmenus.

Exclusivement

(

res/menu

)

Donnéebrute (res/raw)

Donnéesdiversesauformatbrut. Ces données ne sont pas des fichiers de ressources standards, on pourrait y mettre de la musiqueoudesfichiersHTMLpar exemple.

Le moins possible

Différentesvariables

res/va

lues

(                        )

Il est plus difficile de cibler les ressources qui appartiennent à cette catégorie tant elles sont nombreuses.Onytrouveentre autre des variables standards, comme des chaînes de caractères, des dimensions, des couleurs,etc.

Exclusivement

         

Lacolonne«Analysesyntaxique»indiquelapolitiqueàadopterpourlesfichiersXMLdece répertoire.Ellevaut:

— «Exclusivement»,silesfichiersdecetteressourcesonttoutletempsdesfichiersXML.

dra

wable/

— «Oui»,silesfichierspeuventêtred’unautretypequeXML,enfonctiondecequ’on veutfaire.Ainsi,danslerépertoire,onpeutmettredesimagesoudesfichiers XMLdontlecontenuserautiliséparuninterpréteurpourdessinerdesimages.

— « Le moins possible », si les fichiers doivent de préférence ne pas être de type XML. Pourquoi?Parcequetouslesautresrépertoiressontsuffisantspourstockerdesfichiers

XML.Alors,sivousvoulezplacerunfichierXMLdanslerépertoireraw/,c’estqu’ilne trouvevraiment passaplacedansunautrerépertoire.

Il existe d’autres répertoires pour d’autres types de ressources, mais je ne vais pas toutes vous les présenter. De toute manière, on peut déjà faire des applications complexes avec ces ressources-là.

×

Ne mettez pas de ressources directement dans res/, sinon vous aurez une erreur de compilation!

4.3. L’organisation

res/dra

wable/

res/dra

wable/

Si vous êtes observateurs, vous avez remarqué sur l’image précédente que nous avions trois répertoires,alorsquedansletableauquenousvenonsdevoir,jevousdisais quelesdrawablesallaienttousdanslerépertoireetpointbarre!C’esttoutà faitnormaletcen’estpasanodindutout.

Commejevousledisais,nousavonsplusieursressourcesàgérerenfonctiondumaté emplacementsindiquésdansletableauprécédentsontlesemplacementspardéfaut,c’est-à-dire qu’il s’agit des emplacements qui visent le matériel le plus générique possible. Par exemple, vouspouvezconsidérerquelematérielleplusgénériqueestunsystèmequi n’est pas en coréen, alors vous allez mettre dans le répertoire par défaut tous les fichiers qui correspondent aux systèmesquinesontpasencoréen(parexemplelesfichiersdelangue).Pourplacerdesressources destinéesauxsystèmesencoréen,onvacréerunsous-répertoireetpréciserqu’ilestdestinéaux systèmesencoréen.Ainsi,automatiquement,quandunutilisateurfrançaisouanglaisutilisera votreapplication,Androidchoisiralesfichiersdansl’emplacementpardéfaut,alorsquesic’est unutilisateurcoréen,ilirachercherdanslessous-répertoiresconsacrésàcettelangue.

quan

ti

fi

ca

teur 1><

-

quan

ti

fi

ca

teur 2>…<

-

quan

ti

fi

ca

teur N>]

End’autrestermes,enpartantdunomdurépertoirepardéfaut,ilestpossibledecréerd’autres répertoiresquipermettentdepréciseràquelstypesdematérielslesressourcescontenuesdansce répertoiresontdestinées.Lesrestrictionssontreprésentéespardes quantificateurs etcesont cesquantificateursquivouspermettrontdepréciserlematérielpourlequellesfichiersdansce répertoiresontdestinés.Lasyntaxeàrespecterpeutêtrereprésentéeainsi:res/<type_de_res source>[<-

Autrement dit, on peut n’avoir aucun quantificateur si l’on veut définir l’emplacement par défaut,ouenavoirunpourréduirelechampdedestination,deuxpourréduireencoreplus,etc. Cesquantificateurssontséparésparuntiret.SiAndroidnetrouvepasd’emplacementdontle nomcorrespondeexactementauxspécificationstechniquesduterminal,ilchercheraparmiles autresrépertoiresquiexistentlasolutionlaplusproche.Jevaisvousmontrerlesprincipaux quantificateurs(ilyenaquatorzeentout,dontunbonpaquetqu’onutiliserarement,j’aidonc décidédelesignorer).

i

Vousn’allezpascomprendrel’attributPrioritétoutdesuite,d’ailleursilestpossible quevousnecompreniezpastoutimmédiatement.Lisezcettepartietranquillement,zieutez ensuitelesexemplesquisuivent,puisrevenezàcettepartieunefoisquevousaureztout compris.

4.3.0.1. Langue et région

Prio

rité

: 2 Lalanguedusystèmedel’utilisateur.Onindiqueunelanguepuis,éventuellement, onpeutpréciserunerégionavec«-r».Exemples:

— enpourl’anglais;

— frpourlefrançais;

— fr-rFRpourlefrançaismaisuniquementceluiutiliséenFrance; — fr-rCApourlefrançaismaisuniquementceluiutiliséauQuébec; — Etc.

4.3.0.2. Taille de l’écran

Prio

rité

: 3 Ils’agitdelatailledeladiagonaledel’écran:

— smallpourlesécransdepetitetaille;

nor

mal

—pourlesécransstandards;

— largepourlesgrandsécrans,commedanslestablettestactiles;

— xlargepourlestrèsgrandsécrans,làonpensecarrémentauxtéléviseurs.

4.3.0.3. Orientation de l’écran

Prio

rité

: 5 Ilexistedeuxvaleurs:

— port:c’estlediminutifdeportrait,doncquandleterminalestenmodeportrait; — land:c’estlediminutifdelandscape,doncquandleterminalestenmodepaysage.

4.3.0.4. Résolution de l’écran

Prio

rité

: 8

— ldpi:environ120dpi;

— mdpi:environ160dpi;

— hdpi:environ240dpi;

— xhdpi:environ320dpi(disponibleàpartirdel’API8uniquement);

— nodpi:pournepasredimensionnerlesimagesmatricielles(voussavez,JPEG,PNGet GIF!).

4.3.0.5. Version d’Android

Prio

rité

: 14 Ils’agitduniveaudel’API(v3,v5,v7(c’estcellequ’onutilisenous!),etc.).

res/dra

wable

res/dra

wable

res/dra

wable

Regardezl’imageprécédente(quidetoutefaçonreprésentelesrépertoirescréésautomatiquement pour tous les projets), que se passe-t-il si l’écran du terminal de l’utilisateur a une grande résolution?Androidirachercherdans-hdpi!L’écranduterminaldel’utilisateur a une petite résolution? Il ira chercher dans-ldpi/! L’écran du terminal de l’utilisateuraunetrèsgranderésolution?Ehbien…ilirachercherdans-hdpi puisqu’ils’agitdelasolutionlaplusprochedelasituationmatérielleréelle.

4.3.1. Exemples et règles à suivre

res/dra

wable

res/dra

wable

—-smallpouravoirdesimagesspécifiquementpourlespetitsécrans.

—-largepouravoirdesimagesspécifiquementpourlesgrandsécrans. — res/layout-frpouravoirunemiseenpagespécifiquedestinéeàtousceuxquiontun systèmeenfrançais.

— res/layout-fr-rFR pour avoir une mise en page spécifique destinée à ceux qui ont choisilalangueFrançais (France).

res/va

lues

—-fr-rFR-portpourdesdonnéesquis’afficherontuniquementàceuxqui ont choisi la langue Français (France) et dont le téléphone se trouve en orientation portrait.

res/va

lues

—-port-fr-rFR n’est pas possible, c’est à ça que servent les priorités : il faut impérativement mettre les quantificateurs par ordre croissant de priorité.Lapriorité delalangueest2,celledel’orientationest5,comme2<5ondoitplacerleslangues avantl’orientation.

— res/layout-fr-rFR-enn’estpaspossiblepuisqu’onadeuxquantificateursdemême prioritéetqu’ilfauttoujoursrespecterl’ordrecroissantdespriorités.Ilnousfaudracréer unrépertoirepourlefrançaisetunrépertoirepourl’anglais.

dra

wable/

Touslesrépertoiresderessourcesquisontdifférenciéspardesquantificateursdevrontavoirle mêmecontenu:onindiqueàAndroiddequelleressourceonabesoin,sanssepréoccuperdans quelrépertoireallerlechercher,Androidleferatrè’imageprécédente, vousvoyezquel’icônesetrouvedanslestroisrépertoires,sinonAndroidnepourrait paslatrouverpourlestroistypesdeconfiguration.

4.3.2. Mes recommandations

Voici les règles que je respecte pour la majorité de mes projets, quand je veux faire bien les choses:

res/dra

wable

res/dra

wable

res/dra

wable

—-hdpi;

—-ldpi;

—-mdpi;

res/dra

wable

— Pasde;

— res/layout-land; — res/layout.

Unemiseenpagepourchaqueorientationetdesimagesadaptéespourchaqueré quantificateurdel’orientationestsurtoututilepourl’interfacegraphique.Lequantificateurde larésolutionsertplutôtànepasavoiràajusteruneimageetparconséquentànepasperdrede qualité.

Pourfinir,sachezquelesécransdetaillesmalletxlargesefontrares.

4.4. Ajouter un fichier avec Eclipse

Heureusement,lesdéveloppeursdel’ADTontpenséànousencréantunpetitmenuquivous aideraàcréerdesrépertoiresdemanièresimple,sansavoiràretenirdesyntaxe.Enrevanche,il vousfaudraparlerunpeuanglais,jelecrains.Faitesunclicdroitsurn’importequelrépertoire ou fichier de votre projet. Vous aurez un menu un peu similaire à celui représenté à l’image suivante,quis’affichera.

 

Figure 4.2.–L’ADTpermetd’ajouterdesrépertoiresfacilement

An

droid XML File

An

droid XML File

Danslesous-menuNew,soitvouscliquezdirectementsur,soit,s’iln’est pasprésent,vousdevrezcliquersurOther,puischercherdanslerépertoire

An

droid

.CetteopérationouvriraunassistantdecréationdefichiersXMLvisibleàlafigure suivante.

 

Figure 4.3.–L’assistantdecréationdefichiersXML

But

ton

Text

View

Lepremierchampvouspermetdesélectionnerletypederessourcesdésiré.Vousretrouverez lesnomsdesressourcesquenousavonsdécritesdanslepremiertableau,ainsiqued’autresqui nousintéressentmoins,àl’exceptionderawpuisqu’iln’estpasdestinéàcontenirdesfichiers XML.Àchaquefoisquevouschangezdetypederessources,lasecondepartiedel’écranchange et vous permet de choisir plus facilement quel genre de ressources vous souhaitez créer. Par exemplepourLayout,vouspouvezchoisirdecréerunbouton()ouunencartdetexte () champFilevouspermetquantàluidechoisirlenomdufichieràcréer.

Fi

nish

Unefoisvotresélectionfaite,vouspouvezcliquersurNextpourpasseràl’écransuivant(voir figuresuivante)quivouspermettradechoisirdesquantificateurspourvotreressourceou pourquelefichiersoitcréédansunrépertoiresansquantificateurs.

 

Figure 4.4.–Cettefenêtrevouspermetdechoisirdesquantificateurspourvotreressource

Cettesectioncontientdeuxlistes.Celledegaucheprésentelesquantificateursàappliquerau répertoirededestination.Vousvoyezqu’ilssontrangésdansl’ordredeprioritéquej’aiindiqué.

?

Maisilyabeaucoupplusdequantificateursetderessourcesquecequetunousasindiqué!

’écrispasunedocumentationofficiellepourAndroid.Sijelefaisais,j’enlaisseraisplus d’unconfusetvousauriezunnombreimpressionnantd’informationsquinevousserviraientpas ’attelleàvousapprendreàfairedejoliesapplicationsoptimiséesetfonctionnelles, pasàfairedevousdesencyclopédiesvivantesd’Android.

Fol

der

Fol

der

Le champ suivant,, est le répertoire de destination. Quand vous sélectionnez des quantificateurs, vous pouvez avoir un aperçu en temps réel de ce répertoire. Si vous avez commisuneerreurdanslesquantificateurs,parexemplechoisiunelanguequin’existepas,le quantificateurnes’ajouterapasdanslechampdurépertoire.Sicechampnevoussemblepas correctvis-à-visdesquantificateurssélectionnés,c’estquevousavezfaitunefauted’orthographe. Sivousécrivezdirectementunrépertoiredans,lesquantificateursindiquéss’ajouteront danslalistecorrespondante.

!

À mon humble avis, la meilleure pratique est d’écrire le répertoire de destination dans Folder et de regarder si les quantificateurs choisis s’ajoutent bien dans la liste. Mais personnenevousenvoudrad’utiliserl’outilprévupour.

Cetoutilpeutgérerleserreursetconflits.Sivousindiquezcommenom«strings»etcomme ressourceunedonnée(«values»),vousverrezunpetitavertissementquis’afficheraenhautde lafenêtre,puisquecefichierexistedéjà(ilestcréépardéfaut).

4.4.1. Petit exercice

Vérifions que vous avez bien compris : essayez, sans passer par les outils d’automatisation, d’ajouter une mise en page destinée à la version 8, quand l’utilisateur penche son téléphone enmodeportraitalorsqu’ilutiliselefrançaisdesBelges(fr-rBE)etquesonterminalaune résolutionmoyenne.

Fol

der

Fi

nish

Ledoitcontenir exactement /res/layout-fr-rBE-port-mdpi-v8. Ilvoussuffitdecliquersursiaucunmessaged’erreurnes’affiche.

4.5. Récupérer une ressource

4.5.1. La classe R

Onpeutaccéderàcetteclassequisetrouvedanslerépertoiregen/(commegenerated,c’està-dire que tout ce qui se trouvera dans ce répertoire sera généré automatiquement), comme indiquéàlafiguresuivante.

</votre_package>

Ouvrezdonccefichieretregardezlecontenu.

1        public final class R {

2        public static final class attr {

3        }

4        public static final class dimen {

5        public static final int padding_large=0x7f040002;

6        public static final int padding_medium=0x7f040001;

7        public static final int padding_small=0x7f040000;

8        }

9        public static final class drawable {

10       public static final int ic_action_search=0x7f020000;

11       public static final int ic_launcher=0x7f020001;

12       }

13       public static final class id {

14       public static final int menu_settings=0x7f080000;

15       }

16       public static final class layout {

17       public static final int activity_main=0x7f030000;

18       }

19       public static final class menu {

20       public static final int activity_main=0x7f070000;

21       }

22       public static final class string {

23       public static final int app_name=0x7f050000;

24       public static final int hello_world=0x7f050001;

25       public static final int menu_settings=0x7f050002;

26       public static final int title_activity_main=0x7f050003;

27       }

28       public static final class style {

29       public static final int AppTheme=0x7f060000;

30       }

31       }

Çavousrappellequelquechose?Comparonsavecl’ensembledesressourcesquecomportenotre projet(voirfiguresuivante).

 

Figure 4.5.–Tiens,cesnomsmedisentquelquechose…

On remarque en effet une certaine ressemblance, mais elle n’est pas parfaite! Décryptons certaineslignesdececode. 4.5.1.1. La classe layout

 

pu

blic

sta

tic

fi

nal

Ils’agitd’uneclassedéclaréedansuneautreclasse:c’estcequis’appelleuneclasse interne. Laseuleparticularitéd’uneclasseinterneestqu’elleestdéclaréedansuneautreclasse,maiselle peutagircommetouteslesautresclasses.Cependant,pouryaccéder,ilfautfaireréférenceàla classequilacontient.Cetteclasseestdetypeetdenomlayout.

pu

blic

— Un élémentest un élément auquel tout le monde peut accéder sans aucune restriction.

sta

tic

— Lemot-clé,danslecasd’uneclasseinterne,signifiequelaclassen’estpasliée àuneinstanciationdelaclassequil’encapsule.Pouraccéderàlayout,onnedoitpas nécessairementcréerunobjetdetypeR.OnpeutyaccéderparR.layout.

fi

nal

— Lemot-clésignifiequel’onnepeutpascréerdeclassedérivéedelayout.

pu

blic

int

 

sta

tic

 

fi

nal

Cette classe contient un unique       , affublé des modificateurs     et         . Il s’agitparconséquentd’uneconstante,àlaquellen’importequelleautreclassepeutaccédersans avoiràcréerd’objetdetypelayoutnidetypeR.

Cetentierestdelaforme0xZZZZZZZZ.Quandunentiercommencepar0x,c’estqu’ils’agitd’un nombrehexadécimal sur32bits.Sivousignorezcedontils’agit,cen’estpasgrave,dites-vous justequecetypedenombreestunnombreexactementcommeunautre,saufqu’ilrespecteces règles-ci:

— Ilcommencepar0x.

— Aprèsle0x,ontrouvehuitchiffres(oumoins,maisonpréfèremettredes0pourarriver à8chiffres):0x123estéquivalentà0x00000123,toutcomme123estlamêmechose que00000123.

— Ceschiffrespeuventallerde0à…F.C’est-à-direqu’aulieudecompter«0,1,2,3,4,5, 6,7,8,9»oncompte«0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F».A,B,C,D,EetF sontdeschiffresnormaux,banals,mêmes’ilsn’enn’ontpasl’air,c’estjustequ’iln’ya pasdechiffreaprès9,alorsilafalluimproviseraveclesmoyensdubord.Ainsi,après9 onaA,aprèsAonaB,aprèsEonaF,etaprèsFona10!Puisànouveau11,12,13, 14,15,16,17,18,19,1A,1B,etc. Regardezlesexemplessuivants:

1    int deuxNorm = 2; // Valide !

2    int deuxHexa = 0x00000002; // Valide, et vaut la même chose que « deuxNorm »

3    int deuxRed = 0x2; // Valide, et vaut la même chose que « deuxNorm » et « deuxHexa » (évidemment, 00000002, c'est la même chose que 2 !)

4    //Ici, nous allons toujours écrire les nombres hexadécimaux avec huit chiffres, même les 0 inutiles !

5    int beaucoup = 0x0AFA1B00; // Valide !

6    int marcheraPas = 1x0AFA1B00; // Non ! Un nombre hexadécimal commence toujours par « 0x » !

7    int marcheraPasNonPlus = 0xG00000000; // Non ! Un chiffre hexadécimal va de 0 à F, on n'accepte pas les autres lettres !

8    int caVaPasLaTete = 0x124!AZ5%; // Alors là c'est carrément n'importe quoi !

ac

ti

vity_main

ac

ti

ac

ti

vity_main

Cetentieralemêmenomqu’unfichierderessources(),toutsimplementparce qu’il représente ce fichier(). On ne peut donc avoir qu’un seul attribut de ce nom-là dans la classe, puisque deux fichiers qui appartiennent à la même ressource se trouventdans le même répertoire et ne peuventpar conséquentpas avoir le même nom. Cet entierestunidentifiantuniquepourlefichierdemiseenpagequis’ unjouronveututiliserouaccéderàcettemiseenpagedepuisnotrecode,onyferaappelà l’aidedecetidentifiant.

4.5.1.2. La classe drawable

1       public static final class drawable {

2       public static final int ic_action_search=0x7f020000;

3       public static final int ic_launcher=0x7f020001;

4       }

ic_laun

cher

dra

wable

Contrairementaucasprécédent,onaunseulentierpourplusieursfichiersquiontlemêmenom! Onavudanslasectionprécédentequ’ilfallaitnommerdefaçonidentiquecesfichiersquiont lamêmefonction,pourunemêmeressource,maisavecdesquantificateursdifférents.Ehbien, quandvousferezappelàl’identificateur,Androidsauraqu’illuifautlefichieret détermineraautomatiquementquelestlerépertoireleplusadaptéàlasituationdumatériel parmilesrépertoiresdesressourcesdrawable,puisqu’onsetrouvedanslaclasse.

4.5.1.3. La classe string

1       public static final class string {

2       public static final int app_name=0x7f050000;

3       public static final int hello_world=0x7f050001;

4       public static final int menu_settings=0x7f050002;

5       public static final int title_activity_main=0x7f050003;

6       }

res/va

Cettefois,sionaquatreentiers,c’esttoutsimplementparcequ’onaquatrechaînesdecaractères danslefichier,quicontientleschaînesdecaractères(quisontdes données).Vouspouvezlevérifierparvous-mê.

×

Jenelerépéteraijamaisassez,nemodifiez jamais cefichierparvous-mêmes.Eclipses’en occupera.

Ilexisted’autresvariablesdontjen’aipasdiscuté,maisvousaveztoutcomprisdéjàavecce quenousvenonsd’étudier.

4.5.2. Application

4.5.2.1. Énoncé

Text

View

 

Text

View

J’ai créé un nouveau projet pour l’occasion, mais vous pouvez très bien vous amuser avec le premier projet. L’objectif ici est de récupérer la ressource de type chaîne de caractères qui s’appelle hello_world (créée automatiquement par Eclipse) afin de la mettre comme texte dansun      .Onafficheraensuitele .

pu

blic

fi

nal

void

set

Text

(int

id)

Text

View

Onutiliseralaméthode(idétantl’identifiantdela ressource)delaclasse.

4.5.2.2. Solution

 

Commeindiquéauparavant,onpeutaccé récupèredanslaclasseRl’identificateurdelaressourcedunomhello_worldquisetrouvedans laclassestring,puisqu’ils’agitd’unechaînedecaractères,doncR.string.hello_world.

?

Et si je mets à la place de l’identifiant d’une chaîne de caractères un identifiant qui correspondàunautretypederessources?

pu

blic

String

toS

tring()

pu

blic

String

toS

tring()

Sys

.println

toS

tring()

Eh bien, les ressources sont des objets Java comme les autres. Par conséquent ils peuvent aussiposséderuneméthode!Pourceuxquil’auraientoublié,la méthodeestappeléesurunobjetpourletransformerenchaîne decaractères,parexemplesionveutpasserl’objetdansun.Ainsi,si vous mettez une autre ressource qu’une chaîne de caractères, ce sera la valeur rendue par la méthodequiseraaffichée.

Essayezparvous-mêmes,vousverrezcequiseproduit.Soyezcurieux,c’estcommeçaqu’on apprend!

4.5.3. Application

4.5.3.1. Énoncé

Text

View

Jevousproposeunautreexercice.Dansleprécédent,learécupérél’identifiantet aétéchercherlachaînedecaractèresassociéepourl’afficher.Danscetexercice,onvaplutôt récupérerlachaînedecaractèrespourlamanipuler.

4.5.3.2. Instructions

Re

source

pu

blic

— Onvarécupérerlegestionnairederessourcesafind’allerchercherlachaînedecaractères. C’estunobjetdelaclassequepossèdenotreactivitéetquipermetd’accéder aux ressources de cette activité. On peut le récupérer grâce à la méthode

Re

sources

ge

tRe

sources()

.

string

getS

tring(int

id)

— On récupère la chaîne de caractères hello_world grâce à la méthode ,avecidl’identifiantdelaressource.

— Etonmodifielachaînerécupérée.

4.5.3.3. Solution

 

Ah,çaveutdirequevousaveztéléchargéuneversiond’Eclipseavecunanalyseursyntaxique XML.Enfaitsivouslancezlacompilationalorsquevousétiezentraindeconsulterunfichier

XML,alorsc’estl’analyseurquiselanceraetpaslecompilateur.Lasolutionestdoncdecliquer surn’importequelautrefichierquevouspossédezquinesoitpasunXML,puisderelancerla compilation.

 

— AumêmetitrequelelangageJavaestutilepourdéveloppervosapplication,lelangage XMLl’esttoutautantpuisqu’ilaétéchoisipourmettreenplacelesdifférentesressources devosprojets.

— Ilexiste5typesderessourcesquevousutiliserezmajoritairement:

dra

wable

—quicontienttoutes les images matricielles et les fichiersXML décrivant desdessinssimples.

— layout qui contient toutes les interfaces que vous attacherez à vos activités pour mettreenplacelesdifférentesvues.

— menuquicontienttouteslesdéclarationsd’élémentspourconfectionnerdesmenus.

— rawquicontienttouteslesautresressourcesauformatbrut.

va

lues

—quicontientdesvaleurspourunlargechoixcommeleschaînesdecaractères, lesdimensions,lescouleurs,etc.

— Lesquantificateurssontutiliséspourciblerprécisémentuncertainnombredepriorités; àsavoirlalangueetlarégion,latailledel’écran,l’orientationdel’écran,larésolution del’écranetlaversiond’Android.

— Chaque ressource présente dans le dossier res de votre projet génère un identifiant unique dans le fichier R.java pour permettre de les récupérer dans la partie Java de votreapplication.


Deuxième partie Création d’interfaces graphiques

5.   Constitution des interfaces graphiques

Bien,maintenantquevousavezcomprisleprincipeetl’utilitédesressources,voyonscomment appliquernosnouvellesconnaissancesauxinterfacesgraphiques.Avecladiversitédesmachines souslesquellesfonctionneAndroid,ilfautvraimentexploitertouteslesopportunitésoffertes par les ressources pour développer des applications qui fonctionneront sur la majorité des terminaux.

Une application Android polyvalente possède un fichier XML pour chaque type d’écran, de façonàpouvoirs’adapter.Eneffet,sivousdéveloppezuneapplicationuniquementàdestination despetitsécrans,lesutilisateursdetablettestrouverontvotretravailillisibleetnel’utiliseront pasdutout.Icionvavoirunpeuplusenprofondeurcequesontlesvues,commentcréerdes ressources d’interface graphique et comment récupérer les vues dans le code Java de façon à pouvoirlesmanipuler.

5.1. L’interface d’Eclipse

Labonnenouvelle,c’estqu’Eclipsenouspermetdecréerdesinterfacesgraphiquesà esteneffetpossibled’ajouterunélémentetdelepositionnergrâceàsasouris.Lamauvaise, c’estquec’estbeaucoupmoinsprécisqu’unvéritablecodeetqu’enplusl’outilestplutôtbuggé. Toutdemême,voyonsvoirunpeucommentcelafonctionne.

ac

ti

Ouvrezleseulfichierquisetrouvedansleré’agitnormalementdu fichier.Unefoisouvert,vousdevriezavoirquelquechosequiressembleà lafiguresuivante.

 

Figure 5.1.–Lefichierestouvert

Cet outil vous aide à mettre en place les vues directement dans le layout de l’application, représenté par la fenêtre du milieu. Comme il ne peut remplacer la manipulation de fichiers XML,jeneleprésenteraipasdanslesdétails.Enrevanche,ilesttrèspratiquedèsqu’ils’agit d’afficherunpetitaperçufinaldecequedonneraunfichierXML.

5.1.1. Présentation de l’outil

C’estàl’aidedumenuenhaut,celuivisibleàlafiguresuivante,quevouspourrezobserverle résultatavecdifférentesoptions.

 

Figure 5.2.–Menud’options

Ce menu est divisé en deux parties : les icônes du haut et celles du bas. Nous allons nous concentrersurlesicônesduhautpourl’instant(voirfiguresuivante).


 

Figure 5.3.–Lesicônesduhautdumenud’options

— Lapremièrelistedéroulantevouspermetdenaviguerrapidemententrelesrépertoiresde layouts.Vouspouvezainsicréerdesversionsalternativesàvotrelayoutactuelencréant desnouveauxrépertoiresdifférenciésparleursquantificateurs.

— Ladeuxièmepermetd’observerlerésultatenfonctiondedifférentesrésolutions.Lechiffre indiquelatailledeladiagonaleenpouces(sachantqu’unpoucefait2,54centimètres,la diagonaledu Nexus One fait 3,7×2,54 = 9,4 cm)etlasuitedelettresenmajusculesla résolutiondel’écran.Pourvoiràquoicorrespondentcestermesentailleréelle,n’hésitez pasàconsultercetteimageprisesurWikipédia  .

— Latroisièmepermetd’observerl’ trouve-t-onenmodeportraitouenmodepaysage?Lepériphériqueest-ilattachéàun matérield’amarrage?Enfin,fait-iljourounuit?

— Lasuivantepermetd’associerunthèmeàvotreactivité.Nousaborderonsplustardles thèmesetlesstyles.

— L’avant-dernière permet de choisir une langue si votre interface graphique change en fonctiondelalangue.

— Etenfinladernièrevérifielecomportementenfonctiondelaversiondel’API,sivous aviezdéfinidesquantificateursàceniveau-là.

Occupons-nousmaintenantdeladeuxièmepartie,toutd’abordaveclesicônesdegauche,visibles àlafiguresuivante.

 

Figure 5.4.–Lesicônesdegauchedubasmenu

Cesboutonssontspécifiquesàuncomposantetàsonlayoutparent,contrairementauxboutons précédentsquiétaientspécifiquesàl’outil.Ainsi,sivousnesélectionnezaucunevue,cesera la vue racine qui sera sélectionnée par défaut. Comme les boutons changent en fonction du composantetdulayoutparent,jenevaispaslesprésenterendétail. Enfinl’ensembledeboutonsdedroite,visiblesàlafiguresuivante.

 

Figure 5.5.–Lesicônesdedroitedubasmenu

— Lepremierboutonpermetdemodifierl’affichageenfonctiond’unerésolutionquevous èspratiquepourtester,sivousn’avezpastouslesterminauxpossibles.

— Ledeuxièmefaitensortequel’interfacegraphiquefasseexactementlatailledelafenêtre danslaquelleellesetrouve.

— Lesuivantremetlezoomà100%.

— Enfinlesdeuxsuivantspermettentrespectivementdedézoomeretdezoomer.

!

Rien, jamais rien ne remplacera un test sur un vrai terminal. Ne pensez pas que parce votreinterfacegraphiqueestesthétiquedanscetoutilelleleseraaussienvrai.Sivous n’avezpasdeterminal,l’émulateurvousdonneradéjàunmeilleuraperçudelasituation.

5.1.2. Utilisation

Text

View

Autantcetoutiln’estpasaussiprécis,pratiqueetsurtoutdénuédebugsqueleXML,autantil peuts’avérerpratiquepourcertainesmanipulationsdebase.Ilpermetparexempledemodifier lesattributsd’unevueàlavolée.Surlafiguresuivante,vousvoyezaucentredelafenêtreune activitéquinecontientqu’un.Sivouseffectuezunclicdroitdessus,vouspourrez voirlesdifférentesoptionsquiseprésententàvous,commelemontrelafiguresuivante.

 

Figure 5.6.–Unmenuapparaîtlorsd’unclicdroitsurunevue

Pro

per

ties

Vouscomprendrezplustardlasignificationdecestermes,maisretenezbienqu’ilestpossible demodifierlesattributsviaunclicdroit.Vouspouvezaussiutiliserl’encarten basàdroite(voirfiguresuivante).

 

Figure 5.7.–L’encart«Properties»

Deplus,vouspouvezplacerdifférentesvuesencliquantdessusdepuislemenudegauche,puis enlesdéposantsurl’activité,commelemontrelafiguresuivante.

 

Figure 5.8.–Ilestpossibledefaireuncliquer/glisser

Ilvousestensuitepossibledelesagrandir,delesrapetisseroudelesdéplacerenfonctionde vosbesoins,commelemontrelafiguresuivante.

 

Figure 5.9.–Vouspouvezredimensionnerlesvues

ac

ti

Nous allons maintenant voir la véritable programmation graphique. Pour accéder au fichier XMLcorrespondantàvotreprojet,cliquezsurledeuxièmeonglet.

!

Dans la suite du cours, je considérerai le fichier vierge de toute modification,alorssivousavezfaitdesmanipulationsvousaurezdesdifférencesavecmoi.

5.2. Règles générales sur les vues

5.2.1. Différenciation entre un layout et un widget

Normalement,EclipsevousacrééunfichierXMLpardéfaut:

1       <RelativeLayout xmlns:android=";

2       xmlns:tools=";

3       android:layout_width="fill_parent"

4       android:layout_height="fill_parent" >

5

6        <TextView

7        android:layout_width="wrap_content"

8        android:layout_height="wrap_content"

9        android:layout_centerHorizontal="true"

10       android:layout_centerVertical="true"

11       android:padding="@dimen/padding_medium"

12       android:text="@string/hello_world"

13       tools:context=".MainActivity" />

14

15 </RelativeLayout>

Laracinepossèdedeuxattributssimilaires:

xmlns:tools="http://sche

;

droid" et. Ces deux lignes per-

xmlns:an

droid="http://sche

mettent d’utiliser des attributs spécifiques à Android. Si vous ne les mettez pas, vous ne pourrezpasutiliserlesattributsetlefichierXMLseraunfichierXMLbanalaulieud’êtreun fichierspécifiqueàAndroid.Deplus,Eclipserefuseradecompiler.

Re

la

ti

ve

Layout

Text

View

On trouve ensuite une racine qui s’appelle. Vous voyez qu’elle englobe un autrenœudquis’!Çavousconnaissez!Commeindiquéprécédemment, uneinterfacegraphiquepourAndroidestconstituéeuniquementdevues.Ainsi,touslesnœuds decesfichiersXMLserontdesvues.

Revenonsàlapremiè Swing vousavezdéjàrencontréces objetsgraphiquesquienglobentd’autresobjetsgraphiques.Onlesappelleenanglaisdeslayouts etenfrançaisdesgabarits.Unlayoutestdoncunevuespécialequipeutcontenird’autresvues et qui n’est pas destinée à fournir du contenu ou des contrôles à l’utilisateur. Les layouts se contententdedisposerlesvuesd’unecertainefaçon.Lesvuescontenuessontlesenfants,lavue englobante est le parent, comme en XML. Une vue qui ne peut pas en englober d’autres est appeléeunwidget (composant,enfrançais). i

UnlayouthéritedeViewGroup(classeabstraite,qu’onnepeutdoncpasinstancier),et ViewGrouphéritedeView.Doncquandjedisqu’unViewGrouppeutcontenirdesView, c’estqu’ilpeutaussicontenird’autresViewGroup!

Vouspouvezbiensûravoirenracineunsimplewidgetsivoussouhaitezquevotremiseenpage consisteencetuniquewidget.

5.2.2. Attributs en commun

Comme beaucoup de nœuds en XML, une vue peut avoir des attributs, qui permettent de modulercertainsdesesaspects.Certainsdecesattributssontspécifiquesàdesvues,d’autres sontcommuns.Parmicesderniers,lesdeuxlespluscourantssontlayout_width,quidéfinit la largeur que prend la vue (la place sur l’axe horizontal), et layout_height, qui définit la hauteurqu’elleprend(laplacesurl’axevertical).Cesdeuxattributspeuventprendreunevaleur parmilestroissuivantes:

fill_pa

rent

—:signifiequ’elleprendraautantdeplacequesonparentsurl’axeconcerné;

— wrap_content : signifie qu’elle prendra le moins de place possible sur l’axe concerné. Parexemplesivotrevueafficheuneimage,elleprendraàpeinelatailledel’image,si elleafficheuntexte,elleprendrajustelataillesuffisantepourécrireletexte; — Unevaleurnumériquepréciseavecuneunité.

Jevousconseilledeneretenirquedeuxunités:

— dpoudip:ils’agitd’uneunitéquiestindépendantedelarésolutiondel’écran.Eneffet, ilexisted’autresunitéscommelepixel(px)oulemillimètre(mm),maiscelles-civarient d’unécranàl’autre…Parexemplesivousmettezunetaillede500dppourunwidget,il aura toujours la même dimension quelque soit la taille de l’écran. Si vous mettez une dimension de 500 mm pour un widget, il sera grand pour un grand écran… et énorme pourunpetitécran.

— sp:cetteunitérespectelemêmeprincipe,saufqu’elleestplusadaptéepourdéfinirla tailled’unepolicedecaractères.

!

Depuisl’API8(danscecours,ontravaillesurl’API7),vouspouvezremplacerfill_pa ’agitd’exactementlamêmechose,maisenplusexplicite.

?

Il y a quelque chose que je trouve étrange : la racine de notre layout, le nœud Rela tiveLayout, utilise fill_parent en largeur et en hauteur. Or, tu nous avais dit que cetattributsignifiaitqu’onprenaittoutelaplaceduparent…Maisiln’apasdeparent, puisqu’ils’agitdelaracine!

C’estparcequ’onnevousditpastout,onvouscachedeschoses,lavéritéestailleurs.Enfait, mêmenotreracineaunevueparent,c’estjustequ’onn’yapasaccès.Cettevueparentinvisible prendtoutelaplacepossibledansl’écran.

Vouspouvezaussidéfinirunemargeinternepourchaquewidget,autrementditl’espacement entrelecontourdelavueetsoncontenu(voirfiguresuivante).

 

Figure 5.10.–Ilestpossiblededéfinirunemargeinternepourchaquewidget

an

droid:pad

ding

Ci-dessousavecl’attributdanslefichierXMLpourdéfiniruncarréd’espacement;lavaleurserasuivied’uneunité,10.5dpparexemple.

 

pu

blic

void

set

Pad

ding

(int

left,

int

top,

int

right,

LaméthodeJavaéquivalenteest

int

bot

tom)

.

 

an

droid:pad

ding

Bot

tom

an

droid:pad

din

gLeft

an

droid:pad

din

gRight

an

droid:pad

ding

Top

EnXMLonpeutaussiutiliserdesattributspourdéfiniruniquement l’espacementavecleplancher,pourdéfiniruniquementl’espacement entrelebordgaucheduwidgetetlecontenu,pourdéfiniruniquement l’espacementde droite et enfinpour définir uniquementl’espacement avecleplafond.

5.3. Identifier et récupérer des vues

5.3.1. Identification

Vousvousrappelezcertainementqu’ bien,ilestpossibled’accéderàuneressourceàpartirdesonidentifiantàl’aidedelasyntaxe @signifiequ’onvaparlerd’unidentifiant,leXestlaclasseoùsesituel’identifiantdans R.javaetenfin,leYseralenomdel’identifiant.Biensûr,lacombinaisonX/Ydoitpointersur unidentifiantquiexiste.Reprenonsnotreclassecrééepardéfaut:

1       <RelativeLayout xmlns:android=";

2       xmlns:tools=";

3       android:layout_width="fill_parent"

4       android:layout_height="fill_parent" >

5

6        <TextView

7        android:layout_width="wrap_content"

8        android:layout_height="wrap_content"

9        android:layout_centerHorizontal="true"

10       android:layout_centerVertical="true"

11       android:padding="@dimen/padding_medium"

12       android:text="@string/hello_world"

13       tools:context=".MainActivity" />

14

15 </RelativeLayout>

Text

View

ac

ti

On devine d’après la ligne surlignée que leaffichera le texte de la ressource qui se trouve dans la classe String de R.java et qui s’appelle hello_world. Enfin, vous vous rappelezcertainementaussiquel’onarécupérédesressourcesàl’aidedel’identifiantquelefichier R.javacréaitautomatiquementdanslechapitreprécédent.Sivousallezvoircefichier,vous constaterezqu’ilnecontientaucunementionànosvues,justeaufichier.

Ehbien,c’esttoutsimplementparcequ’ilfautcréercetidentifiantnous-mêmes(danslefichier XMLhein,nemodifiezjamaisR.javaparvous-mêmes,malheureux!).

an

droid:id

Afindecréerunidentifiant,onpeutrajouteràchaquevueunattribut.Lavaleur doitê+signifiequ’onparled’unidentifiantquin’estpasencoredéfini. Envoyantcela,Androidsaitqu’ildoitcréerunattribut. i

Lasyntaxe@+X/Yestaussiutiliséepourfaireréférenceàl’identifiantd’unevuecrééeplus tarddanslefichierXML.

LeXestlaclassedanslaquelleseracréél’identifiant.Sicetteclassen’existepas,alorsellesera créée.Traditionnellement,Xvautid,maisdonnez-luilavaleurquivousplaît.Enfin,leYserale nomdel’identifiant.Cetidentifiantdoitêtreuniqueauseindelaclasse,commed’habitude.

Text

View

Parexemple,j’aidécidéd’appelermon«text»etdechangerlepaddingpourqu’il vaille25.7dp,cequinousdonne:

1       <RelativeLayout xmlns:android=";

2       xmlns:tools=";

3       android:layout_width="fill_parent"

4       android:layout_height="fill_parent" >

5

6        <TextView

7        android:id="@+id/text"

8        android:layout_width="wrap_content"

9        android:layout_height="wrap_content"

10       android:layout_centerHorizontal="true"

11       android:layout_centerVertical="true"

12       android:padding="25.7dp"

13       android:text="@string/hello_world"

14       tools:context=".MainActivity" />

15

16 </RelativeLayout>

Dèsquejesauvegarde,monfichierRseramodifiéautomatiquement:

1        public final class R {

2        public static final class attr {

3        }

4        public static final class dimen {

5        public static final int padding_large=0x7f040002;

6        public static final int padding_medium=0x7f040001;

7        public static final int padding_small=0x7f040000;

8        }

9        public static final class drawable {

10       public static final int ic_action_search=0x7f020000;

11       public static final int ic_launcher=0x7f020001;

12       }

13       public static final class id {

14       public static final int menu_settings=0x7f080000;

15       }

16       public static final class layout {

17       public static final int activity_main=0x7f030000;

18       }

19       public static final class menu {

20       public static final int activity_main=0x7f070000;

21       }

22       public static final class string {

23       public static final int app_name=0x7f050000;

24       public static final int hello_world=0x7f050001;

25       public static final int menu_settings=0x7f050002;

26       public static final int title_activity_main=0x7f050003;

27       }

28       public static final class style {

29       public static final int AppTheme=0x7f060000;

30       }

31       }

5.3.2. Instanciation des objets XML

pu

blic

View

find

View

ById

(int

id)

Enfin, on peut utiliser cet identifiant dans le code, comme avec les autres identifiants. Pour cela,onutiliselaméthode.Attention,cetteméthode renvoieuneView,ilfautdoncla«caster»dansletypededestination.

Oncaste?Aucuneidéedecequecelapeutvouloirdire!

Petitrappelencequiconcernelaprogrammationobjet:quanduneclasseClasse_1hérite(ou dérive,ontrouvelesdeuxtermes)d’uneautreclasseClasse_2,ilestpossibled’obtenirunobjet detypeClasse_1àpartird’undeClasse_2avecle transtypage.Pourdirequ’onconvertit une classe mère (Classe_2) en sa classe fille (Classe_1) on dit qu’on caste Classe_2 en Classe_1,etonlefaitaveclasyntaxesuivante:

1    //avec « class Class_1 extends Classe_2 »

2    Classe_2 objetDeux = null;

3    Classe_1 objetUn = (Classe_1) objetDeux;

void

set

Con

tent

View

Ensuite, et c’est là que tout va devenir clair, vous pourrez déclarer que votre activité utilise commeinterfacegraphiquelavuequevousdésirezàl’aidedelaméthode

(View

view)

.Dansl’exemplesuivant,l’interfacegraphiqueestréférencé

ti

vity_main

,ils’agitdoncdulayoutd’identifiantmain,autrementditceluiquenousavons

manipuléunpeuplustôt.

1    import .Activity;

2    import .Bundle;

3    import android.widget.TextView;

4

5       public class TroimsActivity extends Activity {

6       TextView monTexte = null;

7

8          @Override

9          public void onCreate(Bundle savedInstanceState) {

10         super.onCreate(savedInstanceState);

11         setContentView(R.layout.activity_main);

12

13       monTexte = (TextView)findViewById();

14       monTexte.setText("Le texte de notre TextView");

15       }

16       }

Jepeuxtoutàfaitmodifierlepaddinga posteriori.

1    import .Activity;

2    import .Bundle;

3    import android.widget.TextView;

4

5       public class TroimsActivity extends Activity {

6       TextView monTexte = null;

7

8          @Override

9          public void onCreate(Bundle savedInstanceState) {

10         super.onCreate(savedInstanceState);

11         setContentView(R.layout.activity_main);

12

13       monTexte = (TextView)findViewById();

14       // N'oubliez pas que cette fonction n'utilise que des entiers

15       monTexte.setPadding(50, 60, 70, 90);

16       }

17       }

?

Ya-t-iluneraisonpourlaquelleonaccèdeàlavueaprèslesetContentView?

Oui!Essayezdelefaireavant,votreapplicationvaplanter.

View

find

View

ById

(int

Enfait,àchaquefoisqu’onrécupèreunobjetdepuisunfichierXMLdansnotrecodeJava,on procèdeàuneopérationquis’appellela désérialisation.Concrètement,ladésérialisation,c’est transformerunobjetquin’estpasdécritenJava?dansnotrecasl’objetestdécritenXML? en un objet Java réel et concret. C’est à cela que sert la fonction

set

Con

tent

View

find

View

ById

sta

tic

View

in

flate

(Context

context,

id).Leproblèmeestquecetteméthodevaallerchercherdansunarbredevues,quiestcréé automatiquementparl’activité.Or,cetarbreneseracrééqu’aprèsle!Donc leretournera null puisque l’arbre n’existera pas et l’objet ne sera donc pas dansl’àlaplaceutiliserlaméthode

int

id,

View

Group

pa

rent)

.Cetteméthodevadésérialiserl’arbreXMLaulieudel’arbrede

vuesquiseracrééparl’activité.

1    import .Activity;

2    import .Bundle;

3    import android.widget.RelativeLayout;

4    import android.widget.TextView;

5

6       public class TroimsActivity extends Activity {

7       RelativeLayout layout = null;

8       TextView text = null;

9

10       @Override

11       public void onCreate(Bundle savedInstanceState) {

12       super.onCreate(savedInstanceState);

13

14       // On récupère notre layout par désérialisation. La méthode inflate retourne un View

15       // C'est pourquoi on caste (on convertit) le retour de la

méthode avec le vrai type de notre layout, c'est-à-dire RelativeLayout

16       layout = (RelativeLayout) RelativeLayout.inflate(this, R.layout.activity_main, null);

17       // … puis on récupère TextView grâce à son identifiant

18       text = (TextView) layout.findViewById();

19       text.setText("Et cette fois, ça fonctionne !");

20       setContentView(layout);

21       // On aurait très bien pu utiliser « setContentView(R.layout.activity_main) » bien sûr !

22       }

23       }

?

C’estunpeucontraignant!EtsionsecontentaitdefaireunpremiersetContentView pour«inflater»(désérialiser)l’arbreetrécupérerlavuepourlamettredansunsecond setContentView?

 

set

Con

tent

View

 

on

Create

set

Con

tent

View

C’estuneidée…maisjevousrépondraisquevousavezoubliél’optimisation!UnfichierXML esttrèslourdàparcourir,doncconstruireunarbredevuesprenddutempsetdesressources.À la compilation, si on détecte qu’il y a deux dans , eh bien on ne prendraencomptequeladernière!Ainsi,touteslesinstancesdeprécédant ladernièresontrenduescaduques.

 

— Eclipsevouspermetdeconfectionnerdesinterfacesàlasouris,maiscelaneserajamais aussiprécisquedetravaillerdirectementdanslecode.

View

Group

View

Group

— Tousleslayoutshéritentdelasuperclassequiellemêmehéritedelasuper classeView.PuisqueleswidgetshéritentaussideViewetquelespeuvent contenirdesView,leslayoutspeuventcontenird’autreslayoutsetdeswidgets.C’estlà toutelapuissancedelahiérarchisationetlaconfectiondesinterfaces.

— Viewregroupeuncertainnombredepropriétésquideviennentcommunesauxwidgets etauxlayouts.

— Lorsquevousdésérialisez(ouinflatez)unlayoutdansuneactivité,vousdevezrécupérer leswidgetsetleslayoutspourlesquelsvousdésirezrajouterdesfonctionnalités.Celase faitgrâceàlaclasseR.javaquilistel’ensembledesidentifiantsdevosressources.


6.   Les widgets les plus simples

Maintenantqu’onsaitcommentestconstruiteuneinterfacegraphique,onvavoiravecquoiil estpossibledelapeupler.Cechapitretraiterauniquementdeswidgets,c’est-à-diredesvuesqui fournissent uncontenuetnonquilemettent en forme —cesontleslayoutsquis’occupentde cegenredechoses.

Fourniruncontenu,c’estpermettreàl’utilisateurd’interagiravecl’application,ouafficherune informationqu’ilestvenuconsulter.

6.1. Les widgets

Unwidgetestunélémentdebasequipermetd’afficherducontenuàl’utilisateurouluipermet d’interagiravecl’application.Chaquewidgetpossèdeunnombreimportantd’attributsXMLet deméthodesJava,c’estpourquoijenelesdétailleraipas,maisvouspourreztrouvertoutesles informationsdontvousavezbesoinsurladocumentationofficielled’Android(celatombebien, j’enparleàlafinduchapitre).

6.1.1. TextView

Vousconnaissezdéjàcettevue,ellevouspermetd’afficherunechaînedecaractèresquel’utilisateurnepeutmodifier.Vousverrezplustardqu’onpeutaussiyinsérerdeschaînesdecaractères formatées,àl’aidedebalisesHTML,cequinousserviraàsoulignerdutexteouàlemettreen grasparexemple.

6.1.1.1. Exemple en XML

1       <TextView

2       android:layout_width="fill_parent"

3       android:layout_height="wrap_content"

4       android:text="@string/textView"

5       android:textSize="8sp"

6       android:textColor="#112233" />

@string/text

View

an

droid:text

an

droid:text

Size

Vousn’avezpasencorevucommentfaire,maiscettesyntaxesignifiequ’on utilise une ressource de type string. Il est aussi possible de passer directement une chaîne de caractères dans, mais ce n’est pas recommandé. On précise également la taille des caractères avec, puis on précise la couleur du texte avec an

droid:text

Co

lor

.Cettenotationavecun#permetdedécriredescouleursàl’aidedenombres

hexadécimaux.

6.1.1.2. Exemple en Java

1    TextView textView = new TextView(this);

2    textView.setText(R.string.textView);

3    textView.setTextSize(8);

4    textView.setTextColor(0x112233);

Vous remarquerez que l’équivalent de #112233 est 0x112233 (il suffit de remplacer le # par 0x).

6.1.1.3. Rendu

Lerendusetrouveàlafiguresuivante.

 

Figure 6.1.–Rendud’unTextView

6.1.2. EditText

Text

View

Cecomposantestutilisépourpermettreàl’utilisateurd’é’agitenfaitd’un éditable.

i

IlhéritedeTextView,cequisignifiequ’ilpeutprendrelesmêmesattributsqueTextView enXMLetqu’onpeututiliserlesmêmesméthodesJava.

6.1.2.1. Exemple en XML

1       <EditText

2       android:layout_width="fill_parent"

3       android:layout_height="wrap_content"

4       android:hint="@string/editText"

5       android:inputType="textMultiLine"

6       android:lines="5" />

an

droid:text

 

an

droid:hint

Edit

Text

 

an

droid:hint

Edit

Text

— Au lieu d’utiliser , on utilise . Le problème avec an droid:textestqu’ilremplitl’ avecletextedemandé,alorsqu’ affichejusteuntexted’indication,quin’estpasprisencompteparl’entant quevaleur(sivousavezdumalàcomprendreladifférence,essayezlesdeux).

Edit

Text

 

an

droid:in

put

Type

               — On précise quel type de texte contiendra notre                        avec                                       .

Edit

Text

in

put

Types

Danscecasprécisuntextesurplusieurslignes.Cetattributchangelanatureduclavier qui est proposé à l’utilisateur, par exemple si vous indiquez que l’servira à écrireuneadressee-mail,alorsl’arobaseseraproposétoutdesuiteàl’utilisateursurle clavier.Voustrouverezunelistedetousles possiblesici  .

Edit

Text

 

an

droid:lines

                 — Enfin,onpeutpréciserlatailleenlignesquedoitoccuperl’                        avec                             .

6.1.2.2. Exemple en Java

1    EditText editText = new EditText(this);

2    editText.setHint(R.string.editText);

3    editText.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE); 4 editText.setLines(5);

6.1.2.3. Rendu

Lerendusetrouveàlafiguresuivante.

 

Figure 6.2.–Rendud’unEditText

6.1.3. Button

Text

View

Unsimplebouton,mêmes’ils’agitenfaitd’uncliquable.

i

IlhéritedeTextView,cequisignifiequ’ilpeutprendrelesmêmesattributsqueTextView enXMLetqu’onpeututiliserlesmêmesméthodesJava.

6.1.3.1. Exemple en XML

 

6.1.3.2. Exemple en Java

 

6.1.3.3. Rendu

Lerendusetrouveàlafiguresuivante.

 

Figure 6.3.–Rendud’unButton

6.1.4. CheckBox

Unecasequipeutêtredansdeuxétats:cochéeoupas.

i

EllehéritedeButton,cequisignifiequ’ellepeutprendrelesmêmesattributsqueButton enXMLetqu’onpeututiliserlesmêmesméthodesJava.

6.1.4.1. Exemple en XML

1       <CheckBox

2       android:layout_width="fill_parent"

3       android:layout_height="wrap_content"

4       android:text="@string/checkBox"

5       android:checked="true" />

an

droid:che

cked="true"

signifiequelacaseestcochéepardéfaut.

6.1.4.2. Exemple en Java

1       CheckBox checkBox = new CheckBox(this);

2       checkBox.setText(R.string.checkBox);

3       checkBox.setChecked(true)

4       if(checkBox.isChecked())

5       // Faire quelque chose si le bouton est coché

6.1.4.3. Rendu

Lerendusetrouveàlafiguresuivante.

 

Figure 6.4.–Rendud’uneCheckBox:cochéeàgauche,noncochéeàdroite

6.1.5. RadioButton et RadioGroup

Check

Box

Ra

dio

Group

Mêmeprincipequela,àladifférencequel’utilisateurnepeutcocherqu’uneseule case.Ilestplutôtrecommandédelesregrouperdansun.

i

RadioButtonhéritedeButton,cequisignifiequ’ilpeutprendrelesmêmesattributsque ButtonenXMLetqu’onpeututiliserlesmêmesméthodesJava.

Ra

dio

Group

 

Ra

dio

But

ton

Ra

dio

But

ton

Un      est en fait un layout, mais il n’est utilisé qu’avec des            , c’est pourquoionlevoitmaintenant.Sonbutestdefaireensortequ’ilpuissen’yavoirqu’unseul sélectionnédanstoutlegroupe.

6.1.5.1. Exemple en XML

1        <RadioGroup

2        android:layout_width="wrap_content"

3        android:layout_height="wrap_content"

4        android:orientation="horizontal" >

5        <RadioButton

6        android:layout_width="wrap_content"

7        android:layout_height="wrap_content"

8        android:checked="true" />

9        <RadioButton

10       android:layout_width="wrap_content"

11       android:layout_height="wrap_content" />

12       <RadioButton

13       android:layout_width="wrap_content"

14       android:layout_height="wrap_content" />

15       </RadioGroup>

6.1.5.2. Exemple en Java

1    RadioGroup radioGroup = new RadioGroup(this);

2    RadioButton radioButton1 = new RadioButton(this);

3    RadioButton radioButton2 = new RadioButton(this);

4    RadioButton radioButton3 = new RadioButton(this);

5

6    // On ajoute les boutons au RadioGroup

7    radioGroup.addView(radioButton1, 0);

8    radioGroup.addView(radioButton2, 1);

9    radioGroup.addView(radioButton3, 2);

10

11    // On sélectionne le premier bouton

12    radioGroup.check(0);

13

14 // On récupère l'identifiant du bouton qui est coché 15 int id = radioGroup.getCheckedRadioButtonId();

6.1.5.3. Rendu

Lerendusetrouveàlafiguresuivante.

 

Figure 6.5.–Leboutonradiodedroiteestsélectionné

6.1.6. Utiliser la documentation pour trouver une information

Jefaisunpetitapartéafindevousmontrercommentutiliserladocumentationpourtrouverles informationsquevousrecherchez,parcequetoutlemondeenabesoin.Quecesoitvous,moi,des développeursAndroidprofessionnelsoun’importequichezGoogle,nousavonstousbesoinde ’estpaspossibledetoutsavoir,etsurtout,jenepeuxpastoutvousdire! Ladocumentationestlàpourça,etvousnepourrezpasdevenirdebonsdéveloppeursAndroid —voiredebonsdéveloppeurstoutcourt—sivousnesavezpaschercherdesinformationspar

vous-mêmes.

Text

View

Jevaisprocéderàl’aided’unexemple.Jemedemandecommentfairepourchangerlacouleur dutextedema.Pourcela,jemedirigeversladocumentationofficielle:http://de  

Text

View

Vousvoyezunchampderechercheenhautàgauche.Jevaisinsérerlenomdelaclassequeje recherche:.Vousvoyezunelistequis’afficheetquipermetdesélectionnerlaclasse quipourraitéventuellementvousintéresser,commeàlafiguresuivante.

 

Figure 6.6.–Unelistes’afficheafinquevoussélectionniezcequivousintéresse

An

View

Text

View

J’aibiensûrcliquésurpuisquec’estcellequim’inté arrivonsalorssurunepagequivousdécrittouteslesinformationspossiblesetimaginablessur laclasse(voirfiguresuivante).

 

Figure 6.7.–Vousavezaccèsàbeaucoupd’informationssurlaclasse

Onvoitparexemplequ’ils’agitd’uneclasse,publique,quidérivedeViewetimplémenteune interface.

Known Di

rect Sub

Lapartiesuivantereprésenteunarbrequirésumelahiérarchiedesessuperclasses. Ensuite,onpeutvoirlesclassesquidériventdirectementdecetteclasse(

Known In

di

rect Sub

classes

classes) et les classes qui en dérivent indirectement, c’est-à-dire qu’un des ancêtres de ces classesdérivedeView().

Enfin, on trouve en haut à droite un résumé des différentes sections qui se trouvent dans le document(jevaisaussiparlerdecertainessectionsquinesetrouventpasdanscetteclassemais quevouspourrezrencontrerdansd’autresclasses):

Nes

ted Classes

—est la section qui regroupe toutes les classes internes. Vous pouvez cliquersuruneclasseinternepourouvrirunepagesimilaireàcelledelaclasseView.

XML At

trs

—estlasectionquiregroupetouslesattributsquepeutprendreunobjetde cetypeenXML.Allezvoirletableau,vousverrezquepourchaqueattributXMLon trouveassociéunéquivalentJava.

— Constantsestlasectionquiregroupetouteslesconstantesdanscetteclasse.

— Fieldsestlasectionquiregroupetouteslesstructuresdedonnéesconstantesdanscette classe(listesettableaux).

— Ctorsestlasectionquiregroupetouslesconstructeursdecetteclasse.

Me

thods

—estlasectionquiregroupetouteslesméthodesdecetteclasse.

Pro

tec

ted Me

thods

—estlasectionquiregroupetouteslesméthodesprotégées(accessiblesuniquementparcetteclasseoulesenfantsdecetteclasse). i

Vousrencontrerezplusieursfoisl’adjectifInherited,ilsignifiequecetattributouclasse ahéritéd’unedesessuperclasses.

XML At

trs

Ainsi,sijechercheunattributXML,jepeuxcliquersuretparcourirlalistedes attributspourdécouvrirceluiquim’intéresse(voirfiguresuivante),oualorsjepeuxeffectuer unerecherchesurlapage(leraccourcistandardpourcelaest Ctrl + F ).

 

Figure 6.8.–Apprenezàutiliserlesrecherches

an

droid:text

Co

lor

J’aitrouvé!Ils’agitde!Jepeuxensuitecliquerdessuspourobtenirplus d’informationsetainsil’utilisercorrectementdansmoncode.

6.1.7. Calcul de l’IMC - Partie 1

6.1.7.1. Énoncé

Onvacommencerunmini-TP(TPsignifie«travauxpratiques»;cesontdesexercicespour vousentraîneràprogrammer).Vousvoyezcequ’estl’IMC?C’estunnombrequisecalculeà partirdelatailleetdelamassecorporelled’unindividu,afinqu’ilpuisse déterminers’ilest tropsvelteoutropcorpulent.

!

Ayanttravaillédanslemilieumédical,jepeuxvousaffirmerqu’ilnefautpasfairetrop confianceàcenombre(c’estpourquoijeneproposepasd’interprétationdurésultatpour cemini-TP).S’ilvousindiquequevousêtesensurpoids,necomplexezpas!Sachezque touslesbodybuilders dumondesetrouventobèsesd’aprèscenombre.

Pour l’instant, on va se contenter de faire l’interface graphique. Elle ressemblera à la figure suivante.

 

Figure 6.9.–Notreprogrammeressembleraàça

6.1.7.2. Instructions

Avantdecommencer,voiciquelquesinstructions:

— OnutiliserauniquementleXML.

— Pourmettreplusieurscomposantsdansunlayout,onsecontenterademettrelescomposantsentrelesbalisesdecelayout.

— Onn’utiliseraqu’unseullayout.

Edit

Text

an

droid:in

put

Type

 

num

bers

— Les deuxpermettront de n’insérer que des nombres. Pour cela, on utilise l’attributauquelondonnelavaleur .

Text

View

Text

View

 

an

droid:text

Style

— Lesquiaffichent«Poids:»et«Taille:»sontcentrés,enrougeetengras. — Pour mettre un         en gras on utilisera l’attribut            en lui attribuantcommevaleurbold.

Text

View

 

an

droid:text

Co

lor

— Pourmettreun  enrougeonutiliseral’attribut   enlui attribuantcommevaleur#FF0000.Vouspourreztrouverd’autresvaleurspourindiquer unecouleurà  

Text

View

 

an

droid:gra

vity="cen

— Afindecentrerdutextedansun  ,onutilisel’attribut ter".

Voicilelayoutdebase:

1       <LinearLayout xmlns:android=";

2       android:layout_width="fill_parent"

3       android:layout_height="fill_parent"

4       android:orientation="vertical">

5

       6                          <!-- mettre les composants ici -->

7

8 </LinearLayout>

6.1.7.3. Solution

1        <?xml version="1.0" encoding="utf-8"?>

2        <LinearLayout xmlns:android=";

3        android:layout_width="fill_parent"

4        android:layout_height="fill_parent"

5        android:orientation="vertical">

6        <TextView

7        android:layout_width="fill_parent"

8        android:layout_height="wrap_content"

9        android:text="Poids : "

10       android:textStyle="bold"

11       android:textColor="#FF0000"

 

12

android:gravity="center"

13

/>

14

<EditText

15

16

17

18

19

20

android:id="@+id/poids"

android:layout_width="fill_parent" android:layout_height="wrap_content"

android:hint="Poids"

android:inputType="numberDecimal"

/>

21

<TextView

22

23

24

25

26

27

28

android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Taille : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="center"

/>

29

<EditText

30

31

32

33

34

35

android:id="@+id/taille" android:layout_width="fill_parent" android:layout_height="wrap_content"

android:hint="Taille"

android:inputType="numberDecimal"

/>

36

<RadioGroup

37

38

39

40

41

42

 

43

<RadioButton

44

45

46

47

android:id="@+id/radio1"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:text="Mètre"

48

/>

49

<RadioButton

50

51

52

53

54

android:id="@+id/radio2"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:text="Centimètre"

/>

55

</RadioGroup>

56

<CheckBox

57

58

59

60

61

android:id="@+id/mega"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mega fonction !" />

Et voilà, notre interface graphique est prête! Bon pour le moment, elle ne fait rien : si vous appuyezsurlesdifférentsélements,riennesepasse.Maisnousallonsyremédierd’icipeu,ne vousinquiétezpas.

6.2. Gérer les évènements sur les widgets

Onvavoiricicommentgérerlesinteractionsentrel’interfacegraphiqueetl’utilisateur.

6.2.1. Les listeners

call

back

Ilexisteplusieursfaçonsd’interagiravecuneinterfacegraphique.Parexemplecliquersurun bouton,entreruntexte,sélectionneruneportiondetexte,etc.Cesinteractionss’appellentdes évènements.Pourpouvoirréagiràl’apparitiond’unévènement,ilfaututiliserunobjetquiva détecterl’évènementetafindevouspermettreletraiter.Cetyped’objets’appelleun listener. Unlistenerestuneinterfacequivousobligeàredéfinirdesméthodesdeetchaque méthodeseraappeléeaumomentoùseproduiral’évènementassocié.

But

ton

Cli

ck

Lis

te

ner

 

call

back

Par exemple, pour intercepter l’évènement clic sur un, on appliquera l’interface sur ce bouton. Cette interface contient la méthode de

void

on

Click(View

vue)

—leparamètredetypeViewétantlavuesurlaquelleleclicaété

effectué,quiseraappeléeàchaqueclicetqu’ilfaudraimplémenterpourdéterminerquefaireen casdeclic.Parexemplepourgérerd’autresévènements,onutiliserad’autresméthodes(liste nonexhaustive):

Long

Cli

ck

Lis

te

ner

—pour les clics qui durent longtemps, avec la méthode

boo

lean

on

Long

Click(View

vue)

. Cette méthode doit retourner true une fois que

l’actionassociéeaétéeffectuée.

Key

Lis

te

ner

—pourgérerl’appuisurunetouche.Onyassocielaméthodeboo

lean

on

Key(View

vue,

int

code,

KeyEvent

event)

.Cetteméthodedoitretourner

trueunefoisquel’actionassociéeaétéeffectuée.

!

J’ai bien dit qu’il fallait utiliser View.OnClickListener, de la classe View! Il existe d’autrestypesdeOnClickListeneretEclipsepourraitbienvousproposerd’importer n’importequelpackagequin’arienàvoir,auquelcasvotreapplicationnefonctionnerait pas. Le package à utiliser pour OnClickListener est .OnClick Listener.

?

Queveux-tudirepar«Cetteméthodedoitretournertrueunefoisquel’actionassociée aétéeffectuée»?

on

Touch

on

Touch

on

Touch

Petite subtilité pas forcément simple à comprendre. Il faut indiquer à Android quand vous souhaitezquel’évènementsoitconsidérécommetraité,achevé.Eneffet,ilestpossiblequ’un évènementcontinueàagirdansletemps.Unexemplesimpleestceluidutoucher.Letoucher correspondaufaitdetoucherl’écran,pendantquevoustouchezl’écranetavantmêmedelever le doigt pour le détacher de l’écran. Si vous levez ce doigt, le toucher s’arrête et un nouvel évènementestlancé:leclic,maisconcentrons-noussurletoucher.Quandvoustouchezl’écran, unévènementdetypeestdéclenché.Sivousretourneztrueautermedecetteméthode, çaveutdirequecetévènementtoucher aétégéré,etdoncsil’utilisateurcontinueàbougerson doigtsurl’écran,Androidconsidéreralesmouvementssontdenouveauxévènementstoucher et ànouveauxlaméthodedecallbackseraappeléepourchaquemouvement.Enrevanche, si vous retournez false, l’évènement ne sera pas considéré comme terminé et si l’utilisateur continueàbougersondoigtsurl’écran,Androidneconsidérerapasquecesontdenouveaux évènementsetlaméthodeneseraplusappelée.Ilfautdoncréfléchirenfonctiondela situation.

se

tOn[Eve

ne

Enfin pour associer un listener à une vue, on utilisera une méthode du type

ment]Lis

te

ner(On[Eve

ne

ne

ment]Lis

te

ner

lis

te

ner)

 

Eve

ne

ment

                                                                                                                                         avec                     l’évènementconcerné,

parexemplepourdétecterlesclicssurunboutononfera:

 

6.2.2. Par héritage

Onvafaireimplémenterunlistenerànotreclasse,cequiveutdirequel’activitéinterceptera d’elle-même les évènements. N’oubliez pas que lorsqu’on implémente une interface, il faut nécessairementimplémentertouteslesméthodesdecetteinterface.Enfin,iln’estbienentendu pasindispensablequevousgérieztouslesévènementsd’uneinterface,vouspouvezlaisserune méthodevidesivousnevoulezpasvouspréoccuperdecestyled’évènements. Unexempled’implémentation:

1    import .OnTouchListener;

2    import .OnClickListener;

3    import .Activity;

4    import .Bundle;

5    import .MotionEvent;

6    import ;

7    import android.widget.Button;

8

9        // Notre activité détectera les touchers et les clics sur les vues qui se sont inscrites

10       public class Main extends Activity implements View.OnTouchListener, View.OnClickListener {

11       private Button b = null;

12

13       @Override

14       public void onCreate(Bundle savedInstanceState) {

15       super.onCreate(savedInstanceState);

16

17                               setContentView();

18

19       b = (Button) findViewById(R.id.boutton);

20       b.setOnTouchListener(this);

21       b.setOnClickListener(this);

22       }

23

24       @Override

25       public boolean onTouch(View v, MotionEvent event) {

26       /* Réagir au toucher */

27       return true;

28       }

29

30       @Override

31       public void onClick(View v) {

32       /* Réagir au clic */

33       }

34       }

on

Click(View)

Cependant,unproblèmesepose.Àchaquefoisqu’onappuierasurunbouton,quelqu’ilsoit,on rentreradanslamêmeméthode,etonexécuteradonclemêmecode…C’estpastrèspratique,si nousavonsunboutonpourrafraîchirunongletdansuneapplicationdenavigateurinternetetun autrepourquitterunonglet,onaimeraitbienquecliquersurleboutonderafraîchissementne quittepasl’ongletetvice-versa.Heureusement,lavuepasséedanslaméthode

permetdedifférencierlesboutons.Eneffet,ilestpossiblederécupérerl’identifiantdelavue (voussavez,l’identifiantdéfinienXMLetqu’onretrouvedanslefichierR!)surlaquelleleclica étéeffectué.Ainsi,nouspouvonsréagirdifféremmentenfonctiondecetidentifiant:

 

6.2.3. Par une classe anonyme

L’inconvénientprincipaldelatechniqueprécédenteestqu’ellepeuttrèsviteallongerlesméthodes deslisteners,cequifaitqu’ons’yperdunpeus’ilyabeaucoupd’élémentsàgérer.C’estpourquoi ilestpréférabledepasserparuneclasseanonymedèsqu’onaunnombreélevéd’élémentsqui réagissentaumêmeévènement.

Cli

ck

Lis

te

ner()

Pourrappel,uneclasseanonymeestuneclasseinternequidérived’unesuperclasseouimplémente uneinterface,etdontonneprécisepaslenom.Parexemplepourcréeruneclasseanonymequi implémentejepeuxfaire:

1        widget.setTouchListener(new View.OnTouchListener() {

2        /**

3        * Contenu de ma classe

4        * Comme on implémente une interface, il y aura des méthodes à implémenter, dans ce cas-ci

5        * « public boolean onTouch(View v, MotionEvent event) »

6        */

7        }); // Et on n'oublie pas le point-virgule à la fin ! C'est une instruction comme les autres !

Voiciunexempledecode:

1    import .Activity;

2    import .Bundle;

3    import ;

4    import android.widget.Button;

5

6        public class AnonymousExampleActivity extends Activity {

7        // On cherchera à détecter les touchers et les clics sur ce

bouton

8        private Button touchAndClick = null;

9        // On voudra détecter uniquement les clics sur ce bouton

10       private Button clickOnly = null;

11

12       @Override

13       public void onCreate(Bundle savedInstanceState) {

14       super.onCreate(savedInstanceState);

15       setContentView();

16

17       touchAndClick = (Button)findViewById(R.id.touchAndClick);

18       clickOnly = (Button)findViewById(R.id.clickOnly);

19

20            touchAndClick.setOnLongClickListener(new View.OnLongClickListener() {

21            @Override

22            public boolean onLongClick(View v) {

23            // Réagir à un long clic

24            return false;

25            }

26            });

27

28            touchAndClick.setOnClickListener(new View.OnClickListener() {

29            @Override

30            public void onClick(View v) {

31            // Réagir au clic

32            }

33            });

34

35            clickOnly.setOnClickListener(new View.OnClickListener() {

36            @Override

37            public void onClick(View v) {

38            // Réagir au clic

39            }

40            });

41            }

 

6.2.4. Par un attribut

C’estundérivédelaméthodeprécédente:enfaitonimplémentedesclassesanonymesdansdes attributsdefaçonàpouvoirlesutiliserdansplusieursélémentsgraphiquesdifférentsquiauront lamêmeréactionpourlemêmeévènement.C’estlaméthodequejeprivilégiedèsquej’ai,par exemple,plusieursboutonsquiutilisentlemêmecode.

 

35       @Override

36       public void onCreate(Bundle savedInstanceState) {

37       super.onCreate(savedInstanceState);

38

39                               setContentView();

40

41       b1 = (Button) findViewById(R.id.bouton1);

42       b2 = (Button) findViewById(R.id.bouton2);

43       b3 = (Button) findViewById(R.id.bouton3); 44

45       b1.setOnTouchListener(touchListenerBouton1);

46       b1.setOnClickListener(clickListenerBoutons);

47       b2.setOnClickListener(clickListenerBoutons);

48       b3.setOnTouchListener(touchListenerBouton3);

49       }

50       }

6.2.5. Application

6.2.5.1. Énoncé

Onvas’amuserunpeu:nousallonscréerunboutonquiprendtoutl’écranetfaireensorteque letexteàl’intérieurduboutongrossissequandons’éloigneducentredubouton,etrétrécisse quandons’enrapproche.

6.2.5.2. Instructions

— Onvasepréoccupernonpasduclicmaisdutoucher,c’est-à-direl’évènementquidébute dèsqu’ontoucheleboutonjusqu’aumomentoùonlerelâche(contrairementauclicqui nesedéclenchequ’aumomentoùonrelâchelapression).

Text

View

 

set

Text

Size((co

or

don

— La taille du       sera fixée avec la méthode nee_x-largeur_du_bouton/2)(coordonnee_y-hauteur_du_bou ton/2)).

float

getX()

 

Mo

tio

nEvent

                — Pourobtenirlacoordonnéeenabscisse(X)onutilise                                d’un

float

getY()

,etpourobtenirlacoordonnéeenordonnée(Y)onutilise.

Jevousdonnelecodepourfaireensorted’avoirleboutonbienaumilieudulayout:

1        <?xml version="1.0" encoding="utf-8"?>

2        <LinearLayout xmlns:android=";

3        android:orientation="vertical"

4        android:layout_width="fill_parent"

5        android:layout_height="fill_parent" >

6        <Button

7        android:id="@+id/bouton"

8        android:layout_width="fill_parent"

9        android:layout_height="fill_parent"

10       android:layout_gravity="center"

11       android:text="@string/hello" />

12       </LinearLayout>

Maintenant,c’estàvousdejouer!

6.2.5.3. Solution

1         // On fait implémenter OnTouchListener par notre activité

2         public class Main extends Activity implements View.OnTouchListener {

3         @Override

4         public void onCreate(Bundle savedInstanceState) {

5         super.onCreate(savedInstanceState);

6

       7                           setContentView();

8

9        // On récupère le bouton par son identifiant

10       Button b = (Button) findViewById(R.id.bouton);

11       // Puis on lui indique que cette classe sera son listener pour l'évènement Touch

12       b.setOnTouchListener(this);

13       }

14

15       // Fonction qui sera lancée à chaque fois qu'un toucher est détecté sur le bouton rattaché

16       @Override

17       public boolean onTouch(View view, MotionEvent event) {

18       // Comme l'évènement nous donne la vue concernée par le toucher, on le récupère et on le caste en Button

19       Button bouton = (Button)view;

20

21       // On récupère la largeur du bouton

22       int largeur = bouton.getWidth();

23       // On récupère la hauteur du bouton

24       int hauteur = bouton.getHeight();

25

26       // On récupère la coordonnée sur l'abscisse (X) de l'évènement

27       float x = ();

28       // On récupère la coordonnée sur l'ordonnée (Y) de l'évènement

29       float y = ();

30

31                            // Puis on change la taille du texte selon la formule indiquée dans l'énoncé

 

Onaprocédéparhéritagepuisqu’onaqu’unseulboutonsurlequelagir.

6.2.6. Calcul de l’IMC - Partie 2

6.2.6.1. Énoncé

Ilesttempsmaintenantdereliertouslesboutonsdenotreapplicationpourpouvoireffectuer touslescalculs,enrespectantlesquelquesrèglessuivantes:

Check

Box

— Lademegafonctionpermetdechangerlerésultatducalculenunmessage élogieuxpourl’utilisateur.

— Laformulepourcalculerl’IMCest poids(enkilogrammes)taille(enmetres)2 .

— LeboutonRAZremetàzérotousleschamps(sansoublierletextepourlerésultat).

Ra

dio

Group

— Lesélémentsdanslepermettentàl’utilisateurdepréciserenquelleunitéil aindiquésataille.Pourobtenirlatailleenmètresdepuislatailleencentimètresilsuffit dediviserpar100: metres.

— Dès qu’on change les valeurs dans les champs Poids et Taille, on remet le texte du

résultatpardéfautpuisquelavaleurcalculéen’estplusvalablepourlesnouvellesvaleurs.

— On enverra un message d’erreur si l’utilisateur essaie de faire le calcul avec une taille égaleàzérogrâceàunToast. i

UnToastestunwidgetunpeuparticulierquipermetd’afficherunmessageàn’importe quel moment sans avoir à créer de vue. Il est destiné à informer l’utilisateur sans le dérangeroutremesure;ainsil’utilisateurpeutcontinueràutiliserl’applicationcommesi leToastn’étaitpasprésent.

6.2.6.2. Consignes

sta

tic

Toast

ma

ke

Text(Context

context,

— VoicilasyntaxepourconstruireunToast:

Char

Se

quence

texte,

int

du

ra

tion)

. La durée peut être indiquée à l’aide de la

void

show

()

constanteToast.LENGTH_SHORTpourunmessagecourtetToast.LENGTH_LONGpour unmessagequidurerapluslongtemps.Enfin,ilestpossibled’afficherleToastavecla méthode.

Check

Box

 

boo

lean

isChe

— Poursavoirsiune           estsélectionnée,onutiliseralaméthode cked()quirenvoietruelecaséchéant.

Ra

dio

But

ton

 

Ra

dio

Group

int

get

Che

cke

dRa

dio

But

to

nId

()

— Pourrécupérerl’identifiantdu  quiestsélectionnédansun        il faututiliserlaméthode.

Edit

Text

 

Edi

table

get

Text

              — Onpeut récupérer letexte d’un                          àl’aide de lafonction

Edi

table

().Onpeutensuiteviderlecontenudecetobjetàl’aidedelafonctionvoid clear().Plusd’informationssurEditable  .

— Parce que c’est déjà bien assez compliqué comme cela, on se simplifie la vie et on ne prendpasencomptelescasextrêmes(tailleoupoids<0ounullparexemple).

Edit

Text

on

Key

— Pour détecter le moment où l’utilisateur écrit dans un, on peut utiliser l’évènement.Problème,cettetechniquenefonctionnequesurlesclaviersvirtuels, alorssil’utilisateuraunclavierphysique,cequ’ilécritn’enclencherapaslaméthodede callback Jevaisquandmêmevousprésentercettesolution,maispourfairecegenrede surveillance,onpréférerautiliserunTextWatcher  .C’estcommeunlistener,maisça n’enportepaslenom!

6.2.6.3. Ma solution

1     import .Activity;

2     import .Bundle;

3     import .KeyEvent;

4     import .MotionEvent;

5     import ;

6     import .OnClickListener;

7     import .OnKeyListener;

8     import android.widget.Button;

9     import android.widget.CheckBox;

10    import android.widget.EditText;

11    import android.widget.RadioGroup;

12    import android.widget.TextView;

13    import android.widget.Toast;

14

15       public class IMCActivity extends Activity {

16       // La chaîne de caractères par défaut

17       private final String defaut =

"Vous devez cliquer sur le bouton « Calculer l'IMC » pour obtenir un résu

18       // La chaîne de caractères de la megafonction

19       private final String megaString =

"Vous faites un poids parfait ! Wahou ! Trop fort ! On dirait Brad Pitt (

20

21       Button envoyer = null;

22       Button raz = null;

23

24       EditText poids = null;

25       EditText taille = null;

26

27                        RadioGroup group = null;

28

29                         TextView result = null;

 

30

31

CheckBox mega = null;

32

33

@Override

34

public void onCreate(Bundle savedInstanceState) {

35

super.onCreate(savedInstanceState);

36

setContentView(R.layout.activity_main);

37

38

// On récupère toutes les vues dont on a besoin

39

envoyer = (Button)findViewById(R.id.calcul);

40

41

raz = (Button)findViewById();

42

43

taille = (EditText)findViewById(R.id.taille);

44

poids = (EditText)findViewById(R.id.poids);

45

46

mega = (CheckBox)findViewById();

47

48

group = (RadioGroup)findViewById(R.id.group);

49

50

result = (TextView)findViewById(R.id.result);

51

52

// On attribue un listener adapté aux vues qui en ont besoin

53

envoyer.setOnClickListener(envoyerListener);

54

raz.setOnClickListener(razListener);

55

 

56

poids.addTextChangedListener(textWatcher);

57

58

// Solution avec des onKey

59

//taille.setOnKeyListener(modificationListener);

60

//poids.setOnKeyListener(modificationListener);

61

mega.setOnClickListener(checkedListener);

62

}

63

64

/*

65

// Se lance à chaque fois qu'on appuie sur une touche en étant sur un EditText

66

private OnKeyListener modificationListener = new OnKeyListener() {

67

@Override

68

public boolean onKey(View v, int keyCode, KeyEvent event) {

69

// On remet le texte à sa valeur par défaut pour ne pas avoir de résultat incohérent

70

result.setText(defaut);

71

return false;

72

}

73

};*/

74

75

76

private TextWatcher textWatcher = new TextWatcher() {

 

77

@Override

78

public void onTextChanged(CharSequence s, int start, int before, int count) {

79

result.setText(defaut);

80

}

81

82

@Override

83

public void beforeTextChanged(CharSequence s, int start, int count,

84

int after) {

85

86

}

87

88

@Override

89

public void afterTextChanged(Editable s) {

90

91

}

92

};

93

94

// Uniquement pour le bouton "envoyer"

95

private OnClickListener envoyerListener = new OnClickListener() {

96

@Override

97

public void onClick(View v) {

98

if(!mega.isChecked()) {

99

// Si la megafonction n'est pas activée

100

 

101

String t = taille.getText().toString();

102

// On récupère le poids

103

String p = poids.getText().toString();

104

105

float tValue = Float.valueOf(t);

106

107

// Puis on vérifie que la taille est cohérente

108

if(tValue == 0)

109

Toast.makeText(,

"Hého, tu es un Minipouce ou quoi ?",

Toast.LENGTH_SHORT).show();

110

else {

111

float pValue = Float.valueOf(p);

112

// Si l'utilisateur a indiqué que la taille était en

centimètres

113

// On vérifie que la Checkbox sélectionnée est la deuxième à l'aide de son identifiant

114

if(group.getCheckedRadioButtonId() == R.id.radio2)

115

tValue = tValue / 100;

116

117

tValue = (float)(tValue, 2);

118

float imc = pValue / tValue;

119

result.setText("Votre IMC est " + String.valueOf(imc));

120

}

 

on

Key

Curieuxva!Enfaitl’évènementseralancéavantquel’écrituresoitpriseencomptepar lesystème.Ainsi,sivousrenvoyeztrue,Androidconsidéreraquel’évènementaétégéré,etque vousavezvous-mêmeécritlalettrequiaétépressée.Sivousrenvoyezfalse,alorslesystème comprendraquevousn’avezpasécritlalettreetilleferadelui-même.Alorsvousaurieztrès bienpu renvoyertrue,mais ilfaudrait écrirenous-même lalettre et c’estdu travailenplus pourrien!

Vousavezvucequ’onafait?Sanstoucheràl’interfacegraphique,onapueffectuertoutesles modificationsnécessairesaubonfonctionnementdenotreapplication.C’estl’intérêtdedéfinir l’interface dans un fichier XML et le côté interactif en Java : vous pouvez modifier l’un sans toucherl’autre!

 

— Ilexisteungrandnombredewidgetsdifférents.Parmilesplusutilisés,nousavons:

Text

View

Edit

Text

Text

View

—destinéàafficherdutextesurl’écran.

—quihéritedespropriétésdeetquipermetàl’utilisateurd’écrire dutexte.

But

ton

 

Text

View

—  quihéritedespropriétésde            etquipermetàl’utilisateurdecliquer surdutexte.

Check

Box

 

But

ton

— quihéritedespropriétésde etquipermetàl’utilisateurdecocher unecase.

Ra

dio

But

ton

 

But

ton

Ra

dio

Group

— qui hérite des propriétés de et qui permet à l’utilisateur de choisir parmi plusieurs choix. De plus,est un layout spécifique aux

Ra

dio

But

ton

.

— N’oubliezpasqueladocumentationestl’uniqueendroitoùvouspourreztrouvertoutes lespossibilitésoffertespourchacundeswidgetsdisponibles.

— Pourécouterlesdifférentsévènementsquipourraientseproduiresurvosvues,onutilise des listeners quienclenchentdesméthodesdecallback quevouspouvezredéfinirpour gérerleurimplémentation.

— Androidpermetdelierdeslistenersàdesvuesdetroismanièresdifférentes:

— Parhéritageenimplémentantl’interfaceauniveaudelaclasse,auquelcasilfaudra réécrirelesméthodesdecallback directementdansvotreclasse.

— Parclasseanonymeendonnantdirectementuneimplémentationuniqueàlavue.

— Parunattribut,sivousvoulezréutiliservotrelistenersurplusieursvues.


7.   Organiser son interface avec des layouts

Pourl’instant,laracinedetousnoslayoutsatoujoursétélamême,cequifaitquetoutesnos applicationsavaientexactementlemêmesquelette!Maisilvoussuffitderegardern’importe quelleapplicationAndroidpourréaliserquetouteslesvuesnesontpasforcémentorganisées comme cela et qu’il existe une très grande variété d’architectures différentes. C’est pourquoi nousallonsmaintenantétudierlesdifférentslayouts,afind’apprendreàplacernosvuescomme nousledésirons.Nouspourronsainsiconcevoiruneapplicationplusattractive,plusesthétique etplusergonomique!

7.1. LinearLayout : placer les éléments sur une ligne

an

droid:orien

ta

tion

Commesonnoml’indique,celayoutsechargedemettrelesvuessurunemêmeligne,selonune certaineorientation.L’attributpourpré peutluidonnerdeuxvaleurs:

ver

ti

cal

—pourquelescomposantssoientplacésdehautenbas(encolonne);

ho

ri

zon

tal

—pourquelescomposantssoientplacésdegaucheàdroite(enligne).

Onvafairequelquesexpériencespours’amuser!

7.1.0.1. Premier exemple

1         <LinearLayout xmlns:android=";

2         android:orientation="vertical"

3         android:layout_width="fill_parent"

4         android:layout_height="fill_parent" >

5         <Button

6         android:id="@+id/premier"

7         android:layout_width="fill_parent"

8         android:layout_height="wrap_content"

9         android:text="Premier bouton" />

10

11       <Button

12       android:id="@+id/second"

13       android:layout_width="fill_parent"

14       android:layout_height="wrap_content"

15       android:text="Second bouton" />

16       </LinearLayout>

Lerendudececodesetrouveàlafiguresuivante.

 

Figure 7.1.–Lesdeuxboutonsprennenttoutelalargeur

Li

near

Layout

— Leestverticaletprendtoutelaplacedesonparent(voussavez,l’invisible quiprendtoutelaplacedansl’écran).

— Lepremierboutonprendtoutelaplacedansleparentenlargeuretuniquementlataille nécessaireenhauteur(latailledutexte,donc!).

— Lesecondboutonfaitdemême.

7.1.0.2. Deuxième exemple

1       <LinearLayout xmlns:android=";

2       android:orientation="vertical"

3       android:layout_width="fill_parent"

4       android:layout_height="fill_parent" >

5

6        <Button

7        android:id="@+id/premier"

8        android:layout_width="wrap_content"

9        android:layout_height="fill_parent"

10       android:text="Premier bouton" />

11

12       <Button

13       android:id="@+id/second"

14       android:layout_width="wrap_content"

15       android:layout_height="fill_parent"

16       android:text="Second bouton" />

17       </LinearLayout>

Lerendudececodesetrouveàlafiguresuivante.

 

Li

near

Layout

Figure 7.2.–Lepremierboutonfaittoutelahauteur,onnevoitdoncpasledeuxièmebouton — Leestverticaletprendtoutelaplacedesonparent.

— Lepremierboutonprendtoutelaplacedesonparentenhauteuretuniquementlataille nécessaireenlargeur.

— Comme le premier bouton prend toute la place, alors le pauvre second bouton se fait écraser.C’estpourcelaqu’onnelevoitpas.

7.1.0.3. Troisième exemple

1         <LinearLayout xmlns:android=";

2         android:orientation="vertical"

3         android:layout_width="wrap_content"

4         android:layout_height="wrap_content" >

5         <Button

6         android:id="@+id/premier"

7         android:layout_width="wrap_content"

8         android:layout_height="fill_parent"

9         android:text="Premier bouton" /> 10             <Button

11       android:id="@+id/second"

12       android:layout_width="wrap_content"

13       android:layout_height="fill_parent"

14       android:text="Second bouton" />

15       </LinearLayout>

Lerendudececodesetrouveàlafiguresuivante.

 

Figure 7.3.–Les deux boutons prennent uniquement la place nécessaire en hauteur et en largeur

Li

near

Layout

— Leest vertical et prend toute la place en largeur mais uniquement la taille nécessaire en hauteur : dans ce cas précis, la taille nécessaire sera calculée en fonctiondelatailledesenfants.

— Lepremierboutonprendtoutelaplacepossibledansleparent.Commeleparentprend lemoinsdeplacepossible,ildoitfairedemême.

— Lesecondboutonfaitdemême.

7.1.0.4. Quatrième exemple

1        <LinearLayout xmlns:android=";

2        android:orientation="horizontal"

3        android:layout_width="fill_parent"

4        android:layout_height="fill_parent" >

5        <Button

6        android:id="@+id/premier"

7        android:layout_width="wrap_content"

8        android:layout_height="wrap_content"

9        android:text="Premier bouton" />

10       <Button

11       android:id="@+id/second"

12       android:layout_width="wrap_content"

13       android:layout_height="fill_parent"

14       android:text="Second bouton" />

15       </LinearLayout>

Lerendudececodesetrouveàlafiguresuivante.

 

Figure 7.4.–Lepremierboutonprenduniquementlaplacenécessaireetledeuxièmetoutela hauteur

Li

near

Layout

— Leesthorizontaletprendtoutelaplacedesonparent.

— Lepremierboutonprenduniquementlaplacenécessaire.

— Lesecondboutonprenduniquementlaplacenécessaireenlongueurets’étendjusqu’aux bordsduparentenhauteur.

Vousremarquerezquel’espaceesttoujoursdiviséentrelesdeuxboutons,soitdemanièreégale, soit un bouton écrase complètement l’autre. Et si on voulait que le bouton de droite prenne deuxfoisplusdeplacequeceluidegaucheparexemple?

Pourcela,ilfautattribuerunpoidsaucomposant.Cepoidspeutêtredéfinigrâceàl’attribut

an

droid:layout_weight

.Pourfaireensortequeleboutondedroiteprennedeuxfoisplus

an

droid:layout_weight="1"

de place, on peut lui mettreet mettre au bouton de gauche

an

droid:layout_weight="2"

.C’estalorslecomposantquialaplusfaiblepondérationquia

lapriorité.

an

droid:layout_weight="1"

Etsi,dansl’exempleprécédentoùunboutonenécrasaitunautre,lesdeuxboutonsavaienteu unpoidsidentique,parexemplepourlesdeux,ilsauraienteu lamêmeprioritéetauraientprislamêéfaut,cepoidsestà0. i

Uneastucequej’utilisesouventconsisteàfaireensortequelasommedespoidsdansun mêmelayoutfasse100.C’estunemanièreplusévidentepourrépartirlespoids.

an

droid:layout_gra

vity

an

droid:gra

vity

 

an

droid:layout_gra

vity

an

droid:gra

vity

Text

View

Dernier attribut particulier pour les widgets de ce layout,, qu’il ne faut pas confondre avec         .           vous permet de déterminercommentseplaceralavuedansleparent,alorsquevouspermet dedéterminercommentseplaceralecontenudelavueàl’intérieurmêmedelavue(parexemple, commentseplaceraletextedansun?Aucentre,enhaut,àgauche?). Vousprendrezbienunpetitexemplepourillustrercestroisconcepts?

1        <LinearLayout xmlns:android=";

2        android:orientation="horizontal"

3        android:layout_width="fill_parent"

4        android:layout_height="fill_parent" >

5        <Button

6        android:id="@+id/bouton1"

7        android:layout_width="fill_parent"

8        android:layout_height="wrap_content"

9        android:layout_gravity="bottom"

10       android:layout_weight="40"

11       android:text="Bouton 1" />

12       <Button

13       android:id="@+id/bouton2"

14       android:layout_width="fill_parent"

15       android:layout_height="wrap_content"

16       android:layout_gravity="center"

17       android:layout_weight="20"

18       android:gravity="bottom|right"

19       android:text="Bouton 2" />

20       <Button

21       android:id="@+id/bouton3"

22       android:layout_width="fill_parent"

23       android:layout_height="wrap_content"

24       android:layout_gravity="top"

25       android:layout_weight="40"

26       android:text="Bouton 3" />

27       </LinearLayout>

Lerendudececodesetrouveàlafiguresuivante.

 

Figure 7.5.–Troisboutonsplacésdifféremment

an

droid:layout_gra

vity

Commelebouton2aunpoidsdeuxfoisinférieurauxboutons1et3,alorsilprenddeuxfoisplus deplacequ’eux.Deplus,chaqueboutonpossèdeunattributafin dequel’ondéterminesapositiondanslelayout.Ledeuxièmeboutonprésenteaussil’attribut

an

droid:gra

vity

 

Text

View

                                                  ,quiestunattributde                             etnonlayout,defaçonàmettreletexte

bot

tom

enbas()àdroite(right).

7.1.1. Calcul de l’IMC - Partie 3.1

7.1.1.1. Énoncé

Récupérez le code de votreapplication de calcul de l’IMC et modifiez le layoutpour obtenir quelquechoseressemblantàlafiguresuivante.

 

Figure 7.6.–Essayezd’obtenirlamêmeinterface

Edit

Text

Lesprennentleplusdeplacepossible,maiscommeilsontunpoidsplusfortqueles

Text

View

,ilsn’ontpaslapriorité.

1       <?xml version="1.0" encoding="utf-8"?>

2       <LinearLayout xmlns:android=";

3       android:layout_width="fill_parent"

4       android:layout_height="fill_parent"

5       android:orientation="vertical">

 

6

<LinearLayout

7

8

9

10

android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"

11

<TextView

12

13

14

15

16

17

18

android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Poids : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="center" />

19

<EditText

20

21

22

23

24

25

26

android:id="@+id/poids"

android:layout_width="fill_parent" android:layout_height="wrap_content"

android:hint="Poids"

android:inputType="numberDecimal"

android:layout_weight="1"

/>

27

</LinearLayout>

28

<LinearLayout

29

30

31

32

 

33

<TextView

34

35

36

37

38

39

40

android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Taille : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="center" />

41

<EditText

42

43

44

45

46

47

48

android:id="@+id/taille" android:layout_width="fill_parent" android:layout_height="wrap_content"

android:hint="Taille"

android:inputType="numberDecimal"

android:layout_weight="1"

/>

49

</LinearLayout>

50

<RadioGroup

51

52

53

54

55

android:id="@+id/group"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:checkedButton="@+id/radio2" android:orientation="horizontal"

 

56

57

<RadioButton

58

59

60

61

android:id="@+id/radio1"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:text="Mètre"

62

/>

63

<RadioButton

64

65

66

67

68

android:id="@+id/radio2"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:text="Centimètre"

/>

69

</RadioGroup>

70

<CheckBox

71

72

73

74

75

android:id="@+id/mega"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mega fonction !" />

76

<LinearLayout

77

78

79

80

android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"

81

 

82

83

84

85

86

87

88

89

android:id="@+id/calcul"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Calculer l'IMC" android:layout_weight="1" android:layout_marginLeft="25dip" android:layout_marginRight="25dip"

/>

90

<Button

91

92

93

94

android:id="@+id/raz"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:text="RAZ"

95

android:layout_weight="1"

96

97

98

android:layout_marginLeft="25dip" android:layout_marginRight="25dip"

/>

99

</LinearLayout>

100

<TextView

101

102

103

104

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:text="Résultat:" />

105

<TextView

106       android:id="@+id/result"

107       android:layout_width="fill_parent"

108       android:layout_height="fill_parent"

109       android:text="Vous devez cliquer sur le bouton « Calculer l'IMC » pour

110       />

111       </LinearLayout>

!

Demanièregénérale,onévited’empilerlesLinearLayout(avoirunLinearLayoutdans unLinearLayout,dansunLinearLayout,etc.),c’estmauvaispourlesperformances d’uneapplication.

7.2. RelativeLayout : placer les éléments les uns en fonction des autres

Re

la

ti

ve

Layout

De manière totalement différente, ce layout propose plutôt de placer les composants les uns par rapport aux autres. Il est même possible de les placer par rapport au parent.

Re

la

ti

ve

Layout

an

droid:layout_cen

te

rIn

Parent="true"

an

droid:layout_cen

te

rHo

ri

zon

tal="true"

an

droid:layout_cen

ter

Ver

ti

cal="true"

Si on veut par exemple placer une vue au centre d’un, on peut passer à cettevuel’attribut.Ilestaussipossibled’utiliserpour centrer, mais uniquement sur l’axe horizontal,demêmeavecpourcentrersurl’axe vertical.

7.2.0.1. Premier exemple

1       <RelativeLayout xmlns:android=";

2       android:layout_width="fill_parent"

3       android:layout_height="fill_parent" >

4

5        <TextView

6        android:layout_width="wrap_content"

7        android:layout_height="wrap_content"

8        android:text="Centré dans le parent"

9        android:layout_centerInParent="true" />

10       <TextView

11       android:layout_width="wrap_content"

12       android:layout_height="wrap_content"

13       android:text="Centré verticalement"

14       android:layout_centerVertical="true" />

15       <TextView

16       android:layout_width="wrap_content"

17       android:layout_height="wrap_content"

18       android:text="Centré horizontalement"

19       android:layout_centerHorizontal="true" />

20

21 </RelativeLayout>

Lerendudececodesetrouveàlafiguresuivante.

 

Figure 7.7.–Deuxvuessontempilées

Li

near

Layout

Text

View

On observe ici une différence majeure avec le: il est possible d’empiler les vues. Ainsi, lecentré verticalement s’entremêle avec celui centré verticalement et horizontalement.

Re

la

ti

ve

Layout

Ilexiste d’autres contrôlespour situer unevue par rapport à peut utiliser:

an

droid:layout_ali

gn

Pa

rent

Bot

tom="true"

Re

la

ti

ve

Layout

—pouralignerleplancherd’unevueau plancherdu;

an

droid:layout_ali

gn

Pa

rent

Top="true"

Re

la

ti

ve

Layout

—pour coller le plafond d’une vue au plafonddu;

an

droid:layout_ali

gn

Pa

rent

Left="true"

Re

la

ti

ve

Layout

—pour coller le bord gauche d’une vue aveclebordgauchedu;

an

droid:layout_ali

gn

Pa

ren

tRight="true"

Re

la

ti

ve

Layout

—pourcollerleborddroitd’unevueavec leborddroitdu.

7.2.0.2. Deuxième exemple

1        <RelativeLayout xmlns:android=";

2        android:layout_width="fill_parent"

3        android:layout_height="fill_parent" >

4        <TextView

5        android:layout_width="wrap_content"

6        android:layout_height="wrap_content"

7        android:text="En haut !"

8        android:layout_alignParentTop="true" />

9        <TextView

10       android:layout_width="wrap_content"

11       android:layout_height="wrap_content"

12       android:text="En bas !"

13       android:layout_alignParentBottom="true" />

14       <TextView

15       android:layout_width="wrap_content"

16       android:layout_height="wrap_content"

17       android:text="A gauche !"

18       android:layout_alignParentLeft="true" />

19       <TextView

20       android:layout_width="wrap_content"

21       android:layout_height="wrap_content"

22       android:text="A droite !"

23       android:layout_alignParentRight="true" />

24       <TextView

25       android:layout_width="wrap_content"

26       android:layout_height="wrap_content"

27       android:text="Ces soirées là !"

28       android:layout_centerInParent="true" />

29       </RelativeLayout>

Lerendudececodesetrouveàlafiguresuivante.

 

Figure 7.8.–Enhautàgauche,deuxTextViewsesuperposent

Text

View

Re

la

ti

ve

Onremarquetoutdesuitequelescenséssesitueràgaucheetenhauts’entremêlent, mais c’est logique puisque par défaut une vue se place en haut à gauche dans un ,quandonluidit«Place-toiàgauche»ou«Place-toienhaut»,c’estcommesi onneluidonnaitpasd’instructionsaufinal.

Enfin,ilnefautpasoublierqueleprincipalintérêtdecelayoutestdepouvoirplacerleséléments lesunsparrapportauxautres.Pourcelailexistedeuxcatégoriesd’attributs:

— Ceuxquipermettentdepositionnerdeuxbordsopposésdedeuxvuesdifférentesensemble.

an

droid:layout_be

low

an

droid:layout_above

an

droid:layout_to

Righ

tOf

an

droid:layout_to

Lef

tOf

Onytrouve(pouralignerleplafondd’unevuesousleplancher d’uneautre),(pouralignerleplancherd’unevuesurleplafond d’uneautre),(pouralignerlebordgauched’unevueau borddroitd’uneautre)et(pouralignerleborddroitd’une vueaubordgauched’uneautre).

an

droid:layout_ali

— Ceuxquipermettentdecollerdeuxbordssimilairesensemble.Ontrouve

gn

Bot

tom

 

an

droid:layout_ali

(pouralignerleplancherdelavueavecleplancherd’uneautre),

gn

Top

 

an

droid:layout_ali

(pouralignerleplafonddelavueavecleplafondd’uneautre),

gn

Left

(pour aligner le bord gauche d’une vue avec le bord gauche d’une autre) et

an

droid:layout_ali

gn

Right

(pouralignerleborddroitdelavueavecleborddroit

d’uneautre).

7.2.0.3. Troisième exemple

1         <RelativeLayout xmlns:android=";

2         android:layout_width="fill_parent"

3         android:layout_height="fill_parent" >

4         <TextView

5         android:id="@+id/premier"

6         android:layout_width="wrap_content"

7         android:layout_height="wrap_content"

8         android:text="[I] En haut à gauche par défaut" /> 9  <TextView

10       android:id="@+id/deuxieme"

11       android:layout_width="wrap_content"

12       android:layout_height="wrap_content"

13       android:text="[II] En dessous de (I)"

14       android:layout_below="@id/premier" />

15       <TextView

16       android:id="@+id/troisieme"

17       android:layout_width="wrap_content"

18       android:layout_height="wrap_content"

19       android:text="[III] En dessous et à droite de (I)"

20       android:layout_below="@id/premier"

21       android:layout_toRightOf="@id/premier" />

22       <TextView

23       android:id="@+id/quatrieme"

24       android:layout_width="wrap_content"

25       android:layout_height="wrap_content"

26       android:text="[IV] Au dessus de (V), bord gauche aligné avec le bord ga

27       android:layout_above="@+id/cinquieme"

28       android:layout_alignLeft ="@id/deuxieme" />

29       <TextView

30       android:id="@+id/cinquieme"

31       android:layout_width="wrap_content"

32       android:layout_height="wrap_content"

33       android:text="[V] En bas à gauche"

34       android:layout_alignParentBottom="true"

35       android:layout_alignParentRight="true" />

36       </RelativeLayout>

Lerendudececodesetrouveàlafiguresuivante.

 

Figure 7.9.–LesTextViewsontbienplacés

Text

View

Jevousdemandemaintenantderegarderl’avantdernier,enparticuliersonattribut

an

droid:layout_above

 

Text

View

                                                                  .Onnefaitpasréférenceaudernier                           commeauxautres,il

fautpréciserun+!Ehoui,rappelez-vous,jevousavaisditilyaquelqueschapitresdéjàque,si nous voulions faire référence à une vue qui n’était définie que plus tard dans le fichier XML, alorsilfallaitajouterun+dansl’identifiant,sinonAndroidpenseraqu’ils’agitd’unefauteet nond’unidentifiantquiseradéclaréaprès.

7.2.1. Calcul de l’IMC - Partie 3.2

Mêmechosepourunlayoutdifférent!Moi,jeviselemêmerésultatqueprécédemment.

7.2.1.1. Ma solution

1       <?xml version="1.0" encoding="utf-8"?>

2       <RelativeLayout xmlns:android=";

3       android:layout_width="fill_parent"

 

4

android:layout_height="fill_parent">

5

<TextView

6

7

8

9

10

11

12

android:id="@+id/textPoids" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Poids : " android:textStyle="bold" android:textColor="#FF0000"

/>

13

<EditText

14

15

16

17

18

19

20

21

android:id="@+id/poids"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:hint="Poids"

android:inputType="numberDecimal" android:layout_toRightOf="@id/textPoids" android:layout_alignParentRight="true"

/>

22

<TextView

23

24

25

26

27

28

29

30

31

 

32

<EditText

33

34

35

36

37

38

39

40

41

android:id="@+id/taille"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:hint="Taille"

android:inputType="numberDecimal" android:layout_below="@id/poids" android:layout_toRightOf="@id/textTaille" android:layout_alignParentRight="true"

/>

42

<RadioGroup

43

44

45

46

47

48

49

android:id="@+id/group"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:checkedButton="@+id/radio2" android:orientation="horizontal" android:layout_below="@id/taille"

50

<RadioButton

51

52

53

android:id="@+id/radio1"

android:layout_width="wrap_content" android:layout_height="wrap_content"

54         android:text="Mètre"

55         />

56         <RadioButton

57         android:id="@+id/radio2"

58         android:layout_width="wrap_content"

59         android:layout_height="wrap_content"

60         android:text="Centimètre"

61         />

62         </RadioGroup>

63         <CheckBox

64         android:id="@+id/mega"

65         android:layout_width="wrap_content"

66         android:layout_height="wrap_content"

67         android:text="Mega fonction !"

68         android:layout_below="@id/group"

69         />

70         <Button

71         android:id="@+id/calcul"

72         android:layout_width="wrap_content"

73         android:layout_height="wrap_content"

74         android:text="Calculer l'IMC"

75         android:layout_below="@id/mega"

76         android:layout_marginLeft="25dip"

77         />

78         <Button

79         android:id="@+id/raz"

80         android:layout_width="wrap_content"

81         android:layout_height="wrap_content"

82         android:text="RAZ"

83         android:layout_below="@id/mega"

84         android:layout_alignRight="@id/taille"

85         android:layout_marginRight="25dip"

86         />

87         <TextView

88         android:id="@+id/resultPre"

89         android:layout_width="wrap_content"

90         android:layout_height="wrap_content"

91         android:text="Résultat:"

92         android:layout_below="@id/calcul"

93         />

94         <TextView

95         android:id="@+id/result"

96         android:layout_width="fill_parent"

97         android:layout_height="fill_parent"

98         android:text="Vous devez cliquer sur le bouton « Calculer l'IMC » pour 99  android:layout_below="@id/resultPre"

100     />

101     </RelativeLayout>

Le problème de ce layout, c’est qu’une petite modification dans l’interface graphique peut provoquerdegrossesmodificationsdanstoutlefichierXML,ilfautdoncsavoirparavancetrès précisémentcequ’onveutfaire. i

Ils’agitdulayoutlepluscompliquéàmaîtriser,etpourtantlepluspuissanttoutenétant l’undesmoinsgourmandsenressources.Jevousencouragefortementàvousentraînerà l’utiliser.

7.3. TableLayout : placer les éléments comme dans un tableau

Dernierlayoutdebase,ilpermetd’organiserlesélémentsentableau,commeenHTML,mais sanslesbordures.Voiciunexempled’utilisationdecelayout:

   

Cequidonnelafiguresuivante.

 

Figure 7.10.–Lecontenuestorganiséentableau

<Ta

ble

Row>

Onobservetoutd’abordqu’ilestpossibledemettredesvuesdirectementdansletableau,auquel casellesprendronttoutelaplacepossibleenlongueur.Enfait,elless’étendrontsurtoutesles colonnesdutableau.Cependant,sionveutuncontrôlepluscompletouavoirplusieurséléments surunemêmeligne,alorsilfautpasserparunobjet.

1       <TextView

2       android:text="Les items précédés d'un V ouvrent un sous-menu" />

<Ta

ble

Row>

Cetéléments’étendsurtoutelalignepuisqu’ilnesetrouvepasdansun

 

<Ta

ble

Moyenefficacepourdessinerunséparateur—n’essayezpasdelefaireendehorsd’un Layout>ouvotreapplicationplantera.

Uneligneestcomposéedecellules.Chaquecellulepeutcontenirunevue,ouêtrevide.Lataille dutableauencolonnesestcelledelalignequicontientleplusdecellules.Dansnotreexemple, nousavonstroiscolonnespourtoutletableau,puisquelaligneaveclepluscellulesestcellequi contient«V»etseterminepar«Làsi!».

   

Cetteligneatroiséléments,c’estlapluslonguedutableau,cedernierestdoncconstituéde troiscolonnes.

an

droid:layout_co

Ilestpossibledechoisirdansquellecolonnesesitueunitemavecl’attribut

an

droid:layout_co

lumn="1"

lumn. Attention, l’index des colonnes commence à 0. Dans notre exemple, le dernier item se placedirectementàladeuxièmecolonnegrâceà.

 

Text

View

Onveutlaisservidel’espacepourlapremièrecolonne,onplacealorslesdeuxdans lescolonnes1et2.

La taille d’une cellule dépend de la cellule la plus large sur une même colonne. Dans notre exemple,lasecondecolonnefaitlalargeurdelacellulequicontientletexte«N’ouvrepasun sous-menu»,puisqu’ilsetrouvedansladeuxièmecolonneetqu’iln’yapasd’autreséléments danscettecolonnequisoitplusgrand.

an

droid:layout_span

an

droid:layout_co

lumn

Enfin,ilestpossibled’étendreunitemsurplusieurscolonnesàl’aidedel’attribut. Dansnotreexemple,ledernieritems’étenddeladeuxièmecolonneàlatroisième.Ilestpossible defairedemêmesurleslignesavecl’attribut.

   

Text

View

Cedébute à la deuxième colonne et s’étend sur deux colonnes, donc jusqu’à la troisième.

Ta

ble

Layout

Surlenœud,onpeutjoueravectroisattributs(attention,lesrangsdébutentà 0):

an

droid:stret

ch

Co

lumns

fill_pa

rent

—pourquelalongueurdetouslesélémentsdecettecolonne passeen,doncpourprendreleplusdeplacepossible.Ilfautpréciserle rangdelacolonneàcibler,ouplusieursrangsséparéspardesvirgules.

an

droid:shrink

Co

lumns

—pourquelalongueurdetouslesélémentsdecettecolonne passeenwrap_content,doncpourprendrelemoinsdeplacepossible.Ilfautpréciser lerangdelacolonneàcibler,ouplusieursrangsséparéspardesvirgules.

an

droid:col

lap

se

Co

lumns

—pourfairepurementetsimplementdisparaîtredescolonnes dutableau.Ilfautpréciserlerangdelacolonneàcibler,ouplusieursrangsséparéspar desvirgules.

7.3.1. Calcul de l’IMC - Partie 3.3

7.3.1.1. Énoncé

Réitéronsl’expérience,essayezencoreunefoisd’obtenirlemêmerendu,maiscettefoisavecun

Ta

ble

Layout

.L’exerciceestintéressantpuisqu’onn’estpasvraimentenprésenced’untableau,

ilvadoncfalloirréfléchirbeaucoupetexploiteraumaximumvosconnaissancespourobtenirun renduacceptable.

7.3.1.2. Ma solution

1           <?xml version="1.0" encoding="utf-8"?>

2           <TableLayout xmlns:android=";

3           android:layout_width="fill_parent"

4           android:layout_height="fill_parent"

5           android:stretchColumns="1">

6           <TableRow>

7           <TextView

8           android:text="Poids : "

9           android:textStyle="bold"

10          android:textColor="#FF0000"

11          android:gravity="center"

12          />

13          <EditText

14          android:id="@+id/poids"

 

15

16

17

18

android:hint="Poids"

android:inputType="numberDecimal"

android:layout_span="2"

/>

19

</TableRow>

20

<TableRow>

21

<TextView

22

23

24

25

26

27

28

android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Taille : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="center" />

29

<EditText

30

31

32

33

34

35

36

android:id="@+id/taille" android:layout_width="fill_parent" android:layout_height="wrap_content"

android:hint="Taille"

android:inputType="numberDecimal"

android:layout_span="2"

/>

37

</TableRow>

38

<RadioGroup

39

40

41

42

43

44

 

45

46

47

48

android:id="@+id/radio1"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:text="Mètre"

49

/>

50

<RadioButton

51

52

53

54

55

android:id="@+id/radio2"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:text="Centimètre"

/>

56

</RadioGroup>

57

<CheckBox

58

59

60

61

62

android:id="@+id/mega"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mega fonction !" />

63

<TableRow>

64

<Button

7.4. FrameLayout : un layout un peu spécial

View

Group

Fra

me

Layout

an

droid:vi

si

bi

lity

Fra

me

Layout

Celayoutestplutôtutilisépourafficheruneuniquevue.Ilpeutsemblerinutilecommeça,mais nel’estpasdutout!Iln’estdestinéàafficherqu’unélément,maisilestpossibled’enmettre plusieursdedanspuisqu’ils’agitd’un.Siparexemplevoussouhaitezfaireunalbum photo,ilvoussuffitdemettreplusieursélémentsdansleetdenelaisserqu’une seulephotovisible,enlaissantlesautresinvisiblesgrâceàl’attribut(cet attributestdisponiblepourtouteslesvues).PareilpourunlecteurdePDF,ilsuffitd’empiler touteslespagesdansleetden’afficherquelapageactuelle,celledudessusdela pile,àl’utilisateur.Cetattributpeutprendretroisvaleurs:

vi

sible

 

SIBLE

          —                   (                             ),lavaleurpardéfaut.

in

vi

sible

 

VI

SIBLE

—  (          )n’afficherien,maisestprisencomptepourl’affichage dulayoutniveauspatial(onluiréservedelaplace).

— gone()n’afficherienetneprendpasdeplace,unpeucommes’iln’étaitpas là.

pu

blic

void

set

Vi

si

bi

lity

(int)

L’équivalentJavadecetattributestaveccommepara-

Fra

me

Layout

mètreunedesvaleursentreparenthèsesdanslalisteci-dessus.Quandilyaplusieurséléments dansun,celui-cilesempilelesunsau-dessusdesautres,lepremierélémentdu XMLsetrouvantendernièrepositionetledernierajoutétoutau-dessus.

7.5. ScrollView : faire défiler le contenu d’une vue

Scroll

View

Nevouslaissezpasbernezparsonnom,cettevueestbeletbienunlayout.Elleestparailleurs un peu particulière puisqu’elle fait juste en sorte d’ajouter une barre de défilement verticale à un autre layout. En effet, si le contenu de votre layout dépasse la taille de l’écran, une partie du contenu sera invisible à l’utilisateur. De façon à rendre ce contenu visible, on peut préciserquelavueestenglobéedansune,etunebarrededéfilements’ajoutera automatiquement.

Fra

me

Layout

Li

near

Layout

Celayouthéritede,parconséquentilvautmieuxenvisagerdenemettrequ’une ’utiliseengénéralavec,maispeutêtreutiliséavectousles layouts…oubiendeswidgets!Parexemple:

1         <?xml version="1.0" encoding="utf-8"?>

2         <ScrollView

3         xmlns:android=";

4         android:layout_width="fill_parent"

5         android:layout_height="wrap_content">

6         <LinearLayout>

7         <!-- contenu du layout -->

8         </LinearLayout> 9 </ScrollView>

!

Attentioncependant,ilnefautpasmettredewidgetsquipeuventdéjàdéfilerdansune ScrollView,sinonilyauraconflitentrelesdeuxcontrôleursetlerésultatseramédiocre. Nousn’avonspasencorevudewidgetsdecetype,maiscelanesauraittarder.

 

Li

near

Layout

—permet d’afficher plusieurs vues sur une même ligne de manière horizontale ou verticale. Il est possible d’attribuer un poids aux vues pour effectuer des placementsprécis.

Re

la

ti

ve

Layout

—permetd’afficherdesvueslesunesenfonctiondesautres.

Ta

ble

Layout

Fra

me

Layout

       

—permetd’organiserlesélémentsentableau.

—permetd’afficherunevueàl’écranoud’ensuperposerplusieurslesunes au-dessusdesautres.

Scroll

View

—permetderendre«scrollable»lavuequ’ellecontient.Attentiondenelui donner qu’un fils et de ne pas fournir des vues déjà « scrollable » sinon il y aura des conflits.


8.   Les autres ressources

Maintenantquevousavezparfaitementcompriscequ’étaientlesressources,pourquoietcomment lesutiliser,jevousproposedevoir…commentlescréer.Ilexisteunegrandevariétéressources différences,c’estpourquoionnelesverrapastoutes.Jevousprésenteraiiciuniquementlesplus utilesetpluscompliquéesàutiliser.

Undernierconseilavantd’entrerdanslevifdusujet:créezleplusderessourcespossible,dès quevouslepouvez.Ainsi,vosapplicationsserontplusflexibles,etledéveloppementseraplus évident.

8.1. Aspect général des fichiers de ressources

Nousallonsvoircommentsontconstituéslesfichiersderessourcesquicontiennentdesvalues

(jelesappellerai«données»désormais).C’estencoreunefoisunfichierXML,maisquirevêt cetteforme-ci:

 

res/va

Afin d’avoir un petit aperçu de ce à quoi elles peuvent ressembler, on va d’abord observer les fichiers que crée Android à la création d’un nouveau projet. Double-cliquez sur le fichier pourouvrirunenouvellefenêtre(voirfiguresuivante).

 

Figure 8.1.–Fenêtred’éditiondesdonnées

Onretrouveàgauchetouteslesressourcesquisontcontenuesdanscefichier.Làilyenadeux, c’estplutôtfaciledes’yretrouver,maisimaginezungrosprojetavecunecinquantainevoire unecentainededonnées,vousrisquezdevitevousyperdre.Sivousvoulezévitercetypede désagréments,vouspouvezenvisagerdeuxmanièresdevousorganiser:

— Réunirlesdonnéesd’unmêmetypepouruneactivitédansunseulfichier.Parexemple strings.xmlpourtoutesleschainesdecaractères.Leproblèmeestqu’ilvousfaudra créerbeaucoupdefichiers,cequipeutêtrelong.

— Oualorsmettretouteslesdonnéesd’uneactivitédansunfichier,cequidemandemoins detravail,maisnécessiteunemeilleureorganisationafindepouvoirs’yretrouver.

!

N’oubliezpasqu’Androidestcapablederetrouverautomatiquementdesressourcesparce qu’ellessesituentdansunfichierprécisàunemplacementprécis.Ainsi,quellequesoit l’organisationpourlaquellevousoptez,ilfaudralarépercuteràtouslesrépertoiresvalues, tous différenciés par des quantificateurs, pour que les données se retrouvent dans des fichiersaunomidentiquemaisdansdesrépertoiresdifférents.

Sivoussouhaitezopterpourlasecondeorganisation,alorslemeilleurmoyendes’yretrouver estdesavoirtrierlesdifférentesressourcesàl’aidedumenuquisetrouveenhautdelafenêtre. Ilvouspermetdefiltrerlalistedesdonnéesenfonctiondeleurtype.Voicilasignificationde touslesboutons:

Co

lor

—:Afficheruniquementleschaînesdecaractères(String)

—:Afficheruniquementlescouleurs()

Di

men

sion

Dra

wable

—:Afficheruniquementlesdimensions()

—:Afficheruniquementlesdrawables()

—:Afficheruniquementlesstylesetthèmes(Style)

—:Afficheruniquementlesélémentsquiappartiennentàunensemble(àuntableau parexemple)(Item)

String Ar

ray

Int Ar

ray

—:Afficheruniquementlestableauxdechaînesdecaractères()

—:Afficheruniquementlestableauxd’entiers()

—:Rangerlalistedansl’ordrealphabétiquedunomdeladonnée.Unsecondclicrange dansl’ordrealphabétiqueinverse

De plus, le menu du milieu (voir figure suivante) vous permet de créer ou supprimer des données.

 

Figure 8.2.–Menudumilieu

— LeboutonAddpermetd’ajouterunenouvelledonnée.

Re

move

— Leboutonpermetdesupprimerunedonnée.

— Le bouton Up permet d’augmenter d’un cran la position de la donnée dans le tableau central.

— LeboutonDownpermetdediminuerd’uncranlapositiondeladonnéedansletableau central.

Personnellement, je n’utilise cette fenêtre que pour avoir un aperçu rapide de mes données. Cependant, dès qu’il me faut effectuer des manipulations, je préfère utiliser l’éditeur XML. D’ailleurs je ne vous apprendrai ici qu’à travailler avec un fichier XML, de manière à ce que vous ne soyez pas totalement déboussolés si vous souhaitiez utiliser une autre extension que l’ADT.Vouspouveznaviguerentrelesdeuxinterfacesàl’aidedesdeuxboutonsenbasdela fenêtre,visiblesàlafiguresuivante.

 

Figure 8.3.–Vouspouveznaviguerentrelesdeuxinterfaces

8.1.1. Référence à une ressource

Nousavonsdéjàvuquequanduneressourceavaitunidentifiant,Androids’occupaitd’ajouter aufichierR.javauneréférenceàl’identifiantdecetteressource,defaçonàcequenouspuissions larécupérerenl’inflatant.Lasyntaxedelaréférenceétait:

 

Cequejenevousaipasdit,c’estqu’ilétaitaussipossibled’yaccé’estpas tellementpluscompliquéqu’enJavapuisqu’ilsuffitderespecterlasyntaxesuivante:

 

sa

lut

lut

 

@string/sa

lut

Parexemplepourunechaînedecaractèresquis’appellerait,onyferaitréférenceenJava àl’aidede           etenXMLavec.

An

droid.R.type_de_res

source.nom_de_la_res

@an

droid:type_de_res

source/nom_de_la_res

source

Enfin,silaressourceàlaquelleonessaied’accéderestuneressourcefournieparAndroiddans sonSDK,ilsuffitderespecterlasyntaxe sourceenJavaetenXML.

8.2. Les chaînes de caractères

Texte de la chaîne qui s'ap

pelle "nom

De

Vous connaissez les chaînes de caractères, c’est le mot compliqué pour désigner un texte. La syntaxeestévidenteàmaîtriser,parexemplesinousvoulionscréerunechaînedecaractères de nom « nomDeLExemple » et de valeur

Etilsontdisparuoù,lesguillemetsetl’apostrophe?

Commençonsparl’évidence,s’iln’yaniespace,niapostrophedanslenom,c’estparcequ’il s’agit du nom d’une variable comme nous l’avons vu précédemment, par conséquent il faut respecterlesrèglesdenommaged’unevariablestandard.

Pour ce qui est du texte, il est interdit d’insérer des apostrophes ou des guillemets. Sinon, commentAndroidpeut-ildétecterquevousavezfinid’écrireunephrase?Afindecontourner cette limitation, vous pouvez très bien échapper les caractères gênants, c’est-à-dire les faire précéderd’unantislash().

1 <string name="nomDeLExemple">Texte de la chaîne qui s\'appelle \"nomDeLExemple\"</string>

Vous pouvez aussi encadrer votre chaîne de guillemets afin de ne pas avoir à échapper les apostrophes;enrevanchevousaureztoujoursàéchapperlesguillemets.

1 <string name="nomDeLExemple">"Texte de la chaîne qui s'appelle \"nomDeLExemple\""</string>

8.2.1. Application

Vous

connais

sez

Je vous propose de créer un bouton et de lui associer une chaîne de caractères qui contient des balises HTML (<b>, <u> et <i>) ainsi que des guillemets et des apostrophes. Si vous ne connaissez pas de balises HTML, vous allez créer la chaîne suivante : «

l'his

toire

de

<b>"Tom

Sawyer"</b>

?».Lesbalises<b></b>vouspermettentdemettre

dutexteengras.

8.2.1.1. Instructions

Span

ned

 

Span

ned

Span

ned

Html.fromHtml

(String

source)

— On peut convertir notre String en . est une classe particulière qui représente les chaînes de caractères qui contiennent des balises HTML et qui peut les interpréterpourlesaffichercommeleferaitunnavigateurinternet.Cettetransformation sefaitàl’aidedelaméthodestatique.

Span

ned

 

void

set

Text

            — On mettra ce                        comme texte sur le bouton avec la méthode

(Char

Se

quence

text)

.

i

Les caractères spéciaux < et > doivent être écrits en code HTML. Au lieu d’écrire < vous devez marquer « et à la place de > il faut insérer ». Si vous utilisez l’interface graphiquepourlacréationdeString,ilconvertiraautomatiquementlescaractères!Mais ilconvertiraaussilesguillemetsencodeHTML,cequ’ilnedevraitpasfaire…

8.2.1.2. Ma correction

:

1       <?xml version="1.0" encoding="utf-8"?>

2       <resources>

3       <string name="hello">Hello World, TroimsActivity!</string>

4       <string name="histoire">Vous connaissez l\'histoire de <b>\"Tom Sawyer\"</b> ?</string>

5       <string name="app_name">Troims</string>

6       </resources>

EtlecodeJavaassocié:

1    import .Activity;

2    import .Bundle;

3    import ;

4    import .Spanned;

5    import android.widget.Button;

6

7       public class StringExampleActivity extends Activity {

8       Button button = null;

9       String hist = null;

10

11       @Override

12       public void onCreate(Bundle savedInstanceState) {

13       super.onCreate(savedInstanceState);

14

15       // On récupère notre ressource au format String

16       hist = getResources().getString(R.string.histoire);

17       // On le convertit en Spanned

18       Spanned marked_up = Html.fromHtml(hist);

19

20       button = new Button(this);

21       // Et on attribue le Spanned au bouton

22       button.setText(marked_up);

23

24       setContentView(button);

25       }

26       }

8.2.2. Formater des chaînes de caractères

Leproblèmeavecnoschaînesdecaractèresentantqueressources,c’estqu’ellessontstatiques. Ellesnesontpasdestinéesàêtremodifiéesetparconséquentellesnepeuventpass’adapter.

Imaginonsuneapplicationquisaluequelqu’un,quiluidonnesonâge,etquis’adapteàlalangue de l’utilisateur. Il faudrait qu’elle dise : « Bonjour Anaïs, vous avez 22 ans » en français et « Hello Anaïs, you are 22 » en anglais. Cette technique est par exemple utilisée dans le jeu Civilization IV pourtraduireletexteenplusieurslangues.Pourindiquerdansunechaînede caractèresàquelendroitsesituelapartiedynamique,onvautiliseruncode.Dansl’exemple

Bon

jour

%1$s,

vous

avez

%2$d

ans

 

Hello

%1$s,

précédent,onpourraitavoir                                                                          enfrançaiset

you

are

%2$d

enanglais.L’astuceestquelapremièrepartieducodecorrespondàuneposition dansunelisted’arguments(qu’ilfaudrafournir)etlasecondepartieàuntypedetexte(int, float,string,bool,…).End’autrestermes,uncodesedécomposeendeuxparties:

— %n avec « n » étant un entier naturel (nombre sans virgule et supérieur à 0) qui sert àindiquerlerangdel’argumentàinsérer(%1correspondaupremierargument,%2au deuxièmeargument,etc.);

— $x,quiindiquequeltyped’informationonveutajouter($spourunechaînedecaractères et$dpourunentier—vouspourreztrouverlalistecomplètedespossibilitéssurcette page  ).

On va maintenant voir comment insérer les arguments. Il existe au moins deux manières de faire.

Onpeutlefaireenrécupérantlaressource:

1    Resources res = getResources();

2    // Anaïs ira en %1 et 22 ira en %2

3    String chaine = res.getString(R.string.hello, "Anaïs", 22); Oualorssurn’importequellechaîneavecunefonctionstatiquedeString:

1    // On n'est pas obligé de préciser la position puisqu'on n'a qu'un argument !

2    String iLike = String.format("J'aime les $s", "pâtes");

8.2.2.1. Application

C’estsimple,jevaisvousdemanderd’arriveraurésultatvisibleàlafiguresuivante.

 

Figure 8.4.–L’exempleàreproduire

8.2.2.2. Ma solution

va

lues

va

lues

On aura besoin de deux fichiers : un dans le répertoireet un dans le répertoire-enquicontiendraletexteenanglais:

va

1       <?xml version="1.0" encoding="utf-8"?>

2       <resources>

3       <string name="hello">Bonjour %1$s, vous avez %2$d ans.</string>

4       <string name="app_name">Deums</string>

5       </resources>

va

lues

1       <?xml version="1.0" encoding="utf-8"?>

2       <resources>

3       <string name="hello">Hello %1$s, you are %2$d.</string>

4       <string name="app_name">Deums</string>

5       </resources>

Text

View

Deplusonvadonnerunidentifiantànotrepourrécupérerlachaîne:

1       <?xml version="1.0" encoding="utf-8"?>

2       <LinearLayout xmlns:android=";

3       android:layout_width="fill_parent"

4       android:layout_height="fill_parent"

5       android:orientation="vertical" >

6

7        <TextView

8        android:id="@+id/vue"

9        android:layout_width="fill_parent"

10       android:layout_height="wrap_content" />

11

12 </LinearLayout>

Text

View

Etenfin,onvarécupérernotreetafficherletextecorrectpourunefemmes’appelant Anaïsetquiaurait22ans:

1    import .Activity;

2    import .Resources;

3    import .Bundle;

4    import android.widget.TextView;

5

6    public class DeumsActivity extends Activity {

7    @Override

8    public void onCreate(Bundle savedInstanceState) {

9    super.onCreate(savedInstanceState); 10

11                               setContentView();

12

13       Resources res = getResources();

14       // Anaïs se mettra dans %1 et 22 ira dans %2, mais le reste changera en fonction de la langue du terminal !

15       String chaine = res.getString(R.string.hello, "Anaïs", 22);

16       TextView vue = (TextView)findViewById();

17       vue.setText(chaine);

18       }

19       }

Etvoilà,enfonctiondelalanguedel’émulateur,letexteseradifférent!

8.3. Les drawables

Ladénomination«drawable»rassembletouslesfichiers«dessinables»(oui,cemotn’existe pas en français, mais « drawable » n’existe pas non plus en anglais après tout ), c’est-à-dire lesdessinsoulesimages.Jeneparleraiquedesimagespuisquecesontlesdrawableslesplus utilisésetlesplusindispensables.

8.3.1. Les images matricielles

Android supporte trois types d’images : les PNG, les GIF et les JPEG. Sachez que ces trois formatsn’ontpaslesmêmesusages:

— LesGIFsontpeurecommandés.Onlesutilisesurinternetpourlesimagesdemoindre qualitéoulespetitesanimations.Onvadoncleséviterleplussouvent.

— LesJPEGsontsurtoututilisésenphotographieoupourlesimagesdontonveutconserver lahautequalité.Ceformatnegèrepaslatransparence,donctoutesvosimagesseront rectangulaires.

— LesPNGsontunboncompromisentrecompressionetqualitéd’image.Deplus,ilsgèrent latransparence.Silechoixseprésente,optezpourceformat-là.

Iln’yariendeplussimplequed’ajouteruneimagedanslesressources,puisqu’ilsuffitdefaire glisser le fichier à l’emplacement voulu dans Eclipse (ou mettre le fichier dans le répertoire voulu dans les sources de votre projet), comme à la figure suivante, et le drawable sera créé automatiquement.

 

Figure 8.5.–On se contente de glisser-déposer l’image dans le répertoire voulu et Android feralereste

!

Le nom du fichier déterminera l’identifiant du drawable, et il pourra contenir toutes les lettres minuscules, tous les chiffres et des underscores ( _ ), mais attention, pas de ,onpourrarécupérerledrawableàl’aidedeR.drawable.nom_du_fi chier_sans_l_extension.

8.3.2. Les images extensibles

Utiliseruneimagepermetd’agrémentersonapplication,mais,sionveutqu’ellesoitdequalité pourtouslesécrans,ilfaudraituneimagepourchaquerésolution,cequiestlong.Lasolution lapluspratiqueseraituneimagequis’étiresansjamaisperdreenqualité!Danslesfaits,c’est difficileàobtenir,maiscertainesimagessontassezsimplespourqu’Androidpuissedéterminer commentétirerl’imageenperdantlemoinsdequalitépossible.Jefaisiciréférenceàlatechnique 9-Patch. Un exemple sera plus parlant qu’un long discours : on va utiliser l’image visible à la figure suivante, qui est aimablement prêtée par ce grand monsieur  , qui nous autorise à utilisersesimages,mêmepourdesprojetsprofessionnels,ungrandmerciàlui.

 

Figure 8.6.–Nousallonsutilisercetteimagepourl’exemple

Cette image ne paye pas de mine, mais elle pourra être étendue jusqu’à former une image immensesanspourautantêtretoutepixellisée.L’astuceconsisteàindiquerquellespartiesde l’image peuvent être étendues, et le SDK d’Android contient un outil pour vous aider dans votre démarche. Par rapport à l’endroit où vous avez installé le SDK, il se trouve dans \An droid\tools\.Vouspouvezdirectementglisser l’image dansl’application pourl’ouvriroubienallerdansFile > Open 9-patch(voirfiguresuivante).

 

Figure 8.7.–LelogicielDraw9-patch

Celogicielcontienttroiszonesdifférentes:

— Lazonedegauchereprésentel’imageetc’estdanscettezonequevouspouvezdessiner. Si, si, essayez de dessiner un gros cœur au milieu de l’image. Je vous ai eus! Vous ne pouvezenfaitdessinerquesurlapartielaplusextérieuredel’image,labordurequifait unpixeldelargeuretquientourel’image.

— Celle de droite est un aperçu de l’image élargie de plusieurs façons. Vous pouvez voir qu’actuellementlesimagesagrandiessontgrossières,lescoinsdéformésetdegrospixels sontvisibles.

— Etenbasontrouveplusieursoutilspourvousaiderdansvotretâche.

Sivouspassezvotrecurseuràl’intérieurdel’image,unfiltrerouges’interposeradefaçonàvous indiquerquevousnedevezpasdessineràcetendroit(maisvouspouvezdésactivercefiltreavec l’optionShow lock).Eneffet,l’espècedequadrillageàcôtédevotreimageindiqueleszones detransparence,cellesquinecontiennentpasdedessin.Votrerôleserad’indiquerquelsbords del’imagesontextensiblesetdansquellezonedel’objetonpourrainsé indiquerlesbordsextensiblesonvatraceruntraitd’unelargeurd’unpixelsurlesbordshautet gauchedel’image,alorsquedestraitssurlesbordsbasetdroitedéterminentoùpeutseplacer lecontenu.Parexemplepourcetteimage,onpourraitavoir(iln’yapasqu’unefaçondefaire, faitesenfonctiondecequevoussouhaitezobtenir)lerésultatvisibleàlafiguresuivante.

 

Figure 8.8.–Indiquezleszonesextensiblesainsiquel’emplacementducontenu

Vousvoyezladifférence?Lesimagesétiréesmontrentbeaucoupmoinsdepixelsetlestransitions entre les couleurs sont bien plus esthétiques! Enfin pour ajouter cette image à votre projet, il vous suffit de l’enregistrer au format , puis de l’ajouter à votre projet comme un drawablestandard.

L’imagesuivantevousmontreplusclairementàquoicorrespondentlesbords:

 

Figure 8.9.–Àgauche,lazonequipeutêtreagrandie,àdroitelazonedanslaquelleonpeut

écrire

8.3.2.1. Les commandes

— LesliderZoomvouspermetdevousrapprocherouvouséloignerdel’imageoriginale.

— LesliderPatch scalevouspermetdevousrapprocherouvouséloignerdesagrandissements.

— Show patchesmontreleszonesquipeuventêtreétenduedanslazonededessin.

— Show contentvousmontrelazoneoùvouspourrezinsérerducontenu(imageoutexte) dansAndroid.

— Enfin,vousvoyezunboutonenhautdelazonededessin,Show bad patches,quiune fois coché vous montre les zones qui pourraient provoquer des désagréments une fois l’imageagrandie;l’objectifseradoncd’enavoirlemoinspossible(voireaucune).

8.4. Les styles

Souventquandonfaituneapplication,onadopteuncertainpartiprisencequiconcernela chartegraphique.Parexemple,destonsplutôtclairsavecdesboutonsblancsquifontunetaille de 20 pixels et dont la police du texte serait en cyan. Et pour dire qu’on veut que tous les boutonssoientblancs,avecunetaillede20pixelsetletexteencyan,ilvafalloirindiquerpour chaqueboutonqu’onveutqu’ilsoitblanc,avecunetaillede20pixelsetletexteencyan,cequi esttrèsviteunproblèmesionabeaucoupdeboutons!

Afind’éviterd’avoiràserépéterautant,ilestpossiblededéfinircequ’onappelleunstyle.Un styleestunensembledecritèresesthétiquesdontl’objectifestdepouvoirdéfinirplusieursrègles àdifférentsélémentsgraphiquesdistincts.Ainsi,ilestplusévidentdecréerunstyle«Boutons persos»,quiprécisequelacibleest«blanche,avecunetaillede20pixelsetletexteencyan »etd’indiqueràtouslesboutonsqu’onveutqu’ilssoientdes«Boutonspersos».Etsivous voulez mettre tous vos boutons en jaune, il suffit simplement de changer l’attribut blanc du style«Boutonpersos»enjaune. i

Les styles sont des values, on doit donc les définir au même endroit que les chaînes de caractères.

Voicilaformestandardd’unstyle:

1         <resources>

2         <style name="nom_du_style" parent="nom_du_parent">

3         <item name="propriete_1">valeur_de_la_propriete_1</item>

4         <item name="propriete_2">valeur_de_la_propriete_2</item>

5         <item name="propriete_3">valeur_de_la_propriete_3</item>

6         …

7         <item name="propriete_n">valeur_de_la_propriete_n</item> 8 </style>

 

Voicilesrèglesàrespecter:

— Comme d’habitude, on va définir un nom unique pour le style, puisqu’il y aura une variablepouryaccéder.

an

droid:text

Co

lor

— Ilestpossibled’ajouterdespropriétésphysiquesàl’aided’<item>.Lenomdel’<item> correspondàundesattributsdestinésauxVues,qu’onadéjàétudiés.Parexemplepour changerlacouleurd’untexte,onvautiliserl’attribut.

— Enfin,onpeutfairehériternotrestyled’unautrestyle—qu’ilaitétédéfiniparAndroid ouparvous-mêmes—etainsirécupérerouécraserlesattributsd’unparent. Lestylesuivantpermetdemettredutexteencyan:

 

Lesdeuxstylessuivantshéritentdustyleprécédentenrajoutantd’autresattributs:

1       <style name="texte_cyan_grand" parent="texte_cyan">

2       <!-- On récupère la couleur du texte définie par le parent -->

3       <item name="android:textSize">20sp</item> 4 </style>

1       <style name="texte_rouge_grand" parent="texte_cyan_grand">

2       <!-- On écrase la couleur du texte définie par le parent, mais on garde la taille -->

3       <item name="android:textColor">#FF0000</item> 4 </style>

!

Ilestpossibleden’avoirqu’unseulparentpourunstyle,cequipeutêtretrèsvitepénible, alorsorganisez-vousàl’avance!

Il est ensuite possible d’attribuer un style à une vue en XML avec l’attribut style="iden

ti

fiant_du_style"

.Cependant,unstylenes’appliquepasdemanièredynamiqueenJava,

il faut alors préciser le style à utiliser dans le constructeur. Regardez [le constructeur d’une vue](#View(android.content.Context

pu

blic

View

(Context

contexte,

At

tri

bu

te

Set

at

trs)

at

trs

,.AttributeSet)):.Le paramètreest facultatif, et c’est lui qui permet d’attribuer un style à une vue. Par exemple:

1 Button bouton = new Button (this, R.style.texte_rouge_grand);

8.5. Les animations

Pourdonnerunpeudedynamismeànotreinterfacegraphique,onpeutfaireensortedebouger, fairetourner,agrandiroufairedisparaîtreunevueouunensembledevues.Maisaupréalable sachez qu’il est possible de placer un système de coordonnées sur notre écran de manière à pouvoir y situer les éléments. Comme à la figure suivante, l’axe qui va de gauche à droite s’appellel’axeXetl’axequivadehautenbass’appellel’axeY.

 

Figure 8.10.–L’axehorizontalestX,l’axeverticalestY

Voiciquelquesinformationsutiles:

— Surl’axeX,plusonsedéplaceversladroite,plusons’éloignede0.

— Surl’axeY,plusonsedéplaceverslebas,plusons’éloignede0.

— Pourexprimerunecoordonnée,onutiliselanotation(X,Y).

— L’unitéestlepixel.

— Lepointenhautàgaucheapourcoordonnées(0,0).

— Lepointenbasàdroiteapourcoordonnées(largeurdel’écran,hauteurdel’écran).

8.5.1. Définition en XML

Contrairementauxchaînesdecaractèresetauxstyles,lesanimationsnesontpasdesdonnées maisdesressourcesindépendantes,commel’étaientlesdrawables.Ellesdoiventêtredéfinies danslerépertoireres/anim/.

8.5.1.1. Pour un widget

Il existe quatre animations de base qu’il est possible d’effectuer sur une vue (que ce soit un widgetouunlayout!).Uneanimationestdécriteparunétatdedépartpourunevueetunétat

d’arrivée:parexempleonpartd’unevuevisiblepourqu’elledevienneinvisible.

8.5.1.2. Transparence

<al

pha>

permetdefaireapparaîtreoudisparaîtreunevue.

an

droid:fro

mAl

pha

—est la transparence de départ avec 0.0 pour une vue totalement transparenteet1.0pourunevuetotalementvisible.

an

droid:toAl

pha

—estlatransparencefinalevoulueavec0.0pourunevuetotalement transparenteet1.0pourunevuetotalementvisible.

8.5.1.3. Rotation

<ro

tate>

permetdefairetournerunevueautourd’unaxe.

an

droid:from

De

grees

—estl’anglededépart.

an

droid:pi

votX

—estlacoordonnéeducentrederotationsurl’axeX(enpourcentages parrapportàlagauchedelavue,parexemple50%correspondaumilieudelavueet 100%auborddroit).

an

droid:pi

votY

—estlacoordonnéeducentrederotationsurl’axeY(enpourcentages parrapportauplafonddelavue).

an

droid:to

De

grees

—estl’anglevouluàlafin.

8.5.1.4. Taille

<scale>permetd’agrandirouderéduireunevue.

an

droid:fromXS

cale

an

droid:fro

mYS

cale

       

—estlataillededépartsurl’axeX(1.0pourlavaleuractuelle).

—estlataillededépartsurl’axeY(1.0pourlavaleuractuelle).

<ro

tate>

<ro

tate>

an

droid:pi

votX

an

droid:pi

votY

—(identiqueà).

—(identiqueà).

an

droid:toXS

cale

an

droid:toYS

cale

—estlataillevouluesurl’axeX(1.0pourlavaleurdedépart).

—estlataillevouluesurl’axeY(1.0pourlavaleurdedépart).

8.5.1.5. Mouvement

<trans

late>

permetdefairesubirunetranslationàunevue(mouvementrectiligne).

an

droid:fromX

Delta

an

droid:fro

mY

Delta

       

—estlepointdedépartsurl’axeX(enpourcentages).

—estlepointdedépartsurl’axeY(enpourcentages).

an

droid:toX

Delta

an

droid:toY

Delta

—estlepointd’arrivéesurl’axeX(enpourcentages).

—estlepointd’arrivéesurl’axeY(enpourcentages).

Sachezqu’ilestenpluspossiblederegrouperlesanimationsenunensembleetdedéfinirun horairededéœudquireprésentecetensembleestdetype<set>. Touslesattributsquisontpassésàcenœudserépercuterontsurlesanimationsqu’ilcontient. Parexemple:

1        <?xml version="1.0" encoding="utf-8"?>

2        <set xmlns:android=";>

3        <scale

4        android:fromXScale="1.0"

5        android:fromYScale="1.0"

6        android:toXScale="2.0"

7        android:toYScale="0.5"

8        android:pivotX="50%"

9        android:pivotY="50%" />

10       <alpha

11       android:fromAlpha="1.0"

12       android:toAlpha="0.0" /> 13 </set>

i android:pivotX="50%" et android:pivotY="50%" permettent de placer le centre d’applicationdel’animationaumilieudelavue.

al

pha

al

pha

al

pha

an

droid:du

ra

tion

al

pha

Danscecode,lescaleetl’seferontenmêmetemps;cependantnotreobjectifvaêtre d’effectuerd’abordlescale,etseulementaprèsl’.Pourcela,onvadireauscalequ’il démarreraexactementaulancementdel’animation,qu’ildurera0,3secondeetondiraàl’ de démarrer à partir de 0,3 seconde, juste après le scale. Pour qu’une animation débute immédiatement,ilnefautrienfaire,c’estlapropriétépardéfaut.Enrevanchepourqu’elledure 0,3seconde,ilfaututiliserl’attributquiprendcommevaleurladuréeen millisecondes (ça veut dire qu’il vous faut multiplier le temps en secondes par 1000). Enfin, pourdéfiniràquelmomentl’débute,c’est-à-direavecquelretard,onutilisel’attribut

an

droid:star

tOff

set

(toujoursenmillisecondes).Parexemple,pourquelescaledémarre

al

pha

immédiatement,dure0,3secondeetsoitsuiviparunquidure2secondes,voicicequ’on écrira:

1        <?xml version="1.0" encoding="utf-8"?>

2        <set xmlns:android=";>

3        <scale

4        android:fromXScale="1.0"

5        android:fromYScale="1.0"

6        android:toXScale="2.0"

7        android:toYScale="0.5"

8        android:pivotX="50%"

9        android:pivotY="50%"

10       android:duration="300"/>

11       <alpha

 

an

droid:fillAf

ter="true"

 

an

droid:fillE

na

bled="true"

Un dernier détail. Une animation permet de donner du dynamisme à une vue, mais elle n’effectuera pas de changements réels sur l’animation : l’animation effectuera l’action, mais uniquementsurleplanvisuel.Ainsi,sivousessayezcecode,Androidafficheraunmouvement, maisunefoisl’animationfinie,lesvuesredeviendrontexactementcommeellesétaientavantle débutdel’animation.Heureusement,ilestpossiblededemanderàvotreanimationdechanger lesvuespourqu’ellescorrespondentàleurétatfinalàlafindel’animation.Ilsuffitderajouter lesdeuxattributs et .

Ani

ma

tio

nU

tils

Enfin je ne vais pas abuser de votre patience, je comprendrais que vous ayez envie d’essayer votrenouveaujoujou.Pourcefaire,c’esttrèssimple,utilisezlaclasse.

1    // On crée un utilitaire de configuration pour cette animation

2    Animation animation =

AnimationUtils.loadAnimation(contexte_dans_lequel_se_situe_la_vue,

identifiant_de_l_animation);

3    // On l'affecte au widget désiré, et on démarre l'animation 4 le_widget.startAnimation(animation);

8.5.1.6. Pour un layout

Sivouseffectuezl’animationsurunlayout,alorsvousaurezunepetitemanipulationà fait,onpeuttrèsbienappliqueruneanimationnormaleàunlayoutaveclaméthodequenous venonsdevoir,maisilsetrouvequ’onvoudraparfoisfaireensortequel’animationsepropage parmilesenfantsdulayoutpourdonnerunjolieffet.

<layou

tA

ni

ma

tion>

Toutd’abord,ilvousfautcréerunnouveaufichierXML,toujoursdanslerépertoireres/anim, mais la racine de celui-ci sera un nœud de type(attention au « l »

an

droid:ani

ma

minuscule!). Ce nœud peut prendre trois attributs. Le plus important est

tionpuisqu’ilfautymettrel’identifiantdel’animationqu’onveutpasseraulayout.Onpeut ensuite définir le délai de propagation de l’animation entre les enfants à l’aide de l’attribut

an

droid:de

lay

.Lemieuxestd’utiliserunpourcentage,parexemple100%pourattendreque

an

droid:ani

ma

tio

nOr

der

nor

mal

 

re

verse

ran

dom

l’animation soit finie ou 0% pour ne pas attendre. Enfin, on peut définir l’ordre dans lequel l’animations’effectueraparmilesenfantsavec,quipeutprendre lesvaleurs:           pourl’ordredanslequellesvuesontétéajoutéesaulayout,         pour l’ordreinverseetpourunedistributionaléatoireentrelesenfants.

Onobtientalors:

1       <?xml version="1.0" encoding="utf-8"?>

2       <layoutAnimation xmlns:android=";

3       android:delay="10%"

4       android:animationOrder="random"

5       android:animation="@anim/animation_standard"

6       />

Puisonpeutl’utiliserdanslecodeJavaavec:

1   LayoutAnimationController animation =

AnimationUtils.loadLayoutAnimation(contexte_dans_lequel_se_situe_la_vue,

identifiant_de_l_animation);

2   layout.setLayoutAnimation(animation); i

On aurait aussi pu passer l’animation directement au layout en XML avec l’attribut android:layoutAnimation="identifiant_de_l_animation".

8.5.2. Un dernier raffinement : l’interpolation

Nosanimationssontsuper,maisilmanqueunpetitquelquechosequipourraitlesrendreencore plusimpressionnantes.Sivoustestezlesanimations,vousverrezqu’ellessontconstantes,elles nemontrentpasd’effetsd’accélérationoudedécélérationparexemple.Onvautilisercequ’on appelleun agent d’interpolation,c’est-à-direunefonctionmathématiquequivacalculerdans quelétatdoitsetrouvernotreanimationàunmomentdonnépoursimuleruneffetparticulier.

Regardezlafiguresuivante:enrouge,sansinterpolation,lavitessedevotreanimationreste identiquependanttouteladuréedel’animation.Enbleu,avecinterpolation,votreanimation démarrera très lentement et accélérera avec le temps. Heureusement, vous n’avez pas besoin d’êtrebonsenmathspourutiliserlesinterpolateurs.

 

Figure 8.11.–Lavitessedel’animations’accélèreavecletemps

an

droid:in

ter

po

la

tor

Vouspouvezrajouteruninterpolateuràl’aidedel’attribut,puisvous pouvezpréciserqueltyped’effetvoussouhaitezobteniràl’aided’unedesvaleurssuivantes:

@an

droid:anim/ac

ce

le

rate_de

ce

le

rate_in

ter

po

la

tor

—: la vitesse est identique audébutetàlafindel’animation,maisaccélèreaumilieu.

@an

droid:anim/ac

ce

le

rate_in

ter

po

la

tor

—:pouruneanimationlenteaudébutet plusrapideparlasuite.

@an

droid:anim/an

ti

ci

pate_in

ter

po

la

tor

—:pourquel’animationcommenceàl’envers,puisreviennedanslebonsens.

@an

droid:anim/an

ti

ci

pate_over

shoot_in

ter

po

la

tor

—:pourquel’animationcommenceàl’envers,puisreviennedanslebonsens,dépasselavaleurfinalepuisfassemarche arrièrepourl’atteindre.

@an

droid:anim/bounce_in

ter

po

la

tor

—:pouruneffetderebondtrèssympathique.

@an

droid:anim/de

ce

le

rate_in

ter

po

la

tor

—:pourquel’animationdémarrebrutalementetseterminelentement.

@an

droid:anim/over

shoot_in

ter

po

la

tor

—:pouruneanimationquidémarrenormalement,dépasselavaleurfinale,puisfassemarchearrièrepourl’atteindre.

Enfin,sionplaceuninterpolateurdansun<set>,ilestprobablequ’onveuillelepartagerà

an

droid:sha

reIn

ter

po

la

tor="true"

touslesenfantsdece<set>.Pourpropageruneinterpolationàtouslesenfantsd’unensemble, ilfaututiliserl’attribut.

En ce qui concerne les répétitions, il existe aussi un interpolateur, mais il y a plus pratique.

an

droid:re

peat

Count

 

an

droid:re

peat

Mode

Préférezplutôtlacombinaisondesattributs                                                   et                                        .

res

tart

 

re

verse

Le premier définit le nombre de répétitions de l’animation qu’on veut effectuer (-1 pour un nombreinfini,0pouraucunerépétition,etn’importequelautrenombreentierpositifpourfixer unnombreprécisderépétitions),tandisqueleseconds’occupedelafaçondontlesrépétitions s’effectuent.Onpeutluiaffecterlavaleur (répétitionnormale)oualors (àla findel’animation,oneffectuelamêmeanimationmaisàl’envers).

8.5.3. L’évènementiel dans les animations

Ilyatroisévènementsquipeuventêtregérésdanslecode:lelancementdel’animation,lafin del’animation,etchaquedébutd’unerépétition.C’estaussisimpleque:

1         animation.setAnimationListener(new AnimationListener() {

2         public void onAnimationEnd(Animation _animation) {

3         // Que faire quand l'animation se termine ? (n'est pas lancé à la fin d'une répétition)

4         }

5

6       public void onAnimationRepeat(Animation _animation) { 7          // Que faire quand l'animation se répète ?

       8          }

9

10        public void onAnimationStart(Animation _animation) { 11            // Que faire au premier lancement de l'animation ?

12       }

13       });

re

sources

R.type_de_res

source.nom_de_la_res

source

— Chaque type de ressources aura comme racine un élementqui contiendra d’autresélémentshiérarchisantlesressources.Ellespeuventêtreaccessiblessoitparla partieJavasoitpard’autresfichiers

@type_de_res

source/nom_de_la_res

source

XML.

— Leschaînesdecaractèressontdéclaréespardesélémentsstring.

— Androidsupporte3typesd’images:PNG,JPEGetGIF,dansl’ordreduplusconseillé aumoinsconseillé.

— 9-Patchestunetechnologiepermettantderendredesimagesextensiblesengardantun rendunet.

— Lesstylespermettentdedéfinirouredéfinirdespropriétésvisuellesexistantespourles utilisersurplusieursvuesdifférentes.Ilssedéclarentparunélémentstyleetcontiennent unelisted’item.

— Lesanimationssedéfinissentparunensembled’éléments:

<al

pha>

—pourlatransparenced’unevue.

<ro

tate>

—pourlarotationd’unevueautourd’unaxe.

— <scale>pourlamodificationdel’échelled’unevue.

<trans

late>

—pourledéplacementd’unevue.

Layou

tA

ni

ma

tion

— L’animationsurunlayoutsefaitgrâceàladéclarationd’unélément.

— Uneinterpolationpeutêtreappliquéeàuneanimationpourmodifierlesvariationsde vitessedel’animation.


9.   TP : un bloc-notes

NotrepremierTP!Nousavionsbiensûrdéjàfaitunpetitprogrammeaveclecalculateurd’IMC, mais cette fois nous allons réfléchir à tous les détails pour faire une application qui plaira à d’éventuelsutilisateurs:unbloc-notes.

Enthéorie,vousverrezàpeuprèstoutcequiaétéabordéjusquelà,doncs’ilvousmanqueune information,pasdepanique,onrespireunboncoupetonregardedansleschapitresprécédents, enquêted’informations.JevousdonneraiévidemmentlasolutionàceTP,maisceserabien plusmotivantpourvoussivousréussissezseuls.Unedernièrechose:iln’existepasunesolution maisdes solutions.Sivousparvenezàréalisercetteapplicationenn’ayantpaslemêmecode quemoi,cen’estpasgrave,l’importantc’estquecelafonctionne.

9.1. Objectif

L’objectificivaêtrederéaliserunprogrammequimettraenformecequevousé ne sera pas très poussé : mise en gras, en italique, souligné, changement de couleur du texte etquelquessmileys.Ilyauraunevisualisationdelamiseenformeentempsréel.Leseulhic c’estque…vousnepourrezpasenregistrerletexte,étantdonnéquenousn’avonspasencorevu commentfaire.

Ici,onvasurtoutseconcentrersurl’aspectvisuelduTP.C’estpourquoinousallonsessayer d’utiliserleplusdewidgetsetdelayoutspossible.Maisenplus,onvaexploiterdesressources pournoussimplifierlaviesurlelongterme.Lafiguresuivantevousmontrecequej’ n’estpastrèsjoli,maisçafonctionne.

 

Figure 9.1.–Voiciàquoivaressemblerl’application

Vouspouvezvoirquel’écransediviseendeuxzones:

— Celleenhautaveclesboutonsconstitueralemenu;

Edit

Text

 

Text

View

              — Celledubasavecl’                       etles                   .

9.1.1. Le menu

Chaque bouton permet d’effectuer une des commandes de base d’un éditeur de texte. Par exemple,lebouton Gras metuneportiondutexteengras,appuyersurn’importelequeldes smileyspermetd’insérercetteimagedansletexteetlestroiscouleurspermettentdechoisirla couleurdel’ensemble dutexte(enfinvouspouvezlefairepouruneportiondutextesivousle désirez,c’estjustepluscompliqué).

Cemenuestmouvant.Enappuyantsurlebouton Cacher ,lemenuserétracteverslehautjusqu’à disparaî,letextesurleboutondevient«Afficher»etcliquerdessusfaitredescendrele menu(voirfiguresuivante).

 

Figure 9.2.–Lebouton«Afficher»

9.1.2. L’éditeur

Jevousenparlaisprécédemment,nousallonsmettreenplaceunezonedeprévisualisationqui permettradevoirletextemisenformeentempsréel,commesurl’imagesuivante.

 

Figure 9.3.–Letexteestmisenformeentempstéeldanslazonedeprévisualisation

9.2. Spécifications techniques

9.2.1. Fichiers à utiliser

Onvad’abordutiliserlessmileysduSiteduZéro:.

Pourlesboutons,j’aiutiliséles9-patchesvisiblesàlafiguresuivante.

 

9.2.2. Le HTML

9.2.2.1. Les balises

Text

View

Commevousavezpuleconstater,nostextesserontformatésàl’aidedulangagedebalisage HTML.Rappelez-vous,jevousavaisdéjàditqu’ilétaitpossibled’interpréterduHTMLdans un;cependant,onvaprocéderunpeudifféremmenticicommejevousl’indiquerai plustard.

Heureusement,vousn’avezpasàconnaîtreleHTML,justecertainesbalisesdebasequevoici:

Effet désiré

Balise

Écrire en gras

 
 

<b>Le

texte</b>

 

Écrireenitalique

 
 

<i>Le

texte</i>

 

Soulignerdutexte

 
 

<u>Le

texte</u>

 

Inséreruneimage

 
 

<img

src="Nom

de

l'image">

 

Changerlacouleurdelapolice

 
 

<font

 

co

lor="Code

 

cou

leur">Le

 

texte</font>

 
                                 

9.2.2.2. L’évènementiel

Text

View

 

Edit

Text

Edit

Text

Text

View

Lis

te

ner

Text

Wat

cher

Ensuite,onaditqu’ilfallaitquele interprèteentempsréellecontenudel’ . Pourcela,ilsuffitdefaireensortequechaquemodificationdel’provoqueaussiune modification du: c’est ce qu’on appelle un évènement. Comme nous l’avons déjà vu,pourgérerlesévènements,nousallonsutiliserun.Danscecasprécis,ceseraun objetdetypequiferal’affaire.Onpeutl’utiliserdecettemanière:

1         editText.addTextChangedListener(new TextWatcher() {

2         @Override

3         /**

4         * s est la chaîne de caractères qui est en train de changer

5         */

6         public void onTextChanged(CharSequence s, int start, int before, int count) {

7         // Que faire au moment où le texte change ?

8         }

9

10       @Override

11       /**

12       * @param s La chaîne qui a été modifiée

13       * @param count Le nombre de caractères concernés

14       * @param start L'endroit où commence la modification dans la

chaîne

15       * @param after La nouvelle taille du texte

16       */

17       public void beforeTextChanged(CharSequence s, int start, int count, int after) {

18       // Que faire juste avant que le changement de texte soit pris en compte ?

19       }

20

21       @Override

22       /**

23       * @param s L'endroit où le changement a été effectué

24       */

25       public void afterTextChanged(Editable s) {

26       // Que faire juste après que le changement de texte a été pris en compte ?

27       }

28       });

Text

View

 

Edit

Text

De plus, il nous faut penser à autre chose. L’utilisateur va vouloir appuyer sur Entrée pour reveniràlalignequandilseradansl’éditeur.Leproblèmeestqu’enHTMLilfautpréciseravec unebalisequ’onveutfaireunretouràlaligne!S’ilappuiesur Entrée ,aucunretouràlaligne neseraprisencomptedansle ,alorsquedansl’,si.C’estpourquoiilva falloirfaireattentionauxtouchesquepressel’utilisateuretréagirenfonctiondutypedetouche.

Lis

te

ner

On

Key

Lis

te

ner

Cettedétectionestencoreunévènement,ils’agitdoncencored’unrôlepourun: cettefois,le.Ilseprésenteainsi:

1         editText.setOnKeyListener(new View.OnKeyListener() {

2         /**

3         * Que faire quand on appuie sur une touche ?

4         * @param v La vue sur laquelle s'est effectué l'évènement

5         * @param keyCode Le code qui correspond à la touche

6         * @param event L'évènement en lui-même

7         */

8         public boolean onKey(View v, int keyCode, KeyEvent event) {

9         // …

10        }

11        });

<br

/>

Lecodepourlatouche Entrée est66.LecodeHTMLduretouràlaligneest.

9.2.2.3. Les images

ge

Get

ter

pu

blic

Dra

Pour pouvoir récupérer les images en HTML, il va falloir préciser à Android comment les récupérer.Onutilisepourcelal’interface.Onvadoncfaireimplémenter cetteinterfaceàuneclasseetdevoirimplémenterlaseuleméthodeàimplémenter:

wable

get

Dra

wable

(String

source)

.Àchaquefoisquel’interpréteurHTMLrencontrera

<img

src="source">

get

Dra

wable

get

Dra

wable

unebalisepourafficheruneimagedecestyle,alorsl’interpréteurdonnera àlafonctionlasourcepréciséedansl’attributsrc,puisl’interpréteuraffichera l’imagequerenvoie.Onaparexemple:

1         public class Exemple implements ImageGetter {

2         @Override

3         public Drawable getDrawable(String smiley) {

4         Drawable retour = null;

5

       6                                  Resources resources = context.getResources();

7

8       retour = resources.getDrawable(R.drawable.ic_launcher); 9

10       // On délimite l'image (elle va de son coin en haut à gauche à son coin en bas à droite)

11       retour.setBounds(0, 0, retour.getIntrinsicWidth(), retour.getIntrinsicHeight());

12       return retour;

13       }

14       }

pu

blic

Span

ned

Html.fromHtml(String

Enfin,pourinterpréterlecodeHTML,utilisezlafonction

source,

ge

Get

ter

ima

ge

Get

ter,

null)

(nous n’utiliserons pas le dernier para-

Span

ned

 

Text

View

mètre).L’objet                           retournéestceluiquidoitêtreinsérédansle                        .

9.2.2.4. Les codes pour chaque couleur

<font

co

lor="cou

leur">

La balisea besoin qu’on lui précise un code pour savoir quelle couleurafficher.Vousdevezsavoirque:

— Lecodepourlenoirest#000000.

— Lecodepourlebleuest#0000FF.

— Lecodepourlerougeest#FF0000.

9.2.3. L’animation

Trans

la

Onsouhaitefaireensortequelemenuserétracteetressorteàvolonté.Leproblème,c’estqu’on abesoindelahauteurdumenupourpouvoirfairecetteanimation,etcettemesuren’estbiensûr pasdisponibleenXML.Onvadoncdevoirfaireuneanimationdemanièreprogrammatique. Commeonchercheuniquementàdéplacerlinéairementlemenu,onutiliseralaclasse

teA

ni

ma

tion

 

pu

blic

Trans

la

teA

ni

ma

tion

(float

fromX

,enparticuliersonconstructeur

Delta,

float

toX

Delta,

float

fro

mY

Delta,

float

toY

Delta)

.Chacundecesparamètres

permetdedéfinirsurlesdeuxaxes(XetY)d’oùpartl’animation(from)etjusqu’oùelleva (to).Dansnotrecas,onaurabesoindedeuxanimations:unepourfaireremonterlemenu,une autrepourlefairedescendre.

Pourfaireremonterlemenu,onvapartirdesapositiondedépart(doncfromXDelta=0et fromYDelta=0,c’est-à-direqu’onnebougepaslemenusuraucundesdeuxaxesaudébut)et on va le déplacer sur l’axe Y jusqu’à ce qu’il sorte de l’écran (donc toXDelta=0 puisqu’on ne bouge pas et toYDelta=-tailleDuMenu puisque, rappelez-vous, l’axe Y part du haut pour aller vers le bas). Une fois l’animation terminée, on dissimule le menu avec la méthode

set

Vi

si

bi

lity()

.

Avecunraisonnementsimilaire,onvad’abordremettrelavisibilitéàunevaleurnormale(set

Vi

si

bi

lity(

sible)

)etondéplaceralavuedesonemplacementhorscadrejusqu’à

fromX

Delta

=0

 

fro

mY

Delta

=-

taille

Du

Menu

 

toX

Delta

sonemplacementnormal(donc                                    ,                                                        ,

=0ettoYDelta=0).

pu

blic

void

set

Du

ra

tion

(long

du

Il est possible d’ajuster la vitesse avec la fonction

ra

tion

Mil

lis)

 

pu

blic

void

. Pour rajouter un interpolateur, on peut utiliser la fonction

se

tIn

ter

po

la

tor

(In

ter

po

la

tor

i)

 

Ac

ce

le

ra

teIn

ter

po

la

; j’ai par exemple utilisé un

tor.

Enfin, je vous conseille de créer un layout personnalisé pour des raisons pratiques. Je vous laisseimaginerunpeucommentvousdébrouiller;cependant,sachezquepourutiliserunevue personnaliséedansunfichierXML,ilvousfautpréciserlepackagedanslequelellesetrouve, suividunomdelaclasse.Parexemple:

 

9.2.4. Liens

Plusd’informations:

Edit

Text

ge

Get

ter

               — et                                          

Text

View

Text

Wat

cher

Trans

la

teA

ni

ma

tion

          —                                           

9.3. Déboguer des applications Android

Sys

.println

Sys

.println

Quand on veut déboguer en Java, sans passer par le débogueur, on utilise souvent Sys .println afin d’afficher des valeurs et des messages dans la console. Cependant, onestbienembêtéavecAndroid,puisqu’iln’estpaspossibledefairede. Eneffet,sivousfaitesun,vousenvoyezunmessagedanslaconsoledu terminalsurlequels’exécuteleprogramme,c’est-à-direlaconsoledutéléphone,delatablette oudel’émulateur!Etvousn’yavezpasaccèsavecEclipse.Alors,qu’est-cequiexistepourla remplacer?

Win

dow > Show View > Log

cat

Laissez-moivousprésenterle Logcat.C’estunoutildel’ADT,unesortedejournalquipermet deliredesentrées,maissurtoutd’enécrire.Voyonsd’abordcommentl’ouvrir.DansEclipse, allezdans.Normalement,ils’afficheraenbasdelafenêtre, danslapartievisibleàlafiguresuivante.

 

Figure 9.4.–LeLogcastestouvert

Lapremièrechoseàfaire,c’estdecliquersurletroisièmeboutonenhautàdroite(voirfigure suivante).

 

Figure 9.5.–Cliquezsurletroisièmebouton Félicitations,vousvenezdevousdébarrasserd’unnombreincalculabledebugslaissésdansle Logcat!Encequiconcernelesautresboutons,celuidegauchepermetd’enregistrerlejournal dansunfichierexterne,ledeuxième,d’effacertouteslesentréesactuellesdujournalafind’obtenir unjournalvierge,etledernierboutonpermetdemettreenpausepourneplusvoirlejournal défilersanscesse.

PourajouterdesentréesmanuellementdansleLogcat,vousdeveztoutd’abordimporteran .Logdansvotrecode.Vouspouvezensuiteécriredesmessagesàl’aidedeplusieurs méthodes.Chaquemessageestaccompagnéd’uneétiquette,quipermetdeleretrouverfacilement dansleLogcat.

Log.v("Éti

quette",

"Mes

sage

à à à

en

voyer")

Log.d("Éti

quette",

"Mes

sage

en

voyer")

Log.i("Éti

quette",

"Mes

sage

en

voyer")

—pourvosmessagescommuns.

—pourvosmessagesdedebug.

—pourvosmessagesàcaractèreinformatif.

Log.w("Éti

quette",

"Mes

sage

à à

en

voyer")

Log.e("Éti

quette",

"Mes

sage

en

voyer")

—pourvosavertissements. —pourvoserreurs.

VouspouvezensuitefiltrerlesmessagesquevoussouhaitezafficherdansleLogcatàl’aidedela listedéroulantevisibleàlafiguresuivante.

 

Figure 9.6.–Cette liste déroulante permet d’afficher dans le Logcat les messages que vous souhaitez

Ver

bose

De

bug

Vousvoyez,lapremièrelettreutiliséedanslecodeindiqueuntypedemessage:vpour, dpour,etc.

i

Sachezaussique,sivotreprogrammelanceuneexceptionnoncatchée,c’estdansleLogcat quevousverrezcequ’onappellele«stack trace »,c’est-à-direlesdifférentsappelsàdes méthodesquiontamenéaulancementdel’exception.

Parexempleaveclecode:

 

Onobtientlafiguresuivante.

 

Figure 9.7.–Unelisted’erreurss’affiche

Àlafiguresuivante,onpeutvoirlemessagequej’avaisinséré.

 

Figure 9.8.–lemessagequej’avaisinsérés’affichebien

Avec,danslescolonnes(degaucheàdroite):

— Letypedemessage(DpourDebug);

— Ladateetl’heuredumessage;

— Lenumérouniquedel’applicationquialancélemessage;

— Lepackagedel’application; — L’étiquettedumessage; — Lecontenudumessage.

Onpeutaussivoiràlafiguresuivantequemonétourderieaprovoquéunplantagedel’application.

 

Figure 9.9.–L’applicationaplanté,ilsuffitderegarderlemessagepoursavoiroù

Null

Poin

te

rEx

cep

tion

Re

la

ti

ve

Layou

tAc

ti

vity

Ce message signifie qu’il y a eu une exception de type(provoquée quandonveututiliserunobjetquivautnull).Vouspouvezvoiràladeuxièmelignequecette erreur est intervenue dans ma classequi appartient au package

pi

tre

la

ti

ve

Layout

 

on

Create

                                                                                                  .L’erreurs’estproduitedanslaméthode                         ,à

laligne23demoncodepourêtreprécis.Enfin,pasbesoindefouiller,puisqu’undouble-clicsur l’unedeceslignespermetd’yaccéderdirectement.

9.4. Ma solution

9.4.1. Les ressources

9.4.1.1. Couleurs utilisées

va

lues

J’aidéfiniuneressourcedetypequicontienttoutesmescouleurs.Ellecontient:

1       <resources>

2       <color name="background">#99CCFF</color>

3       <color name="black">#000000</color>

4       <color name="translucide">#00000000</color>

5       </resources>

Lacouleurtranslucideestunpeudifférentedesautresquisontdesnombreshexadécimauxsur 8bits:elleestsur8+2bits.Enfait,lesdeuxbitssupplémentairesexprimentlatransparence. Jel’aimiseà00,commeçaellereprésentelesobjetstransparents.

9.4.1.2. Styles utilisés

Parce qu’ils sont bien pratiques, j’ai utilisé des styles, par exemple pour tous les textes qui doiventprendrelacouleurnoire:

1         <resources>

2         <style name="blueBackground">

3         <item name="android:background">@color/background</item>

4         </style>

5

6         <style name="blackText">

7         <item name="android:textColor">@color/black</item>

8         </style>

9

10       <style name="optionButton">

11       <item name="android:background">@drawable/option_button</item>

12       </style>

13

14       <style name="hideButton">

15       <item name="android:background">@drawable/hide_button</item> 16            </style>

 

trans

lu

cide

Riendetrèsétonnantencoreunefois.Notezbienquelestyleappelémepermettra demettreentransparencelefonddesboutonsquiaffichentdessmileys.

9.4.1.3. Les chaînes de caractères

Sanssurprise,j’utilisedesressourcespourcontenirmesstring:

1        <resources>

2        <string name="app_name">Notepad</string>

3        <string name="hide">Cacher</string>

4        <string name="show">Afficher</string>

5        <string name="bold">Gras</string>

6        <string name="italic">Italique</string>

7        <string name="underline">Souligné</string>

8        <string name="blue">Bleu</string>

9        <string name="red">Rouge</string>

10       <string name="black">Noir</string>

11       <string name="smileys">Smileys :</string>

12       <string name="divider">Séparateur</string>

13       <string name="edit">Édition :</string>

14       <string name="preview">Prévisualisation : </string>

15       <string name="smile">Smiley content</string>

16       <string name="clin">Smiley qui fait un clin d\oeil</string>

17       <string name="heureux">Smiley avec un gros sourire</string> 18 </resources>

9.4.1.4. Le Slider

Li

near

Layout

Sli

der

Sli

der

J’ai construit une classe qui dérive depour contenir toutes mes vues et qui s’appelle.Decettemanière,pourfaireglisserlemenu,jefaisglissertoutel’activitéet l’effetestplussaisissant.Monpossèdeplusieursattributs:

boo

lean

isO

pen

—,pourretenirl’étatdemonmenu(ouvertoufermé);

Re

la

ti

ve

Layout

to

Hide

—,quiestlemenuàdissimulerouàafficher;

fi

nal

sta

tic

int

SPEED

—,afindedéfinirlavitessedésiréepourmonanimation.

Finalement,cetteclassenepossèdequ’unegrosseméthode,quipermetd’ouvriroudefermerle menu:

1       /**

2       * Utilisée pour ouvrir ou fermer le menu.

3       * @return true si le menu est désormais ouvert.

4       */

5       public boolean toggle() {

6       //Animation de transition.

7       TranslateAnimation animation = null;

8

9        // On passe de ouvert à fermé (ou vice versa)

10       isOpen = !isOpen;

11

12       // Si le menu est déjà ouvert

13       if (isOpen)

14       {

15       // Animation de translation du bas vers le haut

16       animation = new TranslateAnimation(0.0f, 0.0f,

-toHide.getHeight(), 0.0f);

17       animation.setAnimationListener(openListener);

18       } else

19       {

20       // Sinon, animation de translation du haut vers le bas

21       animation = new TranslateAnimation(0.0f, 0.0f, 0.0f,

-toHide.getHeight());

22       animation.setAnimationListener(closeListener);

23       }

24

25       // On détermine la durée de l'animation

26       animation.setDuration(SPEED);

27       // On ajoute un effet d'accélération

28       animation.setInterpolator(new AccelerateInterpolator());

29       // Enfin, on lance l'animation

30       startAnimation(animation);

31

32       return isOpen;

33       }

9.4.1.5. Le layout

Toutd’abord,jerajouteunfondd’écranetunpaddingaulayoutpourdesraisonsesthétiques.

Sli

der

 

pi

tre

te

pad

pi

tre

te

der

Commemon   setrouvedanslepackage          ,jel’appelleavec lasyntaxe:

1 <sdz.chapitreDeux.notepad.Slider xmlns:android="; 2         android:id="@+id/slider"

3       android:layout_width="fill_parent"

4       android:layout_height="fill_parent"

5       android:orientation="vertical"

6       android:padding="5dip"

7       style="@style/blueBackground" >

8       <!-- Restant du code -->

9       </sdz.chapitreDeux.notepad.Slider>

Ensuite,commejevousl’aiditdanslechapitreconsacréauxlayouts,onvaéviterdecumulerles

Li

near

Layout

 

Re

la

ti

ve

Layout

                                            ,c’estpourquoij’aioptépourletrèspuissant                                         àlaplace:

1       <RelativeLayout

2       android:id="@+id/toHide"

3       android:layout_width="fill_parent"

4       android:layout_height="wrap_content"

5       android:layoutAnimation="@anim/main_appear"

6       android:paddingLeft="10dip"

7       android:paddingRight="10dip" >

8

9        <Button

10       android:id="@+id/bold"

11       style="@style/optionButton"

12       android:layout_width="wrap_content"

13       android:layout_height="wrap_content"

14       android:layout_alignParentLeft="true"

15       android:layout_alignParentTop="true"

16       android:text="@string/bold"

17       />

18

19       <TextView

20       android:id="@+id/smiley"

21       style="@style/blackText"

22       android:layout_width="wrap_content"

23       android:layout_height="wrap_content"

24       android:layout_alignParentLeft="true"

25       android:layout_below="@id/bold"

26       android:paddingTop="5dip"

27       android:text="@string/smileys"

28       />

29

30       <ImageButton

31       android:id="@+id/smile"

32       android:layout_width="wrap_content"

33       android:layout_height="wrap_content"

34       android:layout_below="@id/bold"

35       android:layout_toRightOf="@id/smiley"

36       android:contentDescription="@string/smile"

37       android:padding="5dip"

 

38

39

40

android:src="@drawable/smile" style="@style/translucide" />

41

42

<ImageButton

43

44

45

46

47

48

49

50

51

52

android:id="@+id/heureux" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@id/smile" android:layout_centerHorizontal="true" android:contentDescription="@string/heureux"

android:padding="5dip" android:src="@drawable/heureux" style="@style/translucide" />

53

54

<ImageButton

55

56

57

58

59

60

61

62

63

64

65

 

66

67

<Button

68

69

70

71

72

73

74

android:id="@+id/italic" style="@style/optionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true"

android:text="@string/italic"

75

/>

76

77

<Button

78

79

80

81

82

83

84

85

android:id="@+id/underline" style="@style/optionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:text="@string/underline" />

86

87

<RadioGroup

88       android:id="@+id/colors"

89       android:layout_width="wrap_content"

90       android:layout_height="wrap_content"

91       android:layout_alignParentLeft="true"

92       android:layout_alignParentRight="true"

93       android:layout_below="@id/heureux"

94       android:orientation="horizontal" >

95

96           <RadioButton

97           android:id="@+id/black"

98           style="@style/blackText"

99           android:layout_width="wrap_content"

100          android:layout_height="wrap_content"

101          android:checked="true"

102          android:text="@string/black"

103          />

104          <RadioButton

105          android:id="@+id/blue"

106          style="@style/blackText"

107          android:layout_width="wrap_content"

108          android:layout_height="wrap_content"

109          android:text="@string/blue"

110          />

111          <RadioButton

112          android:id="@+id/red"

113          style="@style/blackText"

114          android:layout_width="wrap_content"

115          android:layout_height="wrap_content"

116          android:text="@string/red"

117          />

118          </RadioGroup>

119          </RelativeLayout>

an

droid:layout_gra

vity="cen

ter_ho

ri

zon

Ontrouveensuiteleboutonpouractionnerl’animation.Onparledel’objetaucentredulayout parent (sur l’axe horizontal) avec l’attribut tal".

1       <Button

2       android:id="@+id/hideShow"

3       style="@style/hideButton"

4       android:layout_width="wrap_content"

5       android:layout_height="wrap_content"

6       android:paddingBottom="5dip"

7       android:layout_gravity="center_horizontal"

8       android:text="@string/hide" />

Ima

ge

View

J’aiensuiterajoutéunséparateurpourdesraisonsesthétiques.C’estunequiaffiche uneimagequiestprésentedanslesystèmeAndroid;faitesdemêmequandvousdésirezfaire unséparateurfacilement!

1       <ImageView

2       android:src="@android:drawable/divider_horizontal_textfield"

3       android:layout_width="fill_parent"

4       android:layout_height="wrap_content"

5       android:scaleType="fitXY" 6     android:paddingLeft="5dp"

7        android:paddingRight="5dp"

8        android:paddingBottom="2dp"

9        android:paddingTop="2dp"

10       android:contentDescription="@string/divider" />

Ta

ble

Layout

Lasecondepartiedel’écranestreprésentéeparun—plusparintérêtpédagogique qu’autrechose.Cependant,j’airencontréuncomportementétrange(maisquiestvoulu,d’après

Edit

Text

 

Ta

ble

Layout

an

droid:stret

ch

Co

lumns

Text

View

Google…).Sionveutquenotre prenneleplusdeplacepossibledansle , ondoitutiliser,commenousl’avonsdéjàvu.Cependant,avecce comportement, lene fera pas de retour à la ligne automatique, ce qui fait que le textedépasselecadredel’activité.Pourcontrercedésagrément,aulieud’étendrelacolonne,

an

droid:shrink

Co

lumns

on la rétrécit avecet on ajoute un élément invisible qui prend le plusdeplacepossibleenlargeur.Regardezvous-mêmes:

   

9.4.2. Le code

9.4.2.1. Le SmileyGetter

Oncommenceparlaclassequej’utilisepourrécupérermessmileysdansmesdrawables.Onlui donneleContextdel’applicationenattribut:

1       /**

2       * Récupère une image depuis les ressources

3       * pour les ajouter dans l'interpréteur HTML

4       */

5       public class SmileyGetter implements ImageGetter {

6       /* Context de notre activité */

7       protected Context context = null;

8

9        public SmileyGetter(Context c) {

10       context = c;

11       }

12

13       public void setContext(Context context) {

14       this.context = context;

15       }

16

17       @Override

18       /**

19       * Donne un smiley en fonction du paramètre d'entrée

20       * @param smiley Le nom du smiley à afficher

21       */

22       public Drawable getDrawable(String smiley) {

23       Drawable retour = null;

24

25       // On récupère le gestionnaire de ressources

26       Resources resources = context.getResources();

27

28         // Si on désire le clin d'œil…

29         if(smiley.compareTo("clin") == 0)

30         // … alors on récupère le drawable correspondant

31         retour = resources.getDrawable();

32         else if(smiley.compareTo("smile") == 0)

33         retour = resources.getDrawable(R.drawable.smile);

34         else

35         retour = resources.getDrawable(R.drawable.heureux);

36         // On délimite l'image (elle va de son coin en haut à gauche à son coin en bas à droite)

37         retour.setBounds(0, 0, retour.getIntrinsicWidth(), retour.getIntrinsicHeight());

38         return retour;

39         }

40         }

9.4.2.2. L’activité

Enfin,leprincipal,lecodedel’activité:

1       public class NotepadActivity extends Activity {

2       /* Récupération des éléments du GUI */

3       private Button hideShow = null;

4       private Slider slider = null;

5       private RelativeLayout toHide = null;

6       private EditText editer = null;

7       private TextView text = null;

8       private RadioGroup colorChooser = null; 9

10       private Button bold = null;

11       private Button italic = null;

12       private Button underline = null;

13

14       private ImageButton smile = null;

15       private ImageButton heureux = null;

16       private ImageButton clin = null;

17

18       /* Utilisé pour planter les smileys dans le texte */

19       private SmileyGetter getter = null;

20

21       /* Couleur actuelle du texte */

22       private String currentColor = "#000000";

23

24       @Override

25       public void onCreate(Bundle savedInstanceState) {

26       super.onCreate(savedInstanceState);

27       setContentView();

28

29                                  getter = new SmileyGetter(this);

30

31               // On récupère le bouton pour cacher/afficher le menu

32               hideShow = (Button) findViewById(R.id.hideShow);

33               // Puis on récupère la vue racine de l'application et on change sa couleur

34               hideShow.getRootView().setBackgroundColor(R.color.background);

35               // On rajoute un Listener sur le clic du bouton…

36               hideShow.setOnClickListener(new View.OnClickListener() {

37               @Override

38               public void onClick(View vue) {

39               // … pour afficher ou cacher le menu

40               if(slider.toggle())

41               {

42               // Si le Slider est ouvert…

43               // … on change le texte en "Cacher"

44               hideShow.setText();

45               }else

46               {

47               // Sinon on met "Afficher"

48               hideShow.setText();

 

49

}

50

}

51

});

52

53

// On récupère le menu

54

toHide = (RelativeLayout) findViewById(R.id.toHide);

55

// On récupère le layout principal

56

slider = (Slider) findViewById(R.id.slider);

57

// On donne le menu au layout principal

58

slider.setToHide(toHide);

59

60

// On récupère le TextView qui affiche le texte final

61

text = (TextView) findViewById();

62

// On permet au TextView de défiler

63

text.setMovementMethod(new ScrollingMovementMethod());

64

65

// On récupère l'éditeur de texte

66

editer = (EditText) findViewById();

67

// On ajoute un Listener sur l'appui de touches

68

editer.setOnKeyListener(new View.OnKeyListener() {

69

@Override

70

public boolean onKey(View v, int keyCode, KeyEvent event) {

71

// On récupère la position du début de la sélection dans le

texte

72

 

73

// Ne réagir qu'à l'appui sur une touche (et pas au

relâchement)

74

if(event.getAction() == 0)

75

// S'il s'agit d'un appui sur la touche « entrée »

76

if(keyCode == 66)

77

// On insère une balise de retour à la ligne

78

editer.getText().insert(cursorIndex, "<br />");

79

return true;

80

}

81

});

82

// On ajoute un autre Listener sur le changement, dans le texte cette fois

83

editer.addTextChangedListener(new TextWatcher() {

84

@Override

85

public void onTextChanged(CharSequence s, int start, int before, int count) {

86

// Le Textview interprète le texte dans l'éditeur en une certaine couleur

87

text.setText(Html.fromHtml("<font color=\"" + currentColor + "\">" + editer.getText().toString() + "</font>", getter, null));

88

}

89

90

@Override

 

91

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

92

93

}

94

95

@Override

96

public void afterTextChanged(Editable s) {

97

98

}

99

});

100

101

102

// On récupère le RadioGroup qui gère la couleur du texte

103

colorChooser = (RadioGroup) findViewById(R.id.colors);

104

// On rajoute un Listener sur le changement de RadioButton sélectionné

105

colorChooser.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

106

@Override

107

public void onCheckedChanged(RadioGroup group, int checkedId) {

108

// En fonction de l'identifiant du RadioButton sélectionné…

109

switch(checkedId)

110

{

111

// On change la couleur actuelle pour noir

112

 

113

currentColor = "#000000";

114

break;

115

// On change la couleur actuelle pour bleu

116

case :

117

currentColor = "#0022FF";

118

break;

119

// On change la couleur actuelle pour rouge

120

case :

121

currentColor = "#FF0000";

122

}

123

/*

124

* On met dans l'éditeur son texte actuel

125

* pour activer le Listener de changement de texte

126

*/

127

editer.setText(editer.getText().toString());

128

}

129

});

130

131

smile = (ImageButton) findViewById(R.id.smile);

132

smile.setOnClickListener(new View.OnClickListener() {

133

@Override

134

public void onClick(View v) {

135

// On récupère la position du début de la sélection dans le

texte

 

136

int selectionStart = editer.getSelectionStart();

137

// Et on insère à cette position une balise pour afficher l'image du smiley

138

editer.getText().insert(selectionStart, "<img src=\"smile\" >");

139

}

140

});

141

142

heureux =(ImageButton) findViewById(R.id.heureux);

143

heureux.setOnClickListener(new View.OnClickListener() {

144

@Override

145

public void onClick(View v) {

146

// On récupère la position du début de la sélection

147

int selectionStart = editer.getSelectionStart();

148

editer.getText().insert(selectionStart, "<img src=\"heureux\" >");

149

}

150

});

151

152

clin = (ImageButton) findViewById();

153

clin.setOnClickListener(new View.OnClickListener() {

154

@Override

155

public void onClick(View v) {

156

//On récupère la position du début de la sélection

157

int selectionStart = editer.getSelectionStart();

158

 

159

}

160

});

161

162

bold = (Button) findViewById();

163

bold.setOnClickListener(new View.OnClickListener() {

164

@Override

165

public void onClick(View vue) {

166

// On récupère la position du début de la sélection

167

int selectionStart = editer.getSelectionStart();

168

// On récupère la position de la fin de la sélection

169

int selectionEnd = editer.getSelectionEnd();

170

171

Editable editable = editer.getText();

172

173

// Si les deux positions sont identiques (pas de sélection de plusieurs caractères)

174

if(selectionStart == selectionEnd)

175

//On insère les balises ouvrante et fermante avec rien dedans

176

editable.insert(selectionStart, "<b></b>");

177

else

178

{

179

// On met la balise avant la sélection

 

180

editable.insert(selectionStart, "<b>");

181

// On rajoute la balise après la sélection (et après les 3 caractères de la balise <b>)

182

editable.insert(selectionEnd + 3, "</b>");

183

}

184

}

185

});

186

187

italic = (Button) findViewById(R.id.italic);

188

italic.setOnClickListener(new View.OnClickListener() {

189

@Override

190

public void onClick(View vue) {

191

// On récupère la position du début de la sélection

192

int selectionStart = editer.getSelectionStart();

193

// On récupère la position de la fin de la sélection

194

int selectionEnd = editer.getSelectionEnd();

195

196

Editable editable = editer.getText();

197

198

// Si les deux positions sont identiques (pas de sélection de plusieurs caractères)

199

if(selectionStart == selectionEnd)

200

//On insère les balises ouvrante et fermante avec rien dedans

201

editable.insert(selectionStart, "<i></i>");

202

 

203

{

204

// On met la balise avant la sélection

205

editable.insert(selectionStart, "<i>");

206

// On rajoute la balise après la sélection (et après les 3 caractères de la balise <b>)

207

editable.insert(selectionEnd + 3, "</i>");

208

}

209

}

210

});

211

212

underline = (Button) findViewById(R.id.underline);

213

underline.setOnClickListener(new View.OnClickListener() {

214

@Override

215

public void onClick(View vue) {

216

// On récupère la position du début de la sélection

217

int selectionStart = editer.getSelectionStart();

218

// On récupère la position de la fin de la sélection

219

int selectionEnd = editer.getSelectionEnd();

220

221

Editable editable = editer.getText();

222

223

// Si les deux positions sont identiques (pas de sélection de plusieurs caractères)

224

if(selectionStart == selectionEnd)

 

9.5. Objectifs secondaires

9.5.1. Boutons à plusieurs états

Entestantvotreapplication,vousverrezqu’encliquantsurunbouton,ilconservesacouleuret nepassepasorange,commelesvraisboutonsAndroid.Leproblèmeestquel’utilisateurrisque d’avoirl’impressionquesonclicnefaitrien,ilfautdoncluifournirunmoyend’avoirunretour. Onvafaireensortequenosboutonschangentdecouleurquandoncliquedessus.Pourcela,on vaavoirbesoindu 9-Patch visibleàlafiguresuivante.

 

Figure 9.10.–Ceboutonvanouspermettredemodifierlacouleurd’unboutonappuyé

Commentfairepourqueleboutonprennecefondquandoncliquedessus?Onvautiliserun type de drawable que vous ne connaissez pas, les state lists. Voici ce qu’on peut obtenir à la fin:

1         <?xml version="1.0" encoding="utf-8"?>

2         <selector xmlns:android="; >

3         <item android:state_pressed="true"

4         android:drawable="@drawable/pressed" />

 

<se

lec

tor>

<item

an

droid:state_pres

sed="true"

an

droid:dra

wable="@dra

wable/pres

sed"

On a une racinequi englobe des <item>, et chaque <item> correspond à un état. Le principe est qu’on va associer chaque état à une image différente. Ainsi, le premier état

/>indiqueque,quandleboutonestdansl’état«pressé»,onutiliseledrawabled’identifiant

pres

sed

 

pres

                              (quicorrespondàuneimagequis’appelle                                           ).Leseconditem,<item

an

droid:dra

wable="@dra

wable/num

ber"

/>

, n’a pas d’état associé, c’est donc l’état par

défaut.SiAndroidnetrouvepasd’étatquicorrespondàl’étatactueldubouton,alorsilutilisera celui-là.

!

EnparcourantleXML,Androids’arrêteradèsqu’iltrouveraunattributquicorrespondà l’état actuel, et, comme je vous l’ai déjà dit, il n’existe que deux attributs qui peuvent correspondreàunétat:soitl’attributquicorrespondàl’état,soitl’étatpardéfaut,celui quin’apasd’attribut.Ilfautdoncquel’étatpardéfautsoitledernierdelaliste,sinon

Androids’arrêteraàchaquefoisqu’iltombedessus,etnechercherapasdansles<item> suivants.

9.5.2. Internationalisation

Pourtoucherleplusdegenspossible,ilvousesttoujourspossibledetraduirevotreapplication enanglais!Mêmesi,jel’avoue,iln’yariendebiencompliquéàcomprendre.

9.5.3. Gérer correctement le mode paysage

Etsivoustournezvotretéléphoneenmodepaysage( Ctrl + F11 avecl’émulateur)?Ehoui,ça nepassepastrèsbien.Maisvoussavezcommentprocéder,n’est-cepas?


10.   Des widgets plus avancés et des boîtesde dialogue

Onavudansunchapitreprécédentlesvueslespluscourantesetlesplusimportantes.Maisle problèmeestquevousnepourrezpastoutfaireaveclesélémentsprécédemmentprésentés.Je penseenparticulieràunestructurededonnéesfondamentalepourreprésenterunensemblede données…jeparlebienentendudeslistes.

Onverraaussilesboîtesdedialogue,quisontutiliséesdansénormémentd’applications.Enfin, jevousprésenteraidemanièreunpeumoinsdétailléed’autreséléments,moinsrépandusmais quipourraientéventuellementvousintéresser.

10.1. Les listes et les adaptateurs

N’oubliezpasqueleJavaestunlangageorientéobjetetqueparconséquentilpourraitvous arriverd’avoiràafficherunelisted’untyped’objetparticulier,deslivresparexemple.Ilexiste plusieursparamètresàprendreencomptedanscecas-là.Toutd’abord,quelleestl’informationà afficherpourchaquelivre?Letitre?L’auteur?Legenrelittéraire?Etquefairequandonclique surunélémentdelaliste?Etl’esthétiquedanstoutça,c’est-à-direcommentsontreprésentés leslivres?Affiche-t-onleurcouvertureavecleurtitre?Cesontautantd’élémentsàprendreen comptequandonveutafficheruneliste.

Adap

ter

Adap

ter

View

La gestion des listes se divise en deux parties distinctes. Tout d’abord les(que j’appellerai adaptateurs),quisontlesobjetsquigèrentlesdonnées,maispasleuraffichageou leur comportement en cas d’interaction avec l’utilisateur. On peut considérer un adaptateur commeunintermédiaireentrelesdonnéesetlavuequireprésentecesdonné’autrecôté, on trouve les, qui, eux, vont gérer l’affichage et l’interaction avec l’utilisateur, maissurlesquelsonnepeutpaseffectuerd’opérationdemodificationdesdonnées.

Adap

ter

View

Lecomportementtypiquepourafficherunelistedepuisunensemblededonnéesestcelui-ci:on donne à l’adaptateur une liste d’éléments à traiter et la manière dont ils doivent l’être, puis onpassecetadaptateuràun,commeschématiséàlafiguresuivante.Dansce dernier, l’adaptateur va créer un widget pour chaque élément en fonction des informations fourniesenamont.

 

Figure 10.1.–Schémadufonctionnementdes«Adapter»et«AdapterView»

Adap

ter

View

Adap

ter

View

L’ovale rouge représente la liste des éléments. On la donne à l’adaptateur, qui se charge de créer une vue pour chaque élément, avec le layout à respecter. Puis, les vues sont fournies à un(toutesaumêmeinstant,bienentendu),oùellesserontaffichéesdansl’ordre fournietaveclelayoutcorrespondant.L’possèdeluiaussiunlayoutafindele personnaliser.

i

Savez-vous ce qu’est une fonction callback (vous trouverez peut-être aussi l’expression

« fonction de rappel »)? Pour simplifier les choses, c’est une fonction qu’on n’appelle pas directement, c’est une autre fonction qui y fera appel. On a déjà vu une fonction de callback dans la section qui parlait de l’évènementiel chez les widgets : quand vous cliquez sur un bouton, la fonction onTouch est appelée, alors qu’on n’y fait pas appel nous-mêmes.Danscetteprochainesectionfigureaussiunefonctiondecallback,jetiens justeàêtrecertainquevousconnaissiezbienleterme.

10.1.1. Les adaptateurs i

Adapter n’est en fait qu’une interface qui définit les comportements généraux des adaptateurs.Cependant,sivousvoulezunjourconstruireunadaptateur,faitesledériver deBaseAdapter .

Sionveutconstruireunwidgetsimple,onretiendratroisprincipauxadaptateurs:

Ar

rayA

dap

ter

1.,quipermetd’afficherlesinformationssimples;

Sim

pleA

dap

ter

2.estquantàluiutiledèsqu’ils’agitd’écrireplusieursinformationspour chaqueélément(s’ilyadeuxtextesdansl’élémentparexemple);

Cur

so

rA

dap

ter

3., pour adapter le contenu qui provient d’une base de données. On y reviendradèsqu’onaborderal’accèsàunebasededonnées.

10.1.1.1. Les listes simples : ArrayAdapter

an

rayA

dap

ter

Ar

rayA

dap

ter

Laclasse setrouvedanslepackage                                                                 .

pu

blic

Ar

rayA

dap

ter

(Context

contexte,

int

id,

T[]

ob

jects)

 

pu

blic

Ar

rayA

dap

ter

(Context

contexte,

int

id,

List<T>

Onvaconsidérerleconstructeursuivant: ouencore

ob

jects)

.Pourvousaider,voicilasignificationdechaqueparamètre:

— Voussavezdéjàcequ’estlecontexte,cesontdesinformationssurl’activité,onpasse doncl’activité.

— Quant à id, il s’agira d’une référence à un layout. C’est donc elle qui déterminera la miseenpagedel’élément.Vouspouvezbienentenducréeruneressourcedelayoutpar vous-mêmes,maisAndroidmetàdispositioncertainslayouts,quidépendentbeaucoup delalistedanslaquellevontsetrouverleswidgets.

ob

jects

—estlalisteouletableaudesélémentsàafficher. i

T[] signifie qu’il peut s’agir d’un tableau de n’importe quel type d’objet; de manière similaireList<T>signifiequelesobjetsdelalistepeuventêtreden’importequeltype. Attention,j’aidit«lesobjets»,doncpasdeprimitives(commeintoufloatparexemple) auquelcasvousdevrezpasserpardesobjetséquivalents(commeIntegerouFloat).

10.1.1.2. Des listes plus complexes : SimpleAdapter

an

pleA

Sim

pleA

dap

ter

Onpeututiliserlaclasse àpartirdupackage

dap

ter

.

Sim

pleA

dap

ter

Leestutilepouraffichersimplementplusieursinformationsparélé réalité,pourchaqueinformationdel’élémentonauraunevuedédiéequiafficheral’information voulue.Ainsi,onpeutavoirdutexte,uneimage…oumêmeuneautrelistesil’envievousen prend.Mieuxqu’unelongueexplication,voicil’exempled’unrépertoiretéléphonique:

1    import .ArrayList;

2    import .HashMap;

3    import ;

4    import .Activity;

5    import .Bundle;

6    import android.widget.ListAdapter;

7    import android.widget.ListView;

8    import android.widget.SimpleAdapter; 9

10       public class ListesActivity extends Activity {

11       ListView vue;

12

13       @Override

14       public void onCreate(Bundle savedInstanceState) {

15       super.onCreate(savedInstanceState);

16       setContentView(R.layout.activity_main);

17

18                            //On récupère une ListView de notre layout en XML, c'est la vue qui représente la liste

 

19

vue = (ListView) findViewById(R.id.listView);

20

21

/*

22

* On entrepose nos données dans un tableau qui contient deux colonnes :

23

* - la première contiendra le nom de l'utilisateur

24

* - la seconde contiendra le numéro de téléphone de l'utilisateur

25

*/

26

String[][] repertoire = new String[][]{

27

28

29

30

31

{"Bill Gates", "06 06 06 06 06"},

{"Niels Bohr", "05 05 05 05 05"},

{"Alexandre III de Macédoine", "04 04 04 04 04"}};

/*

32

* On doit donner à notre adaptateur une liste du type « List<Map<String, ?> » :

33

* - la clé doit forcément être une chaîne de caractères

34

* - en revanche, la valeur peut être n'importe quoi, un objet ou un entier par exemple,

35

* si c'est un objet, on affichera son contenu avec la méthode « toString() »

36

*

37

* Dans notre cas, la valeur sera une chaîne de caractères, puisque le nom et le numéro de téléphone

38

 

39

*/

40

List<HashMap<String, String>> liste = new ArrayList<HashMap<String, String>>();

41

42

HashMap<String, String> element;

43

//Pour chaque personne dans notre répertoire…

44

for(int i = 0 ; i < repertoire.length ; i++) {

45

//… on crée un élément pour la liste…

46

element = new HashMap<String, String>();

47

/*

48

* … on déclare que la clé est « text1 » (j'ai choisi ce mot au hasard, sans sens technique particulier)

49

* pour le nom de la personne (première dimension du tableau de valeurs)…

50

*/

51

("text1", repertoire[i][0]);

52

/*

53

* … on déclare que la clé est « text2 »

54

* pour le numéro de cette personne (seconde dimension du tableau de valeurs)

55

*/

56

("text2", repertoire[i][1]);

57

(element);

58

}

59

60           ListAdapter adapter = new SimpleAdapter(this,

61           //Valeurs à insérer

62           liste,

63           /*

64           * Layout de chaque élément (là, il s'agit d'un layout par

défaut

65           * pour avoir deux textes l'un au-dessus de l'autre, c'est

pourquoi on

66           * n'affiche que le nom et le numéro d'une personne)

67           */

68           android.R.layout.simple_list_item_2,

69           /*

70           * Les clés des informations à afficher pour chaque élément :

71           * - la valeur associée à la clé « text1 » sera la première

information

72           * - la valeur associée à la clé « text2 » sera la seconde

information

73           */

74           new String[] {"text1", "text2"},

75           /*

76           * Enfin, les layouts à appliquer à chaque widget de notre

élément

77           * (ce sont des layouts fournis par défaut) :

78           * - la première information appliquera le layout «

.text1 »

79           * - la seconde information appliquera le layout «

.text2 »

80           */

81           new int[] {.text1, .text2 });

82           //Pour finir, on donne à la ListView le SimpleAdapter

83           vue.setAdapter(adapter);

84           }

85           }

Cequidonnelafiguresuivante.

 

Figure 10.2.–Lerésultatenimage

pu

blic

Sim

pleA

dap

ter(Context

context,

List<?

ex

tends

On a utilisé le constructeur

Map<String,

?>

data,

int

res

source,

String[]

from,

int[]

to)

.

10.1.1.3. Quelques méthodes communes à tous les adaptateurs

void

add

(T

ob

ject)

 

void

in

sert

(T

ob

ject,

int

po

si

Tout d’abord, pour ajouter un objet à un adaptateur, on peut utiliser la méthode oul’inséreràunepositionparticulièreavec

tion). Il est possible de récupérer un objet dont on connaît la position avec la méthode T

ge

tI

tem

(int

po

si

tion)

get

Po

si

tion

(T

ob

ject)

                 

,oubienrécupérerlapositiond’unobjetprécisaveclaméthodeint

.

void

re

move

(T

ob

ject)

void

clear()

Onpeutsupprimerunobjetaveclaméthodeouvidercomplètement l’adaptateuravec.

Ar



rayA

dap

ter

String

toS

tring()

 

Text

View

Pardéfaut,unafficherapourchaqueobjetdelalistelerésultatdelaméthode associéeetl’inséreradansune     .

Voiciunexempledelamanièred’utilisercescodes:

1     // On crée un adaptateur qui fonctionne avec des chaînes de

caractères

2     ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);

3     // On rajoute la chaîne de caractères "Pommes"

4     ("Pommes");

5     // On récupère la position de la chaîne dans l'adaptateur. Comme il n'y a pas d'autres chaînes dans l'adaptateur, position vaudra 0

6     int position = adapter.getPosition("Pommes");

7     // On affiche la valeur et la position de la chaîne de caractères

8     Toast.makeText(this, "Les " + adapter.getItem(position) +

" se trouvent à la position " + position + ".",

Toast.LENGTH_LONG).show();

9     // Puis on la supprime, n'en n'ayant plus besoin

10    adapter.remove("Pommes");

10.1.2. Les vues responsables de l’affichage des listes : les AdapterView

an

ter

View

Adap

ter

View

Ontrouvelaclasse danslepackage                                                             .

Adap

ter

View

Adap

ter

View

Adap

ter

View

Alorsquel’adaptateursechargeradeconstruirelessous-éléments,c’estl’quiliera cessous-élémentsetquiferaensortedelesafficherenuneliste.Deplus,c’estl’ quigéreralesinteractionsaveclesutilisateurs:l’adaptateurs’occupedesélémentsentantque données, alors que l’s’occupe de les afficher et veille aux interactions avec un utilisateur.

Adap

ter

View

Onobservetroisprincipaux:

an

droid.R.layout.simple_list_item_

List

View

Grid

View

1.,poursimplementafficherdesélémentslesunsaprèslesautres; 2.,afind’organiserlesélémentssouslaformed’unegrille;

Spin

ner

3.,quiestunelistedéfilante.

Adap

ter

View

 

void

se

tA

dap

ter

Pour associer un adaptateur à une                                   , on utilise la méthode

(Adap

ter

adap

ter)

,quisechargeradepeuplerlavue,commevousleverrezdansquelques

instants.

10.1.2.1. Les listes standards : ListView

an

View

Onlestrouvedanslepackage.Ellesaffichentlesélémentslesuns

aprèslesautres,commeàlafiguresuivante.Lelayoutdebaseest

 

Figure 10.3.–Unelistesimple

L’exempleprécédentestobtenuàl’aidedececode:

1 import .ArrayList;

2

3    import .Activity;

4    import .Bundle;

5    import android.widget.ArrayAdapter;

6    import android.widget.ListView;

7

8       public class TutoListesActivity extends Activity {

9       ListView liste = null;

10

11       @Override

12       public void onCreate(Bundle savedInstanceState) {

13       super.onCreate(savedInstanceState);

14       setContentView();

15

16       liste = (ListView) findViewById(R.id.listView);

17       List<String> exemple = new ArrayList<String>();

18       ("Item 1");

19       ("Item 2");

20       ("Item 3");

21

22       ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, exemple);

23       liste.setAdapter(adapter);

24       }

25       }

Au niveau évènementiel, il est toujours possible de gérer plusieurs types de clic, comme par exemple:

void

se

tO

nI

tem

Cli

ck

Lis

te

ner

(Adap

ter

tem

Cli

ck

Lis

te

ner

lis

te

ner)

pourunclicsimplesurunélémentdelaliste.Lafonctiondecallback associéeestvoid

onI

tem

Click

(Adap

ter

View<?>

adap

ter,

View

view,

int

po

si

tion,

long

id)

,

adap

ter

 

Adap

ter

View

po

si

tion

avec l’ quicontientlavuesurlaquelleleclicaétéeffectué,view quiestlavueenelle-même,quiestlapositiondelavuedanslalisteetenfin idquiestl’identifiantdelavue.

void

se

tO

nI

tem

Long

Cli

ck

Lis

te

ner

(Adap

ter

tem

Long

Cli

ck

Lis

te

ner

lis

te

ner)

boo

lean

onI

tem

Long

Click

(Adap

ter

View<?>

adap

ter,

View

view,

int

po

si

pourunclicprolongésurunélémentdelaliste.Lafonctiondecallback associée est

tion,

long

id)

.

Cequidonne:

   

En revanche il peut arriver qu’on ait besoin de sélectionner un ou plusieurs éléments. Tout d’abord,ilfautindiqueràlalistequelmodedesélectionelleaccepte.Onpeutlepréciseren

an

droid:choi

ce

Mode

 

sin

gle

Choice

XMLàl’aidedel’attribut                                                      quipeutprendrelesvaleurs

mul

ti

ple

Choice

void

set

Choi

ce

Mode(int

mode)

(sélectionnerunseulélément)ou(sélectionnerplusieurséléments).EnJava, ilsuffitd’utiliserlaméthodeavecmodequipeutvaloirList

List

View.CHOICE_MODE_MUL

View.CHOICE_MODE_SINGLE(sélectionnerunseulélément)ou TIPLE(sélectionnerplusieurséléments).

Ànouveau,ilnousfautchoisirunlayoutadapté.Pourlessélectionsuniques,onpeututiliseran droid.R.layout.simple_list_item_single_choice,cequidonneralafiguresuivante.

 

Figure 10.4.–Unelistedesélectionunique

an

droid.R.layout.simple_list_item_mul

Pour les sélections multiples, on peut utiliser tiple_choice,cequidonneralafiguresuivante.

 

int

get

Che

cke

dI

tem

Po

si

tion()

Figure 10.5.–Unelistedesélectionmultiple Enfin,pourrécupérerlerangdel’élémentsélectionnédanslecasd’unesélectionunique,onpeut utiliserlaméthodeetdanslecasd’unesélectionmultiple,

Spar

se

Boo

lea

nAr

ray

get

Che

cke

dI

tem

Po

si

tions()

.

Spar

se

Boo

lea

nAr

ray

Unest un tableau associatif dans lequel on associe un entier à un

Hash

map<In

te

ger,

booléen,c’est-à-direquec’estunéquivalentàlastructureJavastandard

Boo

lean>

In

te

ger

Boo

lean

Hash

map<String,

,maisenplusoptimisé.Vousvousrappelezcequesontleshashmaps,lestableaux associatifs?Ilspermettentd’associeruneclé(dansnotrecasun)àunevaleur(dans cecas-ciun)én’estpasforcémentun entier, on peut par exemple associer un nom à une liste de prénoms avec

Ar

ray

List<String>

afinderetrouverlesprénomsdesgensquiportentunnomencommun.

Spar

se

Boo

lea

nAr

ray

boo

lean

get(int

key)

En ce qui concerne les, il est possible de vérifier la valeur associée à une clé entière avec la méthode. Par exemple dans notre cas de la sélection multiple, on peut savoir si le troisième élément de la liste est sélectionné en faisant

Che

cke

dI

tem

Po

si

tions().get(3)

, et, si le résultat vaut true, alors l’élément

estbiensélectionnédanslaliste.

10.1.2.2. Application

Voici un petit exemple qui vous montre comment utiliser correctement tous ces attributs. Il s’agitd’uneapplicationquiréaliseunsondage.L’utilisateurdoitindiquersonsexeetleslangages de programmation qu’il maîtrise. Notez que, comme l’application est destinée aux Zéros qui suiventcetuto,pardéfautonsélectionnelesexemasculinetondéclarequel’utilisateurconnaît leJava!

Dèsquel’utilisateurafinid’entrersesinformations,ilpeutappuyersurunboutonpourconfirmer sa sélection. Ce faisant, on empêche l’utilisateur de changer ses informations en enlevant les boutonsdesélectionetenl’empêchantd’appuyerànouveausurlebouton,commelemontrela figuresuivante.

 

Figure 10.6.–À gauche, au démarrage de l’application; à droite, après avoir appuyé sur le bouton«Envoyer»

10.1.2.3. Solution Lelayout:

1       <?xml version="1.0" encoding="utf-8"?>

2       <LinearLayout xmlns:android=";

3       android:layout_width="fill_parent"

4       android:layout_height="fill_parent"

5       android:orientation="vertical" >

6

7        <TextView

8        android:id="@+id/textSexe"

9        android:layout_width="fill_parent"

10       android:layout_height="wrap_content"

11       android:text="Quel est votre sexe :" />

12

13         <!-- On choisit le mode de sélection avec android:choiceMode

-->

14         <ListView

15         android:id="@+id/listSexe"

16         android:layout_width="fill_parent"

17         android:layout_height="wrap_content"

18         android:choiceMode="singleChoice" >

19         </ListView>

20

21         <TextView

22         android:id="@+id/textProg"

23         android:layout_width="fill_parent"

24         android:layout_height="wrap_content"

25         android:text="Quel(s) langage(s) maîtrisez-vous :" />

26

27         <ListView

28         android:id="@+id/listProg"

29         android:layout_width="fill_parent"

30         android:layout_height="wrap_content"

31         android:choiceMode="multipleChoice" >

32         </ListView>

33

34         <Button

35         android:id="@+id/send"

36         android:layout_width="wrap_content"

37         android:layout_height="wrap_content"

38         android:layout_gravity="center"

39         android:text="Envoyer" />

40

41 </LinearLayout> Etlecode:

1 package sdz.exemple.selectionMultiple;

2

3    import .Activity;

4    import .Bundle;

5    import ;

6    import android.widget.ArrayAdapter; 7 import android.widget.Button;

8    import android.widget.ListView;

9    import android.widget.Toast;

10

11       public class SelectionMultipleActivity extends Activity {

12       /** Affichage de la liste des sexes **/

13       private ListView mListSexe = null;

14       /** Affichage de la liste des langages connus **/

15       private ListView mListProg = null;

16       /** Bouton pour envoyer le sondage **/

17       private Button mSend = null;

 

18

19

/** Contient les deux sexes **/

20

private String[] mSexes = {"Masculin", "Feminin"};

21

/** Contient différents langages de programmation **/

22

private String[] mLangages = null;

23

24

@Override

25

public void onCreate(Bundle savedInstanceState) {

26

super.onCreate(savedInstanceState);

27

setContentView();

28

29

//On récupère les trois vues définies dans notre layout

30

mListSexe = (ListView) findViewById(R.id.listSexe);

31

mListProg = (ListView) findViewById(R.id.listProg);

32

mSend = (Button) findViewById();

33

34

//Une autre manière de créer un tableau de chaînes de caractères

35

mLangages = new String[]{"C", "Java", "COBOL", "Perl"};

36

37

//On ajoute un adaptateur qui affiche des boutons radio (c'est l'affichage à considérer quand on ne peut

38

//sélectionner qu'un élément d'une liste)

39

mListSexe.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_single_choice, mSexes));

40

 

41

mListSexe.setItemChecked(0, true);

42

43

//On ajoute un adaptateur qui affiche des cases à cocher (c'est l'affichage à considérer quand on peut sélectionner

44

//autant d'éléments qu'on veut dans une liste)

45

mListProg.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice,

mLangages));

46

//On déclare qu'on sélectionne de base le second élément (Féminin)

47

mListProg.setItemChecked(1, true);

48

49

//Que se passe-t-il dès qu'on clique sur le bouton ?

50

mSend.setOnClickListener(new View.OnClickListener() {

51

52

@Override

53

public void onClick(View v) {

54

Toast.makeText(,

"Merci ! Les données ont été envoyées !",

Toast.LENGTH_LONG).show();

55

56

//On déclare qu'on ne peut plus sélectionner d'élément

57

mListSexe.setChoiceMode(ListView.CHOICE_MODE_NONE);

58        //On affiche un layout qui ne permet pas de sélection 59             mListSexe.setAdapter(new

ArrayAdapter<String>(,

android.R.layout.simple_list_item_1,

60                                                                           mSexes));

61

62            //On déclare qu'on ne peut plus sélectionner d'élément

63            mListProg.setChoiceMode(ListView.CHOICE_MODE_NONE);

64            //On affiche un layout qui ne permet pas de sélection 65            mListProg.setAdapter(new

ArrayAdapter<String>(, android.R.layout.simple_list_item_1, mLangages));

66

67            //On désactive le bouton

68            mSend.setEnabled(false);

69            }

70            });

71            }

72            }

10.1.2.4. Dans un tableau : GridView

an

View

Grid

View

Onpeututiliserlaclasse àpartirdupackage                                                        .

Cetypedelistefonctionnepresquecommeleprécédent;cependant,ilmetlesélémentsdans unegrilledontildétermineautomatiquementlenombred’élémentsparligne,commelemontre lafiguresuivante.

 

Figure 10.7.–Lesélémentssontplacéssurunegrille

an

droid:num

Co

void

set

Num

Co

lumns

(int

co

lumn)

Ilestcependantpossibled’imposercenombred’élémentsparligneàl’aidede lumnsenXMLetenJava.

10.1.2.5. Les listes défilantes : Spinner

an

ner

Spin

ner

Laclasse setrouvedanslepackage                                                      .

Adap

ter

View

Encore une fois, cetne réinvente pas l’eau chaude. Cependant, on utilisera deux vues. Une pour l’élément sélectionné qui est affiché, et une pour la liste d’éléments sélectionnables.Lafiguresuivantemontrecequiarrivesionnedéfinitpasdemiseenpagepour lalisted’éléments.

 

Figure 10.8.–Aucunemiseenpagepourlalisted’élémentsn’aétédéfinie

La première vue affiche uniquement « Element 2 », l’élément actuellement sélectionné. La secondevueaffichelalistedetouslesélémentsqu’ilestpossibledesélectionner.

void

set

Drop

Down

Vie

wRe

source

(int

id)

Heureusement,onpeutpersonnaliserl’affichagedelasecondevue,cellequiafficheuneliste,avec la fonction. D’ailleurs, il existe déjà un layout pardéfautpourcela.Voiciunexemple:

 

5    import android.widget.ArrayAdapter;

6    import android.widget.Spinner;

7

8       public class TutoListesActivity extends Activity {

9       private Spinner liste = null;

10

11       @Override

12       public void onCreate(Bundle savedInstanceState) {

13       super.onCreate(savedInstanceState);

14       setContentView();

15

16       liste = (Spinner) findViewById(R.id.spinner1);

17       List<String> exemple = new ArrayList<String>();

18       ("Element 1");

19       ("Element 2");

20       ("Element 3");

21       ("Element 4");

22       ("Element 5");

23       ("Element 6");

24

25       ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, exemple);

26       //Le layout par défaut est

android.R.layout.simple_spinner_dropdown_item

27       adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdow 28 liste.setAdapter(adapter);

29       }

30       }

Cecodedonneralafiguresuivante.

 

Figure 10.9.–Unstyleaétédéfini

10.2. Plus complexe : les adaptateurs personnalisés

Text

View

 

Ima

ge

View

Sim

pleA

dap

ter

Imaginezquevousvouliezfaireunrépertoiretéléphonique.Ilconsisteraitdoncenuneliste,et chaqueélémentdelalisteauraitunephotodel’utilisateur,sonnometprénomainsiqueson numérodetéléphone.Ainsi,onpeutdéduirequelesitemsdenotrelisteaurontunlayoutqui utiliseradeux   etune   .Jevousvoisvoustrémoussersurvotrechaiseen vous disant qu’on va utiliser unpour faire l’intermédiaire entre les données (complexes) et les vues, mais comme nous sommes des Zéros d’exception, nous allons plutôt créernotrepropreadaptateur. i

Jevousaiditqu’unadaptateurimplémentaitl’interfaceAdapter,cequiestvrai;cependant,quandoncréenotrepropreadaptateur,ilestplussagedepartirdeBaseAdapter afindenoussimplifierl’existence.

Adap

ter

View

Ar

ray

List

Ba

seA

dap

ter

Unadaptateurestleconteneurdesinformationsd’uneliste,aucontrairedel’,qui affichelesinformationsetrégitsesinteractionsavecl’utilisateur.C’estdoncdansl’adaptateur quesetrouvelastructurededonnéesquidéterminecommentsontrangéeslesdonnées.Ainsi, dansnotreadaptateursetrouveraunelistedecontactssousformede. Dèsqu’uneclassehéritede,ilfautimplémenterobligatoirementtroisméthodes:

 

View

get

View(int

po

si

tion,

View

convert

View,

View

Group

pa

rent)

Laméthodeestla plusdélicateàutiliser.Enfait,cetteméthodeestappeléeàchaquefoisqu’unitemestaffichéà l’écran,commeàlafiguresuivante.

 

Figure 10.10.–Dans cet exemple, la méthode « getView » a été appelée sur les sept lignes visibles,maispassurlesautreslignesdelaliste

Encequiconcernelestroisparamètres:

po

si

tion

—estlapositiondel’itemdanslaliste(etdoncdansl’adaptateur).

pa

rent

—estlelayoutauquelrattacherlavue.

convert

View

— Etvautnull…oupas,maisunemeilleureexplications’impose.

convert

View

convert

View

get

View

vautnulluniquementlespremièresfoisqu’onaffichelaliste.Dansnotreexemple, vaudra null aux sept premiers appels de(donc les sept premières

convert

View

créationsdevues),c’est-à-direpourtouslesélémentsaffichésàl’écranaudémarrage.Toutefois, dès qu’on fait défiler la liste jusqu’à afficher un élément qui n’était pas à l’écran à l’instant d’avant,nevautplusnull,maisplutôtlavaleurdelavuequivientdedisparaître del’écran.Cequisepasseeninterne,c’estquelavuequ’onn’afficheplusestrecyclée,puisqu’on aplusbesoindelavoir.

Ilnousfautalorsunmoyend’inflaterunevue,maissansl’associerànotreactivité.Ilexisteau moinstroisméthodespourcela:

Layou

tIn

fla

ter

get

Sys

tem

Ser

vice

(LAYOUT_IN

FLA

TER_SER

VICE)

—sur une activité.

Layou

tIn

fla

ter

get

Layou

tIn

fla

ter

()

—suruneactivité.

Layou

tIn

fla

ter

Layou

tIn

fla

(Context

contexte)

 

Ac

ti

vity

—,sachantque dérivedeContext.

Layou

tIn

fla

ter

Puisvouspouvezinflaterunevueàpartirdeceàl’aidedelaméthodeView

in

flate

(int

id,

View

Group

root)

, avec root la racine à laquelle attacher la hiérarchie

désérialisée.Sivousindiqueznull,c’estlaracineactuelledelahiérarchiequiserarenvoyée, sinonlahiérarchies’attacheraàlaracineindiquée.

get

View

Pourquoi ce mécanisme me demanderez-vous? C’est encore une histoire d’optimisation. En effet,sivousavezunlayoutpersonnalisépourvotreliste,àchaqueappeldevousallez peuplervotrerangéeaveclelayoutàinflaterdepuissonfichierXML:

 

convert

View

Cependant, je vous l’ai déjà dit plein de fois, la désérialisation est un processus lent! C’est pourquoiilfaut utiliserpourvérifiersicettevuen’estpasdéjàpeupléeetainsi nepasdésérialiseràchaqueconstructiond’unevue:

1    LayoutInflater mInflater;

2    String[] mListe;

3

4        public View getView(int position, View convertView, ViewGroup parent) {

5        TextView vue = null;

6        // Si la vue est recyclée, elle contient déjà le bon layout

7        if(convertView != null)

8        // On n'a plus qu'à la récupérer

9        vue = (TextView) convertView;

10       else

11       // Sinon, il faut en effet utiliser le LayoutInflater

12       vue = mInflater.inflate(R.layout.ligne, null);

13

14                           vue.setText(mListe[position]);

15

16       return vue;

17       }

Enfaisantcela,votrelistedevientaumoinsdeuxfoisplusfluide.

!

Quandvousutilisezvotrepropreadaptateuretquevoussouhaitezpouvoirsélectionnerdes élémentsdansvotreliste,jevousconseilled’ignorerlessolutionsdesélectionprésentées dans le chapitre sur les listes (vous savez, void setChoiceMode (int mode)) et de développervotrepropreméthode,,j’aiajoutéunbooléen danschaquecontactpoursavoirs’ilestsélectionnéoupas.

10.2.1. Amélioration : le pattern ViewHolder

find

View

ById

View

Hol

der

Dansnotreadaptateur,onremarquequ’onaoptimisélelayoutdechaquecontactennel’inflatant quequandc’estnécessaire…maisoninflatequandmêmelestroisvuesquiontlemêmelayout! C’estmoinsgrave,parcequelesvuesinflatéesparlesontplusrapidement,mais quandmême.Ilexisteunealternativepouraméliorerencorelerendu.Ilfaututiliseruneclasse internestatique,qu’onappelled’habitude.Cetteclassedevracontenirtoutesles vuesdenotrelayout:

 

View

Hol

der

 

View

Hol

der

 

void

set

Tag

Ensuite,lapremièrefoisqu’oninflatelelayout,onrécupèrechaquevuepourlesmettredansle ,puisoninsèrele danslelayoutàl’aidedelaméthode

(Ob

ject

tag)

,quipeutêtreutiliséesurn’importequelView.Cettetechniquepermetd’insérer

Ob

ject

get

Tag

()

View

Hol

der

 

convert

View

dansnotrevuedesobjetsafindelesrécupérerplustardaveclaméthode. Onrécupérerale        sile           n’estpasnull,commeçaonn’aurainflaté lesvuesqu’unefoischacune.

1         public View getView(int r, View convertView, ViewGroup parent) {

2         ViewHolder holder = null;

3         // Si la vue n'est pas recyclée

4         if(convertView == null) {

5         // On récupère le layout

6         convertView = mInflater.inflate(, null);

7

8        holder = new ViewHolder();

9        // On place les widgets de notre layout dans le holder

10       = (TextView) convertView.findViewById();

11       holder.mNumero = (TextView) convertView.findViewById(R.id.numero);

12       holder.mPhoto = (ImageView) convertView.findViewById(R.id.photo);

13

14       // puis on insère le holder en tant que tag dans le layout

15       convertView.setTag(holder);

16       } else {

17       // Si on recycle la vue, on récupère son holder en tag

18       holder = (ViewHolder)convertView.getTag();

19       }

20

21       // Dans tous les cas, on récupère le contact téléphonique concerné

22       Contact c = (Contact)getItem(r);

23       // Si cet élément existe vraiment…

24       if(c != null) {

25       // On place dans le holder les informations sur le contact

26       .setText(c.getNom());

27       holder.mNumero.setText(c.getNumero());

28       }

29       return convertView;

30       }

10.3. Les boîtes de dialogue

Uneboîtededialogueestunepetitefenêtrequipasseaupremierplanpourinformerl’utilisateur ou lui demander ce qu’il souhaite faire. Par exemple, si je compte quitter mon navigateur internet alors que j’ai plusieurs onglets ouverts, une boîte de dialogue s’ouvrira pour me demanderconfirmation,commelemontrelafiguresuivante.

 

Figure 10.11.–Firefox demande confirmation avant de se fermer si plusieurs onglets sont ouverts

Onlesutilisesouventpourannoncerdeserreurs,donneruneinformationouindiquerunétat d’avancementd’unetâcheàl’aided’unebarredeprogressionparexemple.

10.3.1. Généralités

Lesboîtesdedialogued’Androidsontditesmodales,c’est-à-direqu’ellesbloquentl’interaction avecl’activitésous-jacente.Dèsqu’ellesapparaissent,ellespassentaupremierplanensurbrillance devant notre activité et, comme on l’a vu dans le chapitre introduisant les activités  , une activitéqu’onnevoitplusquepartiellementestsuspendue. i

Les boîtes de dialogue héritent de la classe Dialog et on les trouve dans le package .Dialog.

Onverraicilesboîtesdedialoguelespluscommunes,cellesquevousutiliserezcertainementun jouroul’autre.Ilenexisted’autres,etilvousestmêmepossibledefairevotrepropreboîtede dialogue.Maischaquechoseensontemps.

Dansunsoucid’optimisation,lesdéveloppeursd’Androidontenvisagéunsystèmetrèsastucieux. Eneffet,onferaensortedenepasavoiràcréerdenouvelleboîtededialogueàchaqueoccasion, maisplutôtderecyclerlesanciennes.

Ac

ti

vity

 

Dia

log

on

Crea

te

Dia

log

(int

id)

Laclasse         possèdelaméthodedecallback            ,qui sera appelée quand on instancie pour la première fois une boîte de dialogue. Elle prend en argumentunentierquiseral’identifiantdelaboîte.Maisunexemplevautmieuxqu’unlong discours:

1    private final static int IDENTIFIANT_BOITE_UN = 0;

2    private final static int IDENTIFIANT_BOITE_DEUX = 1;

3

4       @Override

5       public Dialog onCreateDialog(int identifiant) {

6       Dialog box = null;

7       //En fonction de l'identifiant de la boîte qu'on veut créer 8         switch(identifiant) {

9          case IDENTIFIANT_BOITE_UN :

10         // On construit la première boîte de dialogue, que l'on insère dans « box »

11         break;

12

13         case IDENTIFIANT_BOITE_DEUX :

14         // On construit la seconde boîte de dialogue, que l'on insère dans « box »

15         break;

16         }

17         return box;

18         }

on

Crea

Biensûr,commeils’agitd’uneméthodedecallback,onnefaitpasappeldirectementà

te

Dia

log

 

void

show

Dia

log

(int

.Pourappeleruneboîtededialogue,onutiliselaméthode

on

Crea

te

Dia

log(id)

id),quisechargerad’appelerenluipassantlemêmeidentifiant.

show

Dia

log

on

Crea

te

Dia

log

Quand on utilise la méthodepour un certain identifiant la première fois, elle se charge d’appelercomme nous l’avons vu, mais aussi la méthode void

on

Pre

pa

re

Dia

log

(int

id,

Dia

log

dia

log)

,avecleparamètre idquiestencoreunefois

dia

log

show

Dia

log

on

Crea

te

Dia

log

l’identifiant de la boîte de dialogue, alors que le paramètreest tout simplement la boîtededialogueenelle-même.Lasecondefoisqu’onutiliseavecunidentifiant, neserapasappelée(puisqu’onnecréepasuneboîtededialoguedeuxfois),

on

Pre

pa

re

Dia

log

maisseraenrevancheappelée.

on

Pre

pa

re

Dia

log

on

Crea

te

Dia

log

Autrement dit,est appelée à chaque fois qu’on veut montrer la boîte de dialogue.Cetteméthodeestdoncàredéfiniruniquementsionveutafficheruncontenudifférent pour la boîte de dialogue à chaque appel, mais, si le contenu est toujours le même à chaque appel,ilsuffitdedéfinirlecontenudans,quin’estappeléequ’àlacréation. Etcelatombebien,c’estlesujetduprochainexercice!

10.3.2. Application

10.3.2.1. Énoncé

L’activitéconsisteraenungrosbouton.Cliquersurceboutonlancerauneboîtededialogue dontletexteindiqueralenombredefoisquelaboîteaétélancée.Cependantuneautreboîte dedialoguedevientjalouseauboutde5appelsetsouhaiteêtresollicitéeplussouvent,commeà lafiguresuivante.

 

Figure 10.12.–Aprèslecinquièmeclic

10.3.2.2. Instructions

Dia

log

(Context

context)

Pourcréeruneboîtededialogue,onvapasserparleconstructeur.

void

set

Title

On pourra ensuite lui donner un texte à afficher à l’aide de la méthode

(Char

Se

quence

text)

.

10.3.2.3. Ma solution

 

Onvamaintenantdiscuterdestypesdeboîtededialoguelespluscourantes.

10.3.3. La boîte de dialogue de base

Dia

log

Onsaitdéjàqu’uneboîtededialogueprovientdelaclasse.Cependant,vousavezbien vuqu’onnepouvaitmettrequ’untitredemanièreprogrammatique.Alors,delamêmefaçon qu’onfaituneinterfacegraphiquepouruneactivité,onpeutcréerunfichierXMLpourdéfinir lamiseenpagedenotreboîtededialogue.

 

OnpeutassociercefichierXMLàuneboîtededialoguecommeonlefaitpouruneactivité:

 

Surlerésultat,visibleàlafiguresuivante,onvoitbienàgauchel’icônedenotreapplicationet àdroiteletextequ’onavaitinséré.Onvoitaussiunedescontraintesdesboîtesdedialogue:le titrenedoitpasdépasserunecertainetaillelimite.

 

Figure 10.13.–Résultatenimage

Cependantilestassezrared’utilisercetypedeboîtededialogue.Ilyadesclassesbienplus pratiques.

10.3.4. AlertDialog

an

.Alert

Dia

log

Onlesutiliseà’agitdelaboîtededialoguela pluspolyvalente.Typiquement,ellepeutafficheruntitre,untexteet/ouunelisted’éléments.

Alert

Dia

log

Laforced’uneestqu’ellepeutcontenirjusqu’àtroisboutonspourdemanderà l’utilisateurcequ’ilsouhaitefaire.Bienentendu,ellepeutaussin’enconteniraucun.

Alert

Dia

log

 

Alert

Dia

Alert

Dia

der

Pourconstruireune     ,onpeutpasserparleconstructeurdelaclasse logbienentendu,maisonpréférerautiliserlaclasse,quipermetde simplifierénormémentlaconstruction.CeconstructeurprendenargumentunContext.

Alert

Dia

der

Unobjetdetypeconnaîtlesméthodessuivantes:

Alert

Dia

der

set

Can

ce

lable

(boo

lean

can

ce

lable)

—: si le paramètre

can

ce

lable

vaut true, alors on pourra sortir de la boîte grâce au bouton retour de

Alert

Dia

der

se

tI

con

(int

res

source)

 

Alert

Dia

der

se

notreappareil. —       ou

tI

con

(Dra

wable

icon)

: le paramètre icon doit référencer une ressource de type

dra

wable

 

Dra

wable

                                               oudirectementunobjetdetype                           .Permetd’ajouteruneicôneàla

Alert

Dia

der

set

Mes

sage

(int

res

source)

 

Alert

Dia

der

boîtededialogue. —   ou

set

Mes

sage

(String

mes

sage)

 

mes

sage

                                                                                                  : le paramètre                     doit être une ressource de

typeStringouuneString.

Alert

Dia

der

set

Title

(int

res

source)

 

Alert

Dia

der

set

          —                                                                                                 ou

Title

(String

title)

:leparamètretitledoitêtreuneressourcedetypeString

ouuneString.

Alert

Dia

der

set

View

(View

view)

 

Alert

Dia

der

set

View

          —                                                                                       ou

(int

res

source)

set

Con

tent

View

: le paramètre view doit être une vue. Il s’agit de l’équivalent de pourunobjetdetypeContext.Neperdezpasdevuequ’ilnes’agit

qued’uneboîtededialogue,elleestcenséeêtrededimensionréduite:ilnefautdonc pasajoutertropd’élémentsàafficher.

Onpeutensuiteajouterdesboutonsaveclesméthodessuivantes:

Alert

Dia

der

set

Po

si

ti

ve

But

ton

(text,

Dia

lo

gIn

ter

Cli

ck

Lis

te

ner

lis

te

ner)

,avectextquidoitêtreuneressourcedetypeStringouuneString,

lis

te

ner

etquidéfiniraquefaireencasdeclic.Ceboutonsetrouveratoutàgauche.

Alert

Dia

der

set

Neu

tral

But

ton

(text,

Dia

lo

gIn

ter

Cli

ck

Lis

te

ner

lis

te

ner)

.Ceboutonsetrouveraentrelesdeuxautresboutons.

Alert

Dia

der

set

Ne

ga

ti

ve

But

ton

(text,

Dia

lo

gIn

ter

Cli

ck

Lis

te

ner

lis

te

ner)

.Ceboutonsetrouveratoutàdroite.

Enfin, il est possible de mettre une liste d’éléments et de déterminer combien d’éléments on souhaitepouvoirchoisir:

Méthode

Éléments sélectionnables

Usage

 

 

Alert

Dia

der

 

se

tI

tems

(Char

Se

quence[]

 

items,

Dia

lo

gIn

ter

 

 

Cli

ck

Lis

te

ner

 

 

lis

te

ner)

 

                                                     

Aucun

Le paramètre items correspond au tableau

contenant les éléments à

mettre dans la liste, alors

que le paramètre

lis

te

ner

décrit l’action à effectuer quand on clique sur un élément.

 

Alert

Dia

der

 

set

Sin

gle

Choi

ceI

tems

 

(Char

Se

quence[]

items,

 

int

che

cke

dI

tem,

Dia

lo

gIn

ter

Cli

ck

Lis

te

ner

 

lis

te

ner)

 

                                                 

Unseulàlafois

che

cke

dI

tem

Leparamètre indiquel’élémentquiest sélectionnépardéfaut.Comme d’habitude,oncommenceparle rang0pourlepremierélément. Pournesélectionneraucun élément,ilsuffitdemettre-1. Lesélémentsserontassociésà unboutonradioafinquel’on nepuisseensélectionnerqu’un seul.

 

Plusieurs

Letableauper-

che

cke

dI

tems

metdedéterminerleséléments quisontsélectionnéspardéfaut. Les éléments seront associés à une case à cocher afin que l’on puisseensélectionnerplusieurs.

 

Alert

Dia

der

 

set

 

Mul

ti

ple

Choi

ceI

tems

 

(Char

Se

quence[]

 

items,

boo

lean[]

 

che

cke

dI

tems,

Dia

lo

gIn

ter

Cli

ck

 

Lis

te

ner

lis

te

ner)

 
                                           

10.4. Les autres widgets

10.4.1. Date et heure

Ilarriveassezfréquemmentqu’onaitàdemanderàunutilisateurdepréciserunedateouune heure,parexemplepourajouterunrendez-vousdansuncalendrier.

Ca

len

tIns

tance()

Ca

len

dar

Onvad’abordrévisercommentonutiliselesdatesenJava.C’estsimple,ilsuffitderécupérer un objet de type    à l’aide de la méthode de classe        .

Ca

len

dar

Cetteméthoderetourneunquicontiendralesinformationssurladateetl’heure,au momentdelacréationdel’objet.

!

SileCalendaraétécrééle23janvier2012à23h58,ilvaudratoujours«23janvier2012 à23h58»,mêmedixjoursplustard.IlfautdemanderunenouvelleinstancedeCalendar àchaquefoisquec’estnécessaire.

int

get(int

champ)

Ilestensuitepossiblederécupérerdesinformationsàpartirdelaméthode avecchampquiprendunevaleurtelleque:

Ca

len

—pourl’année;

Ca

len

dar.MONTH

—pour le mois. Attention, le premier mois est de rang 0, alors que le premierjourdumoisestbienderang1!

Ca

len

dar.DAY_OF_MONTH

—pourlejourdanslemois;

Ca

len

dar.HOUR_OF_DAY

—pourl’heure;

Ca

len

NUTE

Ca

len

COND

—pourlesminutes; —pourlessecondes.

 

10.4.1.1. Insertion de dates

Da

te

Pi

cker

an

droid:min

Date

an

droid:max

Date

Pour insérer une date, on utilise le widget  . Ce widget possède en particulier deuxattributsXMLintéressants.Toutd’abordpourindiquerquelleestla datelaplusancienneàlaquellepeutremonterlecalendrier,etsonopposé.

void

init(int

En Java, on peut tout d’abord initialiser le widget à l’aide de la méthode

an

nee,

int

mois,

int

jour_dans_le_mois,

Da

te

Pi

Da

te

Chan

ged

Lis

te

ner

lis

te

ner_en_cas_de_chan

ge

ment_de_date)

. Tous les attributs semblent assez évidents de

Lis

te

ner

Lis

te

ner

primeabordàl’exceptiondudernier,peut-ê’agitd’unquis’enclenchedèsque ladateduwidgetestmodifiée,onl’utilisecommen’importequelautre.Remarquez cependantqueceparamètrepeuttrèsbienresternull.

int

ge

tYear()

get

Month()

 

int

get

DayOf

Month()

Enfin vous pouvez à tout moment récupérer l’année avec, le mois avec int etlejourdanslemoisavec        .

Da

te

Pi

cker

Parexemple,j’aicrééunenXML,quicommenceen2012etsetermineen2032:

 

Da

te

Pi

cker

Puis je l’ai récupéré en Java afin de changer la date de départ (par défaut, un s’initialiseàladatedujour):

 

Cequidonnelerésultatvisibleàlafiguresuivante.

 

Figure 10.14.–NotreDatePicker

10.4.1.2. Insertion d’horaires

Ti

me

Pi

cker

Da

te

Pi

cker

void

set

Cur

ren

tHour(In

Pour choisir un horaire, on utilise     , classe pas très contraignante puisqu’elle fonctionnecomme!Alorsqu’iln’estpaspossiblededéfinirunhorairemaximalet unhoraireminimalcettefois,ilestpossiblededéfinirl’heureavec

te

ger

hour)

 

In

te

ger

get

Cur

ren

tHour()

                                   , de la récupérer avec                                                         , et de définir les minutes

void

set

Cur

rent

Mi

nute(In

te

ger

mi

nute)

 

In

te

ger

get

avec                                                                                    , puis de les récupérer avec

Cur

rent

Mi

nute()

.

void

se

tIs24Hour

View(Boo

lean

mettre_en_for

mat_24h)

Commenousutilisonsengrandemajoritéleformat24heures(rappelonsquepournosamisaméricainsiln’existepasde13e heure,maisunedeuxième1re heure),notezqu’ilestpossibledel’activer àl’aidedelaméthode.

Lis

te

ner

 

void

se

tOn

Ti

me

Chan

ged

Le                        pour le changement d’horaire est cette fois géré par

Lis

te

ner(Ti

me

Pi

Ti

me

Chan

ged

Lis

te

ner

on

Ti

me

Chan

ged

Lis

te

ner)

.

Ti

me

Pi

cker

Cettefoisencore,jedéfinisleenXML:

 

Lis

te

ner

Puis je le récupère en Java pour rajouter unqui se déclenche à chaque fois que l’utilisateurchangel’heure:

 

Cequidonnelafiguresuivante.

 

Figure 10.15.–Changementdel’heure

Da

te

Pi

cker

Dia

log

 

Ti

me

Pi

cker

Dia

log

Sachezenfinquevouspouvezutiliserdemanièreéquivalentedesboîtesdedialoguequicontiennent ceswidgets.Cesboîtess’appellent       et         .

10.4.1.3. Affichage de dates

Ana

log

Clock

Di

gi

tal

Clock

Il n’existe malheureusement pas de widgets permettant d’afficher la date pour l’API 7, mais il existe deux façons d’écrire l’heure actuelle, soit avec une horloge analogique (comme sur unemontreavecdesaiguilles)quis’appelle      ,soitavecunehorlogenumérique (commesurunemontresansaiguilles)quis’appelle,lesdeuxvisiblesàlafigure suivante.

 

Figure 10.16.–Àgaucheune«AnalogClock»etàdroiteune«DigitalClock»

10.4.2. Afficher des images

Ima

ge

View

an

droid:src

an

droid:sca

le

Type

an

droid:layout_width="fill_pa

Lewidgetdebasepourafficheruneimageest Onpeutluifourniruneimage enXMLàl’aidedel’attributdontlavaleurestuneressourcedetypedrawable. L’attributpermetdeprécisercommentvoussouhaitezquel’imageréagisse si elle doit être agrandie à un moment (si vous mettez rent"parexemple). i

Leratiod’uneimageestlerapportentrelahauteuretlalargeur.Sileratiod’uneimage estconstant,alorsenaugmentantlahauteur,lalargeuraugmentedansuneproportion identique et vice versa. Ainsi, avec un ratio constant, un carré reste toujours un carré, puisquequandonaugmentelahauteurdexlalongueuraugmenteaussidex.Sileratio n’est pas constant, en augmentant une des dimensions l’autre ne bouge pas. Ainsi, un carrédevientunrectangle,car,sionétirelahauteurparexemple,lalargeurn’augmente pas.

Lesdifférentesvaleursqu’onpeutattribuersontvisiblesàlafiguresuivante.

 

Figure 10.17.–L’imagepeutprendredifférentesvaleurs

Ima

ge

View

— fitXY:lapremièreimageestredimensionnéeavecunratiovariableetelleprendrale plusdeplacepossible.Cependant,elleresteradanslecadredel’.

fitS

tart

Ima

ge

View

Ima

ge

View

—:ladeuxièmeimageestredimensionnéeavecunratioconstantetelleprendra leplusdeplacepossible.Cependant,elleresteradanslecadredel’,puisira seplacersurlecôtéenhautàgauchedel’.

fit

Cen

ter

Ima

ge

View

Ima

ge

View

—:latroisièmeimageestredimensionnéeavecunratioconstantetelleprendra leplusdeplacepossible.Cependant,elleresteradanslecadredel’,puisira seplaceraucentredel’.

fi

tEnd

Ima

ge

View

Ima

ge

View

—:laquatrièmeimageestredimensionnéeavecunratioconstantetelleprendrale plusdeplacepossible.Cependant,elleresteradanslecadredel’,puisirase placersurlecôtébasàdroitedel’.

cen

ter

Ima

ge

View

—:lacinquièmeimagen’estpasredimensionnée.Elleiraseplaceraucentrede l’.

cen

ter

Crop

Ima

ge

View

—:lasixièmeimageestredimensionnéeavecunratioconstantetelleprendra leplusdeplacepossible.Cependant,ellepourradépasserlecadredel’.

cen

te

rIn

side

Ima

ge

View

Ima

ge

View

—: la dernière image est redimensionnée avec un ratio constant et elle prendraleplusdeplacepossible.Cependant,elleresteradanslecadredel’, puisiraseplaceraucentredel’.

void

se

tI

ma

ge

Re

source(int

id)

Dra

wable

 

void

se

tI

ma

ge

Dra

wable(Dra

wable

image)

Bit

map

 

void

se

tI

ma

ge

Bit

map(Bit

map

bm)

En Java, la méthode à employer dépend du typage de l’image. Par exemple, si l’image est décritedansuneressource,onvapasserpar.Onpeutaussi insérerunobjet aveclaméthodeou unfichier avec    .

Dra

wable

get

Dra

wable()

Enfin,ilestpossiblederécupérerl’imageaveclaméthode.

 

Bit

map

Dra

wable

Unestuneimagedemanièregénérale,pourêtreprécisuneimagematriciellecommeje lesavaisdéjàdécritesprécédemment,c’est-à-direunematrice(untableauàdeuxdimensions) pourlaquellechaquecasecorrespondàunecouleur;touteslescasesmiseslesunesàcôtédes autres forment une image. Unest un objet qui représente tout ce qui peut être dessiné. C’est-à-dire autant une image qu’un ensemble d’images pour former une animation, qu’uneforme(onpeutdéfinirunrectanglerougedansundrawable),etc.

Ima

ge

But

ton

Ima

ge

But

ton

 

Ima

ge

View

Notezenfin qu’il existe uneclasse appelée    ,qui est un bouton normal, mais avecuneimage.      dérivede           .

i

Pour des raisons d’accessibilité, il est conseillé de préciser le contenu d’un widget qui contientuneimageàl’aidedel’attributXMLandroid:contentDescription,afinque lesmalvoyantspuissentavoirunaperçusonoredecequecontientlewidget.Cetattribut estdisponiblepourtouteslesvues.

10.4.3. Autocomplétion

Edit

Text

Quand on tape un mot, on risque toujours de faire une faute de frappe, ce qui est agaçant! C’est pourquoi il existe une classe qui hérite deet qui permet, en passant par un adaptateur,desuggéreràl’utilisateurlemotqu’ilsouhaiteinsérer.

Au

to

Com

ple

te

Text

View

Cetteclasses’appelleetonvavoirsonutilisationdansunexemple danslequelonvademanderàl’utilisateurquelleestsacouleurpréféréeetl’aideràl’écrireplus facilement.

On peut modifier le nombre de lettres nécessaires avant de lancer l’autocomplétion à l’aide

an

droid:com

ple

tion

Thre

shold

 

void

set

Thre

de l’attribut                                                                     en XML et avec la méthode

shold(int

thre

shold)

enJava. :

 

Au

to

Com

ple

tio

nAc

ti

vity

Ensuite,jedéclarel’activitésuivante:

 

Etvoilà,dèsquenotreutilisateuratapédeuxlettresdunomd’unecouleur,unelistedéfilante nous permet de sélectionner celle qui correspond à notre choix, comme le montre la figure suivante.

 

Figure 10.18.–L’autocomplétionenmarche

Mul

tiAu

to

Com

ple

te

Text

View

Vousremarquerezquecetteautocomplétionsefaitsurlaligneentière,c’est-à-direquesivous tapez « Jaune rouge », l’application pensera que vous cherchez une couleur qui s’appelle « Jaune rouge », alors que bien entendu vous vouliez le mot « jaune » puis le mot « rouge ». Pourfaireensortequ’uneautocomplétionsoitrépartieentreplusieursconstituantsd’unemême chaînedecaractères,ilfaututiliserlaclasse.Toutefois,ilfaut

void

set

To

préciser quel caractère sera utilisé pour séparer deux éléments avec la méthode

ke

ni

zer(Mul

tiAu

to

Com

ple

te

Text

ke

ni

zer

t)

. Par défaut, on peut par exemple

Mul

tiAu

to

Com

ple

te

Text

ma

To

ke

ni

zer

utiliserun,quidifférencielesélémentspar

Mul

tiAu

to

Com

ple

te

Text

View

desvirgules(cequisignifiequ’àchaquefoisquevousécrirezunevirgule,le vousproposeraunenouvellesuggestion).

 

Adap

ter

 

Adap

ter

View

— L’affichaged’unelistes’organisedelamanièresuivante:ondonneunelistededonnéesà unadaptateur( )quiseraattachéàuneliste( ).L’adaptateurse chargeraalorsdeconstruirelesdifférentesvuesàafficherainsiquedegérerleurscycles devie.

Adap

ter

View

— Lesadaptateurspeuventêtreattachésàplusieurstypesd’:

List

View

Grid

View

—pourlisterlesvueslesunesendessousdesautres.

—pourafficherlesvuesdansunegrille.

Spin

ner

—pourafficherunelistedevuesdéfilante.

Ba

seA

dap

ter

— Lorsque vous désirez afficher des vues plus complexes, vous devez créer votre propre adaptateurquiétendlasuperclasseetredéfinirlesméthodesenfonction devotrelistededonnées.

— Lesboîtesdedialoguepeuventêtreconfectionnéesde2manièresdifférentes:parlaclasse

Dia

log

 

Alert

Dia

log

                                           ouparunbuilderpourconstruireune                                  ,cequiestpluspuissant.

Au

to

— Pourinsérerunwidgetcapabledegérerl’autocomplétion,onutiliseralewidget

Com

ple

te

Text

View

.


11. Gestion des menus de l’application

Àuneépoquepassilointaine,touslesterminauxsousAndroidpossédaientunboutonphysique pourafficherlemenu.Cependant,cettepratiqueestdevenueunpeuplusraredepuisqueles constructeursessaientaumaximumdedématérialiserlesboutons.MaisdepuisAndroid2.3,il existeunboutondirectementdansl’interfacedusystèmed’exploitation,quipermetd’ouvrirun menu.Ensorte,onpeutdirequetouslesutilisateurssonttouchésparlaprésenced’unmenu.

Entoutcas,unmenuestunendroitprivilégiépourplacercertainesfonctionstoutenéconomisant notreprécieuxespacedanslafenêtre.Vouspouvezparexemplefaireensortequecemenuouvre lapagedesoptions,ouaucontrairevousramèneàlapaged’accueil.

IlexistedeuxsortesdemenudansAndroid:

— Lemenud’options,celuiqu’onpeutouvriravecleboutonMenusurletélé téléphoneestdépourvudecettetouche,Androidfournitunboutondanssoninterface graphiquepouryaccéder.

— Lesmenuscontextuels,voussavez,cesmenusquis’ouvrentàl’aided’unclicdroitsous Windows et Linux? Eh bien, dans Android ils se déroulent dès lors qu’on effectue un longclicsurunélémentdel’interfacegraphique.

Et ces deux menus peuvent bien entendu contenir des sous-menus, qui peuvent contenir des sous-menus,etc.Encoreunefois,onvadevoirmanipulerdesfichiersXMLmais,franchement, vousêtesdevenusdesexpertsmaintenant,non?

11.1. Menu d’options

11.1.1. Créer un menu

Chaque activité est capable d’avoir son menu propre. On peut définir un menu de manière programmatique en Java, mais la meilleure façon de procéder est en XML. Tout d’abord, la racinedecemenuestdetype<menu>(vousarriverezàretenir?),etonnepeutpasvraiment lepersonnaliseravecdesattributs,cequidonnelamajoritédutemps:

 

Cemenudoitêtrepeupléavecdeséléments,etc’estsurcesélémentsquecliqueral’utilisateur pouractiveroudésactiverunefonctionnalité.Cesélémentss’appellentenXMLdes<item>et peuventêtrepersonnalisésàl’aidedeplusieursattributs:

an

droid:id

—, que vous connaissez déjà. Il permet d’identifier de manière unique un <item>.Autantd’habitudecetattributestfacultatif,autantcettefoisilestvraiment indispensable,vousverrezpourquoidanscinqminutes.

an

droid:icon

—,pouragrémentervotre<item>d’uneicône.

an

droid:title

—,quiserasontextedanslemenu.

an

droid:en

abled="false"

— Enfin,onpeutdésactiverpardéfautun<item>avecl’attribut.

i

Vouspouvezrécupérergratuitementetlégalementlesicô rapportàl’endroitoùsesitueleSDK,vouslestrouverezdans.\platforms\androidx\data\res\ avec x le niveau de l’API que vous utilisez. Il est plutôt recommandé d’importercesimagesentantquedrawablesdansnotreapplication,plutôtquedefaire référenceàl’icôneutiliséeactuellementparAndroid,carellepourraitnepasexisterouêtre différenteenfonctiondelaversiond’Androidqu’exploitel’utilisateur.Sivoussouhaitez fairevospropresicônes,sachezquelataillemaximalerecommandéeestde72pixelspour leshautesrésolutions,48pixelspourlesmoyennesrésolutionset38pixelspourlesbasses résolutions.

Le problème est que l’espace consacré à un menu est assez réduit, comme toujours sur un périphérique portable, remarquez. Afin de gagner un peu de place, il est possible d’avoir un <item>quiouvreunsous-menu,etcesous-menuseraàtraitercommetoutautremenu.Onlui ’autrestermes,lasyntaxeestcelle-ci:

 

an

droid:title

an

droid:tit

le

Con

den

sed

an

droid:title

droid:che

ckable

Le sous-menu s’ouvrira dans une nouvelle fenêtre, et le titre de cette fenêtre se trouve dans l’attribut. Si vous souhaitez mettre un titre plutôt long dans cette fenêtre et conserver un nom court dans le menu, utilisez l’attribut, qui permetd’indiqueruntitreà<item> qui se trouvent dans un sous-menu peuvent être modulés avec d’autres attributs, comme an auquelvouspouvezmettretruesivoussouhaitezquel’élémentpuisseêtre

Check

Box

an

droid:che

cked

an

droid:tit

le

Con

den

sed="Item

coché,commeune.Deplus,sivoussouhaitezqu’ilsoitcochépardéfaut,vouspouvez mettreàéalisequecen’estpastrèsclair,aussivousproposé-je deregarderlesdeuxfiguressuivantes:lapremièreutilise

1",ladeuxièmeandroid:title="Item1maisavecuntitrepluslongquandmême".

Enfin,ilpeutarriverqueplusieursélémentsseressemblentbeaucoupoufonctionnentensemble,

Check

Box

 

an

droid:che

cka

ble

Be

c’estpourquoiilestpossibledelesregrouperavec<group>.Sionveutquetousleséléments dugroupesoientdes           ,onpeutmettreaugroupel’attribut

ha

vior="all"

 

Ra

dio

But

ton

                                            ,ou,sionveutqu’ilssoienttousdes                                    ,onpeutmettrel’attribut

an

droid:che

cka

ble

Be

ha

vior="single"

.

Voiciunexempledemenuqu’ilvousestpossibledecréeraveccetteméthode:

 

boo

lean

on

Crea

teOp

tions

Menu

(Menu

menu)

Comme pour un layout, il va falloir dire à Android qu’il doit parcourir le fichier XML pour construire le menu. Pour cela, c’est très simple, on va surcharger la méthode d’uneactivité.Cetteméthodeestlancéeaumomentdela

boo

lean

on

Pre

pa

reOp

tions

Menu

(Menu

menu)

premièrepressionduboutonquifaitémergerlemenu.Cependant,commeaveclesboîtesde dialogue,sivoussouhaitezquelemenuévolueàchaquepressiondubouton,alorsilvousfaudra surchargerlaméthode.

PourparcourirleXML,onval’inflater,ehoui!encoreunefois!Encoreunpetitrappeldece qu’estinflater?To inflate,c’estdésérialiserenfrançais,etdansnotrecasc’esttransformerun objetquin’estdécritqu’enXMLenvéritableobjetqu’onpeutmanipuler.Voicilecodetype dèsqu’onaconstituéunmenuenXML:

 

Sivoustestezcecode,vousremarquereztoutd’abordque,contrairementaupremierexemple, iln’yapasassezdeplacepourcontenirtouslesitems,c’estpourquoile6e itemsetransforme enunboutonpourafficherlesélémentscachés,commeàlafiguresuivante.

 

Figure 11.1.–Unboutonpermetd’accéderauxautresitems

Che

ckable

Ensuite vous remarquerez que les items 4.1 et 4.2 sont décrits comme, mais ne possèdent pas de case à cocher. C’est parce que les seuls <item> que l’on puisse cocher sont ceuxquisetrouventdansunsous-menu.

Me

nuI

tem

se

tE

na

bled

(boo

lean

ac

ti

ver)

nuI

tem

Les <item> 5.1 et 5.2 sont désactivés par défaut, mais vous pouvez les réactiver de manière programmatique à l’aide de la fonction(le Me retournéestceluisurlequell’opérationaétéeffectuée,defaçonàpouvoircumulerles

setters).

i

Unsetter estuneméthodequipermetdemodifierundesattributsd’getter estuneméthodequipermet,elle,derécupérerunattributd’unobjet.

Vous pouvez aussi si vous le désirez construire un menu de manière programmatique avec la méthodesuivantequis’utilisesurunMenu:

 

Où:

grou

pId

—permetd’indiquersil’objetappartientàungroupe.Sicen’estpaslecas,vous .

ob

jec

tId

—estl’identifiantuniquedel’objet,,mais jenelerecommandepas.

— ordre permet de définir l’ordre dans lequel vous souhaitez le voir apparaître dans le éfaut,l’ordrerespectéestceluidufichierXMLoudel’ajoutaveclaméthode add,maisaveccetteméthodevouspouvezbousculerl’ordreétablipourindiquercelui quevouspréférez.Encoreunefois,. — titreestletitredel’item.

Demanièreidentiqueetaveclesmêmesparamètres,vouspouvezconstruireunsous-menuavec laméthodesuivante:

Etc’estindispensabledepasserlemenuàlasuperclassecommeonlefait?

Laréponsecourteestnon,laréponselongueestnon,maisfaites-lequandmême.Enpassant lemenuàl’implémentationpardéfaut,Androidvapeuplerlemenuavecdesitemssystèmes standards.Alors,entantquedébutants,vousneverrezpasladifférence,maissivousdevenez desutilisateursavancés,unoublipourraitbienvousencombrer.

11.1.2. Réagir aux clics

boo

lean

onOp

tion

sI

tem

Se

lec

ted

(Me

nuI

tem

item)

Vous vous rappelez quand je vous avais dit qu’il était inconcevable d’avoir un <item> sans identifiant?C’étaitparcequel’identifiantd’un<item>permetdedéterminercommentilréagit auxclicsauseindelaméthode.

Dans l’exemple précédent, si on veut que cliquer sur le premier item active les deux items inactifs,onpourraitutiliserlecodesuivantdansnotreactivité:

 

su

tion

sI

tem

Se

lec

ted(item)

Onretournetruesionabiengérél’item,falsesionariengéré.D’ailleurs,sionpassel’item à, alors la méthode retournera false puisqu’elle

su

tion

sI

tem

Se

lec

ted(item)

ne sait pas gérer l’item. En revanche, je vous conseille de toujours retourner quand vous êtes dans une classe qui ne dérive pas directement

Ac

ti

vity

de, puisqu’il se peut que vous gériez l’item dans une superclasse de votre classe actuelle.

boo

lean

on

Crea

teOp

tions

Menu(menu)

Dans,onretournetoujourstruepuisqu’ongèredans touslescaslacréationdumenu. i

Googlenousfournituneastucedequalitésursonsite:souvent,uneapplicationpartage plusoumoinsle(s)même(s)menu(s)entretoussesécrans(etdonctoutessesactivités), c’estpourquoiilestconseilléd’avoiruneactivitédebasequinegèrequelesévènements liés au(x) menu(s) (création dans onCreateOptionsMenu, mise à jour dans onPrepa reOptionsMenu et gestion des évènements dans onOptionsItemSelected), puis d’en fairedérivertouteslesactivitésdenotreapplicationquiutilisentlesmêmesmenus.

11.2. Menu contextuel

Le menu contextuel est très différent du menu d’options, puisqu’il n’apparaît pas quand on appuiesurleboutond’options,maisplutôtquandoncliquesurn’importequelélément!Sur Windows,c’estlemenuquiapparaîtquandvousfaitesunclicdroit.

Ac

ti

vity

Alors,onneveutpeut-êtrepasquetouslesobjetsaientunmenucontextuel,c’estpourquoiil fautdéclarerquelswidgetsenpossèdent,etcelasefaitdanslaméthodedelaclasse

void

re

gis

ter

For

Con

text

Menu

(View

vue)

. Désormais, dès que l’utilisateur fera un clic

longsurcettevue,unmenucontextuels’ouvrira…enfin,sivousledéfinissez! Cemenusedéfinitdanslaméthodesuivante:

 

me

nuInfo

On

Pre

pare

Oùmenuestlemenuàconstruire,vuelavuesurlaquellelemenuaétéappeléet indiquesurquelélémentd’unadaptateuraétéappelélemenu,sionsetrouvedansunelistepar exemple.Cependant,iln’existepasdeméthodedutypecettefois-ci,parconséquent le menu est détruit puis reconstruit à chaque appel. C’est pourquoi il n’est pas conseillé de conserverlemenudansunparamètrecommenousl’avionsfaitpourlemenud’options.Voiciun exempledeconstructiondemenucontextueldemanièreprogrammatique:

 

Context

Me

nuInfo

boo

lean

on

Con

tex

tI

tem

Se

lec

ted

(Me

nuI

Onremarquedeuxchoses.Toutd’abordpourécriredesidentifiantsfacilement,laclasseMenu possèdeuneconstanteMenu.FIRSTquipermetdedésignerlepremierélément,puisledeuxième enincrémentant,etc.Ensuite,onpasselesparamètresàlasuperclasse.Enfait,cettemanœuvre apourbutbienprécisdepermettrederécupérerledanslaméthodequigère l’évènementieldesmenuscontextuels,laméthode

tem

item)

Context

Menu.Context

Me

nuInfo

get

Me

nuInfo

()

 

Me

nuI

tem

.Cefaisant,vouspourrezrécupérerdesinformationssurlavuequiaappelélemenu avec la méthode           de la classe      .

Unexempled’implémentationpournotreexemplepourraitêtre:

 

Context

Me

nuInfo

 

tar

get

View

po

si

tion

Voilà!Le apermisderécupérerlavuegrâceàsonattribut .Il possèdeaussiunattributidpourrécupérerl’identifiantdel’item(dansl’adaptateur)concerné ainsiqu’unattributpourrécupérersapositionauseindelaliste.

11.3. Maintenant que vous maîtrisez les menus, oubliez tout

Titreracoleur,j’enconviens,maisquirévèleunevéritéqu’ilvousfautconsidérer:lebouton

Menu estamenéàdisparaître.Demanièregénérale,lesutilisateursn’utilisentpascebouton,il n’estpasassezvisuelpoureux,cequifaitqu’ilsn’ypensentpasouignorentsonexistence.C’est assezgrave,oui.Jevousapprendsàl’utiliserparcequec’estquandmêmesacrémentpratiqueet puissant, mais c’est à vous de faire la démarche d’apprendre à l’utilisateur comment utiliser correctementcebouton,avecunToastparexemple.

Ilexistedessolutionsquipermettentdesepasserdecemenu.Androidaintroduitdansson

API11(Android3.0)l’ActionBar,quiestunebarredetitreétenduesurlaquelleilestpossible d’ajouter des widgets de façon à disposer d’options constamment visibles. Cette initiative a été efficace puisque le taux d’utilisation de l’ActionBar est bien supérieur à celui du bouton Menu .

Cependant,pournotrecours,cetteActionBarn’estpasdisponiblepuisquenousutilisonsl’API

7, et qu’il n’est pas question d’utiliser l’API 11 rien que pour ça — vous ne toucheriez plus que5%desutilisateursdel’AndroidMarket,aulieudes98%actuels…Ilexistedessolutions alternatives,commecelle-ciquiestofficielle  oucelle-làquiestpuissante  Jevousinviteà lesdécouvrirparvous-mêmes.

Histoirederetournerlecouteaudanslaplaie,sachezquelesmenuscontextuelssontrarement utilisés,puisqu’engénérall’utilisateurignoreleurprésenceounesaitpascommentlesutiliser (faireunappuilong,c’estcompliquépourl’utilisateur,vraiment).Encoreunefois,vouspouvez enseigneràvosutilisateurscommentlesutiliser,oubienajouterunealternativeplusvisuelle pourouvrirunmenusurunobjet.Çatombesuperbien,c’estlesujetduprochainchapitre.

 

— Lacréationd’unmenusefaitenXMLpourtoutcequieststatiqueetenJavapourtout cequiestdynamique.

— Ladéclarationd’unmenusefaitobligatoirementavecunélémentmenuàlaracinedu fichieretcontiendradesélémentsitem.

boo

lean

on

Crea

teOp

tions

Menu(Menu

menu)

boo

lean

onOp

tion

sI

tem

Se

lec

ted(Me

nuI

tem

— Un menu d’options s’affiche lorsque l’utilisateur clique sur le bouton de menu de son appareil.IlneseraaffichéquesilefichierXMLreprésentantvotremenuestdésérialisédans laméthodeetquevousavezdonnédes actionsàchaqueitemdanslaméthode item).

— Unmenucontextuels’affichelorsquevousappuyezlongtempssurunélémentdevotre interface.Pourcefaire,vousdevezconstruirevotremenuàpartirdelaméthodevoid

on

Crea

te

Con

text

Menu(Context

Menu

menu,

View

vue,

Context

Menu.Context

Me

nuInfo

me

nuInfo)

boo

lean

on

Con

tex

tI

tem

Se

lec

ted(Me

nuI

tem

item)

etrécupérerlavuequiafaitappelàvotremenucontextuelàpartir delaméthode.

— Sacheztoutdemêmequeleboutonmenuphysiquetendàdisparaitredeplusenplus pourunmenutactile.


12. Création de vues personnalisées

Voussavezdésormaisl’essentielpourdévelopperdebellesinterfacesgraphiquesfonctionnelles, etenthéorievousdevriezêtrecapablesdefairetoutcequevousdésirez.Cependant,ilvous manqueencorel’outilultimequivouspermettradedonnervieàtousvosfantasmeslesplus extravagants:êtrecapablesdeproduirevospropresvuesetainsiavoirlecontrôletotalsurleur aspect,leurtaille,leursréactionsetleurfonction.

Ondifférencietypiquementtroistypesdevuespersonnalisées:

— Sivoussouhaitezfaireunevuequiressembleàunevuestandardquevousconnaissezdéjà, vouspourrezpartirdecettevueetmodifiersonfonctionnementpourlefairecoïncider avecvosbesoins.

— Autrement, vous pourriez exploiter des vues qui existent déjà et les réunir de façon à produireunenouvellevuequiexploitelepotentieldesesvuesconstitutives.

— Oubienencore,sivoussouhaitezforgerunevuequin’existepasdutout,ilesttoujours possible de la fabriquer en partant de zéro. C’est la solution la plus radicale, la plus exigeante,maisaussilapluspuissante.

12.1. Règles avancées concernant les vues

!

Cettesectionesttrèsthéorique,jevousconseilledelalireunefois,delacomprendre,puis de continuer dans le cours et d’y revenir au besoin. Et vous en aurez sûrement besoin, d’ailleurs.

SivousdeviezinstancierunobjetdetypeViewetl’afficherdansuneinterfacegraphique,vous vousretrouveriezdevantuncarréblancquimesure100pixelsdecôté.Pastrèsglamour,j’en conviens.C’estpourquoi,quandoncréeunevue,ondoitjouersuraumoinsdeuxtableaux:les dimensionsdelavue,etsondessin.

12.1.1. Dimensions et placement d’une vue

Lesdimensionsd’unevuesontdeuxentiersquireprésententlataillequeprendlavuesurlesdeux axesdel’écran:lalargeuretlahauteur.Toutevuenepossèdepasqu’unepairededimensions, maisbiendeux:cellesquevousconnaissezetquivoussemblerontlogiquessontlesdimensions réellesoccupéesparlavuesurleterrain.Cependant,avantquelescoordonnéesréellessoient déterminées,unevuepasseparunephasedecalculoùelles’efforcededéterminerlesdimensions qu’ellesouhaiteraitoccuper,sansgarantiequ’ils’agiradesesdimensionsfinales.

FILL_PA

RENT

FILL_PA

RENT

Parexemple,sivousditesquevousdisposezd’unevuequioccupetouteseulesonlayoutparent etquevousluidonnezl’instruction,alorslesdimensionsréellesserontidentiques aux dimensions demandées puisque la vue peut occuper tout le parent. En revanche, s’il y a plusieurs vues qui utilisentpour un même layout, alors les dimensions réelles serontdifférentesdecellesdemandées,puisquelelayoutferaensortederépartirlesdimensions entrechacundesesenfants.

12.1.1.1. Un véritable arbre généalogique

Re

la

ti

ve

Layout

Vouslesavezdéjà,onpeutconstruireuneinterfacegraphiquedanslecodeouenXML.Jevais vousdemanderderéfléchirenXMLici,poursimplifierleraisonnement.UnfichierXMLcontient toujours un premier élément unique qui n’a pas de frère, cet élément s’appelle la racine, et danslecontextedudéveloppementd’interfacesgraphiquespourAndroidcetteracineseratrès souventun layout.Danslecodesuivant,laracineestun.

 

Celayoutpeutavoirdesenfants,quiserontdeswidgetsoud’autreslayouts.Dansl’éventualitéoù unenfantseraitunlayout,alorsilpeutaussiavoirdesenfantsàsontour.Onpeutdoncaffirmer que,commepourunefamille,ilestpossibledeconstruireunvéritablearbregénéalogiquequi commenceparlaracineets’étendsurplusieursgénérations,commeàlafiguresuivante.

 

Figure 12.1.–Danscetexemple,onpeutvoirquetouteslesvuessontdesenfantsoupetits-

enfantsdu«LinearLayout»etquelesautreslayoutspeuventaussiavoirdes enfants,tandisqueleswidgetsn’ontpasd’enfant

Ce que vous ne savez pas, c’est que la racine de notre application n’est pas la racine de la hiérarchiedesvuesetqu’elleseraforcémentl’enfantd’uneautrevuequ’acrééeAndroiddans notre dos et à laquelle nous n’avons pas accès. Ainsi, chaque vue que nous utiliserons sera

directement l’enfant d’un layout.

12.1.1.2. Le placement

void

mea

sure(int

width

Mea

Leplacement—quiseditaussilayout enanglais(ànepasconfondreavecleslayoutsquisont desvuesquicontiennentdesvues,etlelayoutcorrespondantàlamiseenpagedel’interface graphique) — est l’opération qui consiste à placer les vues dans l’interface graphique. Ce processuss’effectueendeuxétapesquis’exécuterontdansl’ordrechronologique.Toutd’abordet enpartantdelaracine,chaquelayoutvadonneràsesenfantsdesinstructionsquantàlataille qu’ils devraient prendre. Cette étape se fait dans la méthode

su

reS

pec,

int

height

Mea

su

reS

pec)

,nevouspréoccupezpastropdecetteméthode,onne

void

layout(int

l’implémenterapas.Puisvientlasecondeétape,quidébuteelleaussiparlaracineetoùchaque layouttransmettraàsesenfantsleursdimensionsfinalesenfonctiondesmesuresdéterminées dansl’étapeprécédente.Cettemanœuvresedérouledurantl’exécutionde

bord_gauche,

int

pla

fond,

int

bord_droit,

int

plan

cher)

,maisonnel’implémentera

pasnonplus. i

Siàunquelconquemomentvousrencontrezunevuedontleslimitesneluicorrespondent plus, vous pouvez essayer de la faire se redimensionner en lançant sa méthode void requestLayout()—ainsilecalculseferasurlavueetsurtouteslesautresvuesqui pourraientêtreinfluencéesparlesnouvellesdimensionsdelavue.

12.1.1.3. Récupérer les dimensions

int

get

Mea

su

De manière à récupérer les instructions de dimensions, vous pouvez utiliser

red

Width

()

 

int

get

Mea

su

red

Height

()

                                       pour la largeur et                                                              pour la hauteur, cependant

mea

sure(int,

int)

uniquement après qu’un appel àa été effectué, sinon ces valeurs n’ont pasencoreétéattribuées.Enfin,vouspouvezlesattribuervous-mêmesaveclaméthodevoid

set

Mea

su

red

Di

men

sion

(int

mea

su

red

Width,

int

mea

su

red

Height)

.

Cesinstructionsdoiventvoussemblerencoremystérieusespuisquevousnedevezpasdutout savoirquoiinsérer.Enfait,cesentierssont uncode.Eneffet,vouspouvezàpartirdececode déterminerunmodedefaçonnageetunetaille.

int

Mea

su

reS

Size

(int

mea

su

— Latailleserécupèreaveclafonctionstatique

reS

pec)

.

int

Mea

su

reS

Mode

(int

mea

— Le mode se récupère avec la fonction statique

su

reS

pec)

 

Mea

su

reS

PE

CI

FIED

                                                .S’ilvaut                                                               ,alorsleparentn’apasdonnéd’ins-

Mea

su

reS

pec.EXACTLY

Mea

su

reS

pec.AT_MOST

tructionparticulièresurlatailleàprendre.S’ilvaut,alorsla taille donnée est la taille exacte à adopter. S’il vaut, alors la tailledonnéeestlataillemaximalequepeutavoirlavue.

Parexemplepourobtenirlecodequipermetd’avoiruncubequifait10pixelsauplus,onpeut faire:

 

int

get

Width

()

int

ge

tHeight

()

De plus, il est possible de connaître la largeur finale d’une vue avecet sa hauteurfinaleavec.

int

get

Top

()

 

int

get

Bot

tom

Enfin,onpeutrécupérerlapositiond’unevueparrapportàsonparentàl’aidedesméthodes (position du haut de cette vue par rapport à son parent),

int

get

Left

()

 

int

ge

tRight

()

()(enbas),      (àgauche)et     (àdroite).C’estpourquoivous pouvezdemandertrèssimplementàn’importequellevuesesdimensionsenfaisant:

 

12.1.2. Le dessin

void

draw

C’estseulementunefoisleplacementeffectuéqu’onpeutdessinernotrevue(vousimaginezbien qu’avantAndroidnesaurapasoùdessiner).Ledessins’effectuedanslaméthode

(Can

vas

can

vas)

 

Can

vas

                                                      ,quineserapasnonplusàimplé                         passéenparamètreest

lasurfacesurlaquelleledessinseratracé.

12.1.2.1. Obsolescence régionale

Tout d’abord, une vue ne décide pas d’elle-même quand elle doit se dessiner, elle en reçoit l’ordre, soit par le Context, soit par le programmeur. Par exemple, le contexte indique à la racinequ’elledoitsedessineraulancementdel’application.Dèsqu’unevuereçoitcetordre,sa premièretâcheseradedéterminercequidoitêtredessinéparmilesélémentsquicomposentla vue.

void

in

va

li

date

(Rect

dirty)

void

in

va

li

date

(int

gauche,

int

haut,

int

droite,

int

bas)

Silavuecomporteunnouveaucomposantouqu’undesescomposantsvientd’êtremodifié,alors lavuedéclarequecesélémentssontdansunezonequ’ilfautredessiner,puisqueleurétatactuel necorrespondplusàl’anciendessindelavue.Lasurfaceàredessinerconsisteenunrectangle, le plus petit possible, qui inclut tous les éléments à redessiner, mais pas plus. Cette surface s’appellela dirty region.L’actiondedélimiterladirtyregions’appellel’invalidation (c’est pourquoi on appelle aussi la dirty region la région d’invalidation) et on peut la provoquer avec les méthodes(où dirty est le rectangle qui délimite ladirtyregion)ouavec gauche la limite gauche du rectangle, haut le plafond du rectangle, etc., les coordonnées étantexpriméesparrapportàlavue.Sivoussouhaitezquetoutelavueseredessine,utilisez

void

in

va

li

date

()

 

void

in

va

li

date

(0,

0,

la méthode                                               , qui est juste un alias utile de

lar

geur_de_la_vue,

hau

teur_de_la_vue)

.Enfin,évitezdetroplefairepuisquedessiner

estunprocessusexigeant.

Text

View

 

Text

View

Par exemple, quand on passe d’une            vide à une        avec du texte, la seule chosequichangeestlecaractère«i»quiapparaît,larégionlapluspetiteestdoncunrectangle quientouretoutle«i»,commelemontrelafiguresuivante.

 

Figure 12.2.–Laseulechosequichangeestlecaractère«i»quiapparaît

But

ton

Enrevanche,quandonaunnormaletqu’onappuiedessus,letextenechangepas,mais toutelacouleurdufondchange,commeàlafiguresuivante.Parconséquentlarégionlaplus petitequicontienttouslesélémentsnouveauxouquiauraientchangéenglobetoutl’arrière-plan etsubséquemmentenglobetoutelavue.

 

Figure 12.3.–Lacouleurdufondchange

Ainsi,enutilisantunrectangle,onpeuttrèsbiendemanderàunevuedeseredessinerdansson intégralitédecettemanière:

 

12.1.2.2. La propagation

Quandondemandeàunevuedesedessiner,ellelanceleprocessuspuistransmetlarequête à ses enfants si elle en a. Cependant, elle ne le transmet pas à tous ses enfants, seulement à ceux qui se trouvent dans sa région d’invalidation. Ainsi, le parent sera dessiné en premier, puislesenfantsleserontdansl’ordredanslequelilssontplacésdansl’arbrehiérarchique,mais uniquements’ilsdoiventêtreredessinés. i

Pourdemanderàunevuequ’elleseredessine,utilisezunedesméthodesinvalidatevues précédemment, pour qu’elle détermine sa région d’invalidité, se redessine puis propage l’instruction.

12.2. Méthode 1 : à partir d’une vue préexistante

Leprincipeiciseradedériverd’unwidgetoud’unlayoutquiestfourniparleSDKd’Android. Nousl’avonsdéjàfaitparlepassé,maisnousn’avionsmanipuléquelecomportementlogique delavue,paslecomportementvisuel.

De manière générale, quand on développe une vue, on fait en sorte d’implémenter les trois constructeursstandards.Petitrappelàcesujet:

 

void

mea

sure

(int

width

Mea

su

reS

pec,

int

De plus, on développe aussi les méthodes qui commencent par on. Ces méthodes sont des fonctionsdecallback etellessontappeléesdèsqu’uneméthodeaunomidentique(maissanson) est utilisée. Je vous ai par exemple parlé de

height

Mea

su

reS

pec)

 

void

on

Mea

sure

(int

width

Mea

su

reS

pec,

int

height

Mea

su

reS

pec)

,àchacunedesesexécutions,lafonctiondecallback est lancée. Vous voyez, c’est simple

commebonjour.

i

Vous trouverez à cette adresse   une liste intégrale des méthodes que vous pouvez implémenter.

Parexemple,j’aicrééunboutonquipermetdevisualiserplusieurscouleurs.Toutd’abord,j’ai déclaréuneressourcequicontientunelistedecouleurs:

 

Ty

pe

dAr

ray

int

get

Co

lor

(int

po

si

tion,

int

de

fault

Va

lue)

 

po

si

tion

de

fault

Va

lue

Ce type de ressources s’appelle un, c’est-à-dire un tableau qui peut contenir n’importequellesautresressources.Unefoiscetableaudésérialisé,jepeuxrécupérerleséléments qui le composent avec la méthode appropriée, dans notre cas, comme nous manipulons des couleurs,          ( étantlaposition del’élémentvouluetlavaleurrenvoyéesil’élémentn’estpastrouvé).

 

void

on

Layout

(boo

lean

chan

ged,

int

left,

int

top,

int

right,

int

bot

Jeredéfinis

tom)pourqu’àchaquefoisquelavueestredimensionnéejepuissechangerlatailleducarré quiaffichelescouleursdemanièreàcequ’ilsoittoujoursconformeaurestedubouton.

 

boo

lean

on

Tou

chEvent

(Mo

tio

nEvent

event)

int

ge

tAc

tion

()

 

Mo

tio

nEvent

Mo

tio

TION_DOWN

J’implémentepour qu’à chaque fois que l’utilisateur appuie sur le bouton la couleur qu’affiche le carré change. Le problème est que cetévènementselanceàchaquetoucher,etqu’untouchernecorrespondpasforcémentàun clic,maisaussiàn’importequellefoisoùjebougemondoigtsurlebouton,neserait-ceque d’un pixel. Ainsi, la couleur change constamment si vous avez le malheur de bouger le doigt quand vous restez appuyé sur le bouton. C’est pourquoi j’ai rajouté une condition pour que le dessin ne réagisse que quand on appuie sur le bouton, pas quand on bouge ou qu’on lève le doigt. Pour cela, j’ai utilisé la méthode      de        . Si la valeur retournéeest,c’estquel’évènementquiadéclenchélelancement delaméthodeestunclic.

 

void

on

Draw(Can

vas

can

vas)

Can

vas

Can

vas

Enfin,j’écrismapropreversiondepourdessinerlecarrédans sacouleuractuelle.L’objetcorrespondàlafoisàlatoilesurlaquelleonpeutdessiner etàl’outilquipermetdedessiner,alorsqu’unobjetPaintindiquejusteaucomment ilfautdessiner,maispasce qu’il faut dessiner.

 

i

Vousremarquerezqu’àlafindechaqueméthodedetypeon,jefaisappelàl’équivalentde lasuperclassedecetteméthode.C’esttoutsimplementparcequelessuperclasseseffectuent desactionspourlaclasseButtonquidoiventêtrefaitessouspeined’uncomportement incorrectdubouton.

Cequidonnelafiguresuivante.

 

Figure 12.4.–On a un petit carré en bas de notre bouton (écran de gauche) et dès qu’on appuiesurleboutonlecarréchangedecouleur(écrandedroite)

12.3. Méthode 2 : une vue composite

Spin

ner

But

ton

 

List

View

 

Au

to

Com

ple

te

Text

View

 

Edit

Text

List

View

Onpeuttrèsbiensecontenterd’avoirunevuequiconsisteenunassemblagedevuesquiexistent déjà.D’ailleursvousconnaissezdéjàaumoinsdeuxvuescomposites!Pensezà,c’est un avecune ,non?Et ,c’estunassocié àuneaussi!

View

Group

 

View

Group

Logiquement, cette vue sera un assemblage d’autres vues et par conséquent ne sera pas un widget—quinepeutpascontenird’autresvues—maisbienunlayout,elledevradoncdériver de            oud’unesous-classede        .

ToHtml

View

Jevaisvousmontrerunevuequipermetd’écriredutexteenHTMLetd’avoirlerésultaten tempsréel.J’aiappelé’expliquepaslecodeligneparlignepuisque vousconnaissezdéjàtouscesconcepts.

 

Cequidonne,unefoisintégré,lafiguresuivante.

 

Figure 12.5.–Lerenduducode

Maisj’auraistrèsbienpupasserparunfichierXMLaussi!Voicicommentj’auraispufaire:

 

on

Draw

 

on

Mea

sure

L’avantage par rapport aux deux autres méthodes, c’est que cette technique est très facile à mettre en place (pas de méthodes ou de à redéfinir) et puissante. En revanche,onabeaucoupmoinsdecontrôle.

12.4. Méthode 3 : créer une vue en partant de zéro

void

on

Mea

sure

(int

width

Mea

su

reS

pec,

Ilvousfautpenseràtoutici,puisquevotrevuedériveradirectementdeViewetquecetteclasse ne gère pas grand-chose. Ainsi, vous savez que par défaut une vue est un carré blanc de 100 pixelsdecôté,ilfaudradoncaumoinsredéfinir

int

height

Mea

su

reS

pec)

 

void

on

Draw

(Can

vas

can

vas)

                                                                    et                                                                . De plus, vous devez penser

auxdifférentsévènements(est-cequ’ilfautréagirautoucher,etsiouicomment?etàl’appui surunetouche?),auxattributsdevotrevue,auxconstructeurs,etc. Dansmonexemple,j’aidécidédefaireunéchiquier.

12.4.1. La construction programmatique

Toutd’abord,j’implémentetouslesconstructeursquimepermettrontd’instancierdesobjets depuislecode.Pourcela,jeredéfinisleconstructeurstandardetjedéveloppeunautreconstructeurquimepermetdedéterminerquellessontlescouleursquejeveuxattribuerpourlesdeux typesdecase.

 

12.4.2. La construction par inflation

J’exploitelesdeuxconstructeursdestinésàl’inflationpourpouvoirrécupérerlesattributsque j’ai pu passer en attributs. En effet, il m’est possible de définir mes propres attributs pour ma vue. Pour cela, il me faut créer des ressources de type attr dans un tableau d’attributs.

de

clare

-

sty

leable

Ce tableau est un nœud de type. J’attribue un nom à chaque élément quileurservirad’identifiant.Enfin,jepeuxdirepourchaqueattrqueltyped’informationsil contiendra.

Pourutilisercesattributsdanslelayout,ilfauttoutd’aborddéclarerutiliserun namespace,

commeonlefaitpourpouvoirutiliserlesattributsquiappartiennentàAndroid:xmlns:an

droid="http://sche

droid"

.

an

droid:

xmlns:an

droid

http://sche

droid

Cettedéclarationnouspermetd’utiliserlesattributsquicommencentpardansnotre layout,ellenouspermettradoncd’utilisernospropresattributsdelamêmemanière. Pourcela,onvasecontenterd’agird’unemanièresimilaireenremplaçantpar lenomvouludenotrenamespaceetpar notrepackageactuel.Dansmoncas,j’obtiens:

 

CequimedonneceXML:

 

Ilmesuffitmaintenantderécupérerlesattributscommenousl’avionsfaitprécédemment:

 

12.4.3. onMeasure

Lataillepardéfautde100pixelsestridiculeetneconviendrajamaisàunéchiquier.Jevais faireensorteque,sil’applicationmel’autorise,jepuisseexploiterlecarréleplusgrandpossible, etjevaisfaireensortequ’aupirenotrevueprenneaumoinslamoitiédel’écran.

Pourcela,j’aiécrituneméthodequicalculeladimensionlaplusgrandeentrelataillequeme demandedeprendrelelayoutetlataillequicorrespondàlamoitiédel’écran.Puisjecompare enlargeuretenhauteurquelleestlapluspetitetailleaccordée,etmonéchiquiers’accordeà cettetaille.

i

Ilexisteplusieursméthodespourcalculerlatailledel’écran.Demoncôté,j’aifaitensorte del’intercepterdepuislesressourcesaveclaméthodeDisplayMetricsgetDisplayMe trics().Jerécupèreensuitel’attributheightPixelspouravoirlahauteurdel’écran etwidthPixelspoursalargeur.

×

Toujours avoir dans son implémentation de onMeasure un appel à la méthode void setMeasuredDimension (int measuredWidth, int measuredHeight), sinon votre vuevousrenverrauneexception.

12.4.4. onDraw

Il ne reste plus qu’à dessiner notre échiquier! Ce n’est pas grave si vous ne comprenez pas l’algorithme,dumomentquevousavezcompristouteslesétapesquimepermettentd’afficher cetéchiquiertantvoulu.

 

Cequipeutdonnerlafiguresuivante.

 

Figure 12.6.–Lechoixdescouleursestdiscutable

 

— Lors de la déclaration de nos interfaces graphiques, la hiérarchie des vues que nous déclaronsauratoujoursunlayoutparentqu’Androidplacesansnousledire.

void

mea

sure(int

width

Mea

su

reS

pec,

int

height

Mea

su

reS

pec)

— Leplacementestl’opérationpendantlaquelleAndroidplaceralesvuesdansl’interface graphique.Ellesecaractériseparl’appeldelaméthode pourdéterminerlesdimensionsréellesdevotre

void

layout(int

bord_gauche,

int

pla

fond,

int

bord_droit,

int

plan

cher)

vue et ensuite de la méthode pourlaplaceràl’endroitdemandé.

— Toutes les vues que vous avez déclarées dans vos interfaces offrent la possibilité de connaitreleursdimensionsunefoisqu’ellesontétédessinéesàl’écran.

void

in

va

li

date

()

— Unevueneredessinequeleszonesquiontétémodifiées.Ceszonesdéfinissentcequ’on appellel’obsolescencerégionale.Ilestpossiblededemanderàunevuedeseforceràse redessinerparlebiaisdelaméthodeettoutessesdérivées.

— Vouspouvezcréerunenouvellevuepersonnaliséeàpartird’unevuepréexistanteque vousdécidezd’étendredansl’unedevosclassesJava.

Spin

ner

 

But

ton

— Vouspouvezcréerunenouvellevuepersonnaliséeàpartird’unassemblaged’autresvues préexistantescommeleferaitun quiestunassemblageentreun etune

List

View

.

— Vous pouvez créer une nouvelle vue personnalisée à partir d’une feuille blanche en dessinantdirectementsurlecanvasdevotrevue.


Troisième partie Vers des applications plus complexes

13.   Préambule : quelques concepts avancés

An

droid

Ma

ni

LeManifestestunfichierquevoustrouverezàlaracinedevotreprojetsouslenomd’ etquivouspermettradespécifierdifférentesoptionspourvosprojets,comme

lematérielnécessairepourlesfairefonctionner,certainsparamètresdesécuritéouencoredes informationsplusoumoinstrivialestellesquelenomdel’applicationainsiquesonicône.

Maiscen’estpastout,c’estaussilapremièreétapeàmaîtriserafindepouvoirinsérerplusieurs activitésauseind’unemêmeapplication,cequiseralafinalitédesdeuxprochainschapitres.

on

Create

Cechapitresechargeraaussidevousexpliquerplusendétailcommentmanipulerlecycled’une activité.Eneffet,pourl’instantnousavonstoujourstoutinsérédans,maisilexiste dessituationspourlesquellescetteattituden’estpasdutoutlameilleureàadopter.

13.1. Généralités sur le nœud <manifest>

CefichierestindispensablepourtouslesprojetsAndroid,c’estpourquoiilestcréépardéfaut. Sijecréeunnouveauprojet,voicileManifestquiestgénéré:

 

Voyonsunpetitpeudequoiils’agitici.

13.1.1. <manifest>

<ma

ni

fest>

an

droid

LaracineduManifestestunnœuddetype.Commepourlesvuesetlesautres ressources,oncommenceparmontrerqu’onutilisel’espacedenoms:

 

Puis,ondéclaredansquelpackagesetrouvenotreapplication:

 

an

droid:name=".Ma

ni

fes

tAc

ti

vity"

Ma

ni

fes

tAc

ti

vity

… afin de pouvoir utiliser directement les classes qui se situent dans ce package sans avoir à préciser à chaque fois qu’elles s’y situent. Par exemple, dans notre Manifest actuel, vous pouvez voir la ligne suivante :. Elle fait référence à l’activité principale de mon projet :. Cependant, si nous n’avions

pa

ckage="

pi

tre

Trois"

 

an

droid:name

pasprécisé                                                                 ,alorslenœud                                    auraitdûvaloir

an

droid:name="

pi

tre

ni

fes

tAc

ti

vity"

. Imaginez seulement que nous

ayonsàlefairepourchaqueactivitédenotreapplication…Celarisqueraitd’êtreviteusant. i

N’oubliezpasquelenomdepackagedoitêtreuniquesivousvoulezêtrepubliésurlePlay Store.Deplus,unefoisvotreapplicationdiffusée,nechangezpascenompuisqu’ilagira commeunidentifiantuniquepourvotreapplication.

<ma

ni

fest>

Toujours dans le nœud, il est ensuite possible d’indiquer quelle est la version actuelledulogiciel:

 

an

droid:ver

sion

Code

an

droid:ver

sion

Name

L’attributdoit être un nombre entier (positif et sans virgule) qui indiquequelleestlaversionactuelledel’application.Maisattention,ilnes’agitpasdunombre quiseramontréàl’utilisateur,justeceluiconsidéréparlePlayStore.Sivoussoumettezvotre application avec un code de version supérieur à celui de votre ancienne soumission, alors le PlayStoresauraquel’applicationaétémiseàjour.Enrevanche,le peut être n’importe quelle chaîne de caractères et sera montré à l’utilisateur. Rien ne vous empêchedoncdemettreandroid:versionName="Premièreversionalpha-0.01a"par exemple.

13.1.2. <uses-sdk>

Onutilisecenœuddemanièreàpouvoirfiltrerlespériphériquessurlesquelsl’applicationest censéefonctionnerenfonctiondeleurversiond’Android.Ainsi,ilvousestpossibled’indiquerla versionminimaledel’APIquedoitutiliserlepériphérique:

 

Ici,ilfaudralaversion2.1d’Android(API7)ousupérieurepourpouvoirutilisercetteapplication.

!

VotreapplicationneseraproposéesurleGooglePlayqu’àpartirdumomentoùl’utilisateur utilisecetteversiond’Androidouuneversionsupérieure.

an

droid:tar

getSdk

Ver

sion

Ilexisteaussiunattributquidésignenonpaslaversionminimale d’Android demandée, mais plutôt la version à partir de laquelle on pourra exploiter à fond l’application.Ainsi,vousavezpeut-êtreimplémentédesfonctionnalitésquinesontdisponibles qu’à partir de versions d’Android plus récentes que la version minimale renseignée avec an

droid:minSdk

Ver

sion

,toutenfaisantensortequel’applicationsoitfonctionnelleenutilisant

an

droid:minSdk

Ver

sion

uneversiond’Androidégaleousupérieureàcellepréciséedans.


an

droid:maxSdk

Ver

sion

Vouspouvezaussipréciserunelimitemaximaleàrespecteravecsi voussavezquevotreapplicationnefonctionnepassurlesplateformeslesplusrécentes,mais jenevousleconseillepas,essayezplutôtderendrevotreapplicationcompatibleavecleplus grandnombredeterminaux!

13.1.3. <uses-feature>

Étantdonnéqu’Androidestdestinéàunetrèsgrandevariétédeterminauxdifférents,ilfallait un moyen pour faire en sorte que les applications qui utilisent certains aspects hardware ne puissent être proposées que pour les téléphones qui possèdent ces capacités techniques. Par exemple,vousn’allezpasproposerunlogicielpourfairedesphotographiesàuntéléphonequi nepossèdepasd’appareilphoto(mêmesic’estrare)oudecapturesonorepourunetablettequi n’apasdemicrophone(cequiestdéjàmoinsrare).

Cenœudpeutprendretroisattributs,maisjen’enprésenteraiquedeux:

 

13.1.3.1. android :name

an

droid:name

Vous pouvez préciser le nom du matériel avec l’attribut. Par exemple, pour l’appareilphoto(etdonclacaméra),onmettra:

 

Cependant, il arrive qu’on ne cherche pas uniquement un composant particulier mais une fonctionnalitédececomposant;parexemplepourpermettreàl’applicationden’êtreutilisée quesurlespériphériquesquiontunappareilphotoavecautofocus,onutilisera:

 

13.1.3.2. android :required

Commecetattributn’acceptequ’unbooléen,ilnepeutprendrequedeuxvaleurs:

1.  true:cecomposantestindispensablepourl’utilisationdel’application.

2.  false:cecomposantn’estpasindispensable,maissaprésenceestrecommandée.

13.1.4. <supports-screens>

Celui-ci est très important, il vous permet de définir quels types d’écran supportent votre application.Cetattributseprésenteainsi:

 

smallS

creen

nor

malS

creen

 

lar

geS

creen

Siunécranestconsidérécommepetit,alorsilentreradanslacatégorie,s’ilest moyen,c’estun ,etlesgrandsécranssontdes .

i

L’API 9 a vu l’apparition de l’attribut <supports-screens android:xlargeS creens="boolean" />. Si cet attribut n’est pas défini, alors votre application sera lancéeavecunmodedecompatibilitéquiagrandiratouslesélémentsgraphiquesdevotre application,ésultatserapluslaid quesivousdéveloppiezuneinterfacegraphiquedédiée,maisaumoinsvotreapplication fonctionnera.

</supports-screens></uses-feature></uses-sdk></manifest>

13.2. Le nœud <application>

Lenœudleplusimportantpeut-êécritlesattributsquicaractérisentvotreapplication et en énumère les composants de votre application. Par défaut, votre application n’a qu’un composant,l’activitéprincipale.Maisvoyonsd’abordlesattributsdecenœud.

an

droid:icon

an

droid:icon="@dra

wable/ic_laun

cher"

Vouspouvezdéfinirl’icônedevotreapplicationavec,pourcelavousdevezfaire référenceàuneressourcedrawable:.

!

Ne confondez pas avec android:logo qui, lui, permet de changer l’icône uniquement dansl’ActionBar.

an

droid:la

bel

Ilexisteaussiunattributquipermetdedéfinirlenomdenotreapplication.

13.2.1. Les thèmes

Voussavezdéjàcommentappliquerunstyleàplusieursvuespourqu’ellesrespectentlesmêmes attributs. Et si nous voulions que toutes nos vues respectent un même style au sein d’une application?Quelestextesdetoutescesvuesrestentnoirsparexemple!Ceseraitcontraignant d’appliquer le style à chaque vue. C’est pourquoi il est possible d’appliquer un style à une application,auquelcasonl’appelleun thème.CetteopérationsedérouledansleManifest,il voussuffitd’insérerl’attribut:

 

VouspouvezaussiexploiterlesthèmespardéfautfournisparAndroid,parexemplepourque votreapplicationressembleàuneboîtededialogue:

Vousenretrouverezd’autressurladocumentation .

Laissez-moi maintenant vous parler de la notion de composants. Ce sont les éléments qui composerontvosprojets.Ilenexistecinqtypes,maisvousneconnaissezpourl’instantqueles activités,alorsjenevaispasvousembrouillerplusavecça.Sachezjustequevotreapplicationsera aufinalunensembledecomposantsquiinteragissent,entreeuxetaveclerestedusystème.

13.2.2. <activity>

Ce nœud permet de décrire toutes les activités contenues dans notre application. Comme je vousl’aidéjàdit,uneactivitécorrespondàunécrandevotreapplication,donc,sivousvoulez avoirplusieursécrans,ilvousfaudraplusieursactivités.

an

droid:name

Leseulattributvraimentindispensableiciest,quiindiquequelleestlaclasse quiimplémentel’activité.

×

android:namedéfinitaussiunidentifiantpourAndroidquipermetderepérercecomposantparmitous.Ainsi,nechangezpasl’attributandroid:named’uncomposantaucours d’unemiseàjour,sinonvousrisquezderencontrerdeseffetsdebordassezdésastreux.

an

droid:la

bel

an

droid:la

bel

 

<ap

pli

ca

tion>

Vous pouvez aussi préciser un nom pour chaque activité avec, c’est le mot qui s’affichera en haut de l’écran sur notre activité. Si vous ne le faites pas, c’est la String renseignéedansle dunœud quiserautilisée.

fil

ter>

Vouspouvezvoirunautrenœuddetype<intent-quiindiquecommentselancera cetteactivité.Pourl’instant,sachezjustequel’activitéquiseralancéedepuislemenuprincipal d’AndroidcontiendratoujoursdanssonManifestceslignes-ci:

 

Jevousdonneraibeaucoupplusdedétailsdansleprochainchapitre.

Vous pouvez aussi définir un thème pour une activité, comme nous l’avons fait pour une application.</activity>

13.3. Les permissions

Vous le savez sûrement, quand vous téléchargez une application sur le Play Store, on vous propose de regarder les autorisations que demande cette application avant de commencer le téléchargement(voirfiguresuivante).Parexemple,pouruneapplicationquivouspermetde retenirvotrenumérodecartebancaire,onpeutlégitimementseposerlaquestiondesavoirsi danssesautorisationssetrouve«Accèsàinternet».

 

Figure 13.1.–Onvousmontrelesautorisationsquedemandel’applicationavantdelatélécharger

Par défaut, aucune application ne peut exécuter d’opération qui puisse nuire aux autres applications,ausystèmed’exploitationouàl’utilisateur.Cependant,Androidestconstituéde manièreàcequelesapplicationspuissentpartager.C’estlerôledespermissions,ellespermettent delimiterl’accèsauxcomposantsdevosapplications.

13.3.1. Utiliser les permissions

AfindepouvoirutilisercertainesAPId’Android,commel’accèsàinternetdanslecasprécédent, vousdevezpréciserdansleManifestquevousutilisezlespermissions.Ainsi,l’utilisateurfinal estavertidecequevoussouhaitezfaire,c’estunemesuredeprotectionimportanteàlaquelle vousdevezvoussoumettre.

Voustrouverezsurcettepage  unelistedespermissionsquiexistentdéjà.

Ainsi,pourdemanderunaccèsàinternet,onindiqueralaligne:

 

13.3.2. Créer ses permissions

Ilestimportantquevotreapplicationpuisseelleaussipartagersescomposantspuisquec’est commeçaqu’ellesaitserendreindispensable. Unepermissiondoitêtredecetteforme-ci:

 

Où:

an

droid:name

per

mis

sion

—estlenomquiserautilisédansunuses-pourfaireréférence àcettepermission.Cenomdoitêtreunique.

an

droid:la

bel

—est le nom qui sera indiqué à l’utilisateur, faites-en donc un assez explicite.

an

droid:des

crip

tion

—est une description plus complète de cette permission que le

la

bel

.

an

droid:icon

—est assez explicite, il s’agit d’une icône qui est censée représenter la permission.Cetattributestheureusementfacultatif.

an

droid:pro

tec

tion

Le

vel

—indiqueledegréderisqueducomposantliéàcettepermission.Ilexisteprincipalementtroisvaleurs:

nor

mal

—si le composant est sûr et ne risque pas de dégrader le comportement du téléphone;

dan

ge

rous

—si le composant a accès à des données sensibles ou peut dégrader le fonctionnementdupériphérique;

si

gna

ture

—pourn’autoriserl’utilisationducomposantqueparlesproduitsdumême auteur (concrètement, pour qu’une application se lance sur votre terminal ou sur l’émulateur, il faut que votre application soit « approuvée » par Android. Pour ce faire, un certificat est généré — même si vous ne le demandez pas, l’ADT s’en occupeautomatiquement—etilfautquelescertificatsdesdeuxapplicationssoient identiquespourquelapermissionsoitacceptée).

13.4. Gérer correctement le cycle des activités

Commenousl’avonsvu,quandunutilisateurmanipulevotreapplication,laquittepourune autre ou y revient, elle traverse plusieurs états symbolisés par le cycle de vie des activités, schématiséàlafiguresuivante.

 

Figure 13.2.–Lecycledevied’uneactivité

on

Create

La transition entre chaque étape implique que votre application appelle une méthode. Cette méthode partage le même nom que l’état traversé, par exemple à la création est appelée la méthode.

Cesméthodesnesontquedesétatsdetransitiontrèséphémèresentrelestroisgrandsétatsdont nousavonsdéjàdiscuté:lapériode active peutêtreinterrompueparlapériode suspendue, quielleaussipeutêtreinterrompueparlapériode arrêtée. i

Vouslecomprendreztrèsvite,l’entréedanschaqueétatestsymboliséeparuneméthode etlasortiedechaqueétatestsymboliséeparuneautreméthode.Cesdeuxméthodessont complémentaires:cequiestinitialisédanslapremièreméthodedoitêtrestoppédansla deuxième,etcepresquetoujours.

13.4.1. Sous les feux de la rampe : période suspendue

on

Re

sume()

 

on

Pause()

Cettepériodedébuteavec      etsetermineavec         .Onentredanslapériode suspenduedèsquevotreactivitén’estplusquepartiellementvisible,commequandelleestvoilée paruneboîtededialogue.Commecettepériodearrivefréquemment,ilfautquelecontenude cesdeuxméthodess’exécuterapidementetnécessitepeudeprocesseur.

13.4.1.1. onPause()

on

Pause()

on

Pause()

on

Pause()

On utilise la méthodepour arrêter des animations, libérer des ressources telles que le GPS ou la caméra, arrêter des tâches en arrière-plan et de manière générale stopper touteactivitéquipourraitsolliciterleprocesseur.Attention,onévitedesauvegarderdansla basededonnéesauseinde,carc’estuneactionquiprendbeaucoupdetempsàse faire,etilvautmieuxques’exécuterapidementpourfluidifierlamanipulationpar l’utilisateur.Demanièregénérale,iln’estpasnécessairedesauvegarderdesdonnéesdanscette méthode,puisqueAndroidconserveunecopiefonctionnelledel’activité,etqu’auretourelle serarestauréetellequelle.

13.4.1.2. onResume()

on

Pause()

on

Create(Bundle)

Cette méthode est exécutée à chaque fois que notre activité retourne au premier plan, mais aussi à chaque lancement, c’est pourquoi on l’utilise pour initialiser les ressources qui seront coupéesdansle.Parexemple,dansvotreapplicationdelocalisationGPS,vousallez initialiserleGPSàlacréationdel’activité,maispasdansle,plutôtdansle

on

Re

sume()

 

on

Pause()

                                            puisquevousallezlecouperàchaquefoisquevouspassezdansle                             .

13.4.2. Convoquer le plan et l’arrière-plan : période arrêtée

Cettefois-ci,votreactivitén’estplusvisibledutout,maisellen’estpasarrêtéenonplus.C’est lecassil’utilisateurpassedevotreapplicationàuneautre(parexemples’ilretournesurl’écran d’accueil),alorsl’activitéencourssetrouverastoppéeetonreprendraaveccetteactivitédèsque l’utilisateurretourneradansl’application.Ilestaussiprobablequedansvotreapplicationvous ayezplusd’uneactivité,etpasserd’uneactivitéàl’autreimpliquequel’anciennes’arrête.

onS

top()

 

on

Pause()

 

on

Res

tart()

on

Re

sume()

 

onS

tart()

onS

top()

on

Create(Bundle)

Cetétatestdélimitépar (toujoursprécédéde )et (toujours suivide ,puis )).Cependant,ilsepeutquel’applicationsoittuéepar Androids’ilabesoindemémoire,auquelcas,après,l’applicationestarrêtéeet,quand elleseraredémarrée,onreprendraà.

onS

tart()

onS

top()

 

on

Re

sume()

onS

top()

Là,enrevanche,vousdevriezsauvegarderlesélémentsdansvotrebasededonnéesdansonS top()etlesrestaurerlorsquec’estnécessaire(danssilarestaurationdoitsefaire au démarrage et après un ou dans si la restauration ne doit se faire qu’aprèsun).

13.4.3. De la naissance à la mort

13.4.3.1. onCreate(Bundle)

Première méthode qui est lancée au démarrage de l’activité, c’est l’endroit privilégié pour initialiserl’interfacegraphique,pourdémarrerlestâchesd’arrière-planquis’exécuterontpendant touteladuréedeviedel’activité,pourrécupérerdesélémentsdelabasededonnées,etc.

pu

blic

void

fi

nish

()

 

on

Des

troy()

Ilsepeuttrèsbienquevousutilisiezuneactivitéuniquementpourfairedescalculsetprendre desdécisionsentrel’exécutiondedeuxactivités,auquelcasvouspouvezfaireappelàlaméthode pourpasserdirectementàlaméthode            ,quisymbolise

fi

nish()

la mort de l’activité. Notez bien qu’il s’agit du seul cas où il est recommandé d’utiliser la méthode(c’est-à-direqu’onévited’ajouterunboutonpourarrêtersonapplication parexemple).

13.4.3.2. onDestroy()

on

Des

troy

Ilexistetroisraisonspourlesquellesvotreapplicationpeutatteindrelaméthode, c’est-à-direpourlesquellesonvaterminernotreapplication:

— Commejel’aidéjàexpliqué,ilpeutarriverqueletéléphonemanquedemémoireetqu’il aitbesoind’arrêtervotreapplicationpourenrécupérer.

Ar

rière

— Si l’utilisateur presse le boutonet que l’activité actuelle ne permet pas de retourneràl’activitéprécédente(ous’iln’yenapas!),alorsonvaquitterl’application.

pu

blic

void

fi

nish()

Ar

rière

— Enfin, si vous faites appel à la méthode— mais on évite de l’utiliserengénéral—,ilvautmieuxlaisserl’utilisateurappuyersurlebouton, parcequ’Androidestconçupourgérerlecycledesactivitéstoutseul(c’estd’ailleursla raisonpourlaquelleilfautéviterd’utiliserdestask killers).

on

Create(Bundle)

on

Des

troy()

on

Pause()

 

onS

top()

Commevouslesavez,c’estdansquedoiventêtreeffectuéeslesdifférentes initialisationsainsiquelestâchesd’arrière-planqu’onsouhaitevoirs’exécuterpendanttoute l’application.Normalement,quandl’applicationarriveau,elleestdéjàpasséepar et          ,donclamajoritédestâchesdefondaurontétéarrêtées;cependant,

on

Create(Bundle)

 

on

Des

troy()

s’ils’agitd’unetâchequidevraits’exécuterpendanttoutelaviedel’activité—quiauraété démarréedans       —,alorsc’estdans          qu’ilfaudral’arrêter.

on

Pause()

 

onS

top()

fi

nish()

on

Des

troy()

 

on

Des

troy()

fi

nish()

 

pu

blic

boo

lean

is

Fi

ni

shing()

Android passera d’abord par et dans tous les cas, à l’exception de l’éventualité où vous appeleriez la méthode! Si c’est le cas, on passe directement au .Heureusement,ilvousestpossibledesavoirsile aétéappelé suiteàun aveclaméthode .

!

Si à un moment quelconque votre application lance une exception que vous ne catchez pas,alorsl’applicationseradétruitesanspasserparleonDestroy(),c’estpourquoicette méthoden’estpasunendroitprivilégiépoursauvegarderdesdonnées.

13.4.4. L’échange équivalent

Ar

rière

on

Create(Bundle)

Quandvotreapplicationestquittéedemanièrenormale,parexemplesil’utilisateurpressele boutonouqu’elleestencoreouverteetquel’utilisateurnel’aplusconsultéedepuis longtemps,alorsAndroidnegardepasenmémoiredetracesdevosactivités,puisquel’application s’estarrêtéecorrectement.Enrevanche,siAndroidadûtuerleprocessus,alorsilvagarderen mémoireunetracedevosactivitésafindepouvoirlesrestaurertellesquelles.Ainsi,auprochain lancementde l’application, le paramètre de type Bundle de la méthode serapeupléd’informationsenregistréessurl’étatdesvuesdel’interfacegraphique.

pro

tec

ted

void

Maisilpeutarriverquevousayezbesoinderetenird’autresinformationsqui,elles,nesontpas sauvegardées par défaut. Heureusement, il existe une méthode qui est appelée à chaque fois qu’ilyadeschancespourquel’activitésoittuée.Cetteméthodes’appelle

on

Sa

veIns

tan

ceS

tate(Bundle

outS

tate)

.

Un objet de type Bundle  est l’équivalent d’une table de hachage qui à une chaîne de caractèresassocieunélément,maisseulementpourcertainstypesprécis.Vouspouvezvoirdans la documentation tous les types qu’il est possible d’insérer. Par exemple, on peut insérer un entieretlerécupéreràl’aidede:

 

Onnepeutpasmettren’importequelobjetdansunBundle,uniquementdesobjetssérialisables. La sérialisation est le procédé qui convertit un objet en un format qui peut être stocké (par exempledansunfichieroutransmissurunréseau)etensuitereconstituédemanièreparfaite. Vousfaiteslerapprochementaveclasérialisationd’unevueenXML,n’est-cepas?

EncequiconcerneAndroid,onn’utilisepaslasérialisationstandarddeJava,avecl’interface

ria

li

zable

,,quandnousessayonsdefaire

communiquerdescomposants,ilfautquel’opérationsefassedemanièrerapide.C’estpourquoi onutiliseunsystèmedifférentquenousaborderonsendétaildansleprochainchapitre.

on

Sa

veIns

tan

ceS

tate(Bundle)

su

Sa

veIns

tan

ceS

tate(Bundle)

Cependant,l’implémentationpardéfautdenesauvegarde pastouteslesvues,justecellesquipossèdentunidentifiantainsiquelavuequialefocus,alors n’oubliezpasdefaireappelàpourvoussimplifierla vie.

on

Create(Bundle)

Parlasuite,cetobjetBundleserapasséà,maisvouspouvezaussichoisir

on

Res

to

reIns

tan

ceS

tate(Bundle)

 

onS

tart()

deredéfinirlaméthode          ,quiestappeléeaprès etquirecevralemêmeobjetBundle.

i

L’implémentationpardéfautdeonRestoreInstanceState(Bundle)restaurelesvues sauvegardéesparl’implémentationpardéfautdeonSaveInstanceState().

Lafiguresuivanteestunschémaquivouspermettrademieuxcomprendretouscesimbroglios.

 

Figure 13.3.–Lecycledesauvegardedel’étatd’uneactivité

13.5. Gérer le changement de configuration

Il se peut que la configuration de votre utilisateur change pendant qu’il utilise son terminal. Vous allez dire que je suis fou, mais un changement de configuration correspond simplement à ce qui pourrait contribuer à un changement d’interface graphique. Vous vous rappelez les quantificateurs?Ehbien,sil’undecesquantificateurschange,alorsonditquelaconfiguration change.

Etçavousestdéjàarrivé,j’ensuissûr.Réfléchissez!Sil’utilisateurpassedepaysageàportrait dansl’undenosanciensprojets,alorsilchangedeconfigurationetparconséquentd’interface graphique.

Pardéfaut,dèsqu’unchangementquipourraitchangerlesressourcesutiliséesparuneapplicationseproduit,Androiddétruittoutsimplementlaoulesactivitéspourlesrecréerensuite.

Heureusement pour vous, Android va retenir les informations des widgets qui possèdent un identifiant.Dansuneapplicationtrèssimple,onvacréerunlayoutpardéfaut:

 

Edit

Text

Seulundecespossèdeunidentifiant.Ensuite,onfaitunlayoutpresquesimilaire, maisavecunquantificateurpourqu’ilnes’affichequ’enmodepaysage:

 

Edit

Text

 

Edit

Text

Remarquezbienquel’identifiantdel’  estpasséàl’      dubas.Ainsi,quandvous lancezvotreapplication,écrivezdutextedanslesdeuxchamps,commeàlafiguresuivante.

 

Figure 13.4.–Écrivezdutextedanslesdeuxchamps

Puis tournez votre terminal (avant qu’un petit malin ne casse son ordinateur en le mettant sur le côté : pour faire pivoter l’émulateur, c’est CTRL + F12 ou F11 ) et admirez le résultat, identiqueàlafiguresuivante.

 

Figure 13.5.–Ilyaperted’information!

Vousvoyezbienquelewidgetquiavaitunidentifiantaconservésontexte,maispasl’autre! Celaprouvebienqu’ilpeutyavoirperted’informationdèsqu’unchangementdeconfiguration seproduit.

on

Sa

veIns

tan

ceS

tate()

Bienentendu,danslecasdeswidgets,leproblèmeestviterésolupuisqu’ilsuffitdeleurajouterun identifiant,maisilexistedesinformationsàretenirendehorsdeswidgets.Alors,commentgérer cesproblèmes-là?CommepardéfautAndroidvadétruirepuisrecréerlesactivités,vouspouvez trèsbientoutenregistrerdanslaméthode,puistoutrestaurerdans

on

Create(Bundle)

 

on

Res

to

reIns

tan

ceS

tate()

                                                    ou                                                             . Mais il existe un problème! Vous ne

pouvezpasserquelesobjetssérialisablesdansunBundle.Alorscommentfaire?

Ilexistetroisfaçonsdefaire:

— Utiliseruneméthodealternativepourretenirvosobjets,quiestspécifiqueauxchangementsdeconfiguration.

— Gérervous-mêmesleschangementsdeconfiguration,auquelcasAndroidnes’enchargera plus.Etcommecettetechniqueestunpeurisquée,jenevaispasvouslaprésenter.

— Bloquerlechangementderessources.

13.5.0.1. Retenir l’état de l’activité

pu

blic

Donc,leproblèmeavecBundle,c’estqu’ilnepeutpascontenirdegrosobjetsetqu’enplusla sérialisationetladésérialisationsontdesprocessuslents,alorsquenoussouhaiterionsquela transitionentredeuxconfigurationssoitfluide.C’estpourquoinousallonsfaireappelàuneautre méthodequiestappeléecettefoisuniquementencasdechangementdeconfiguration:

Ob

ject

on

Re

tain

Non

Con

fi

gu

ra

tio

nIns

tance()

. L’objet retourné peut être de n’importe

quelordre,vouspouvezmêmeretournerdirectementuneinstancedel’activitésivouslesouhaitez (maisbon,nelefaitespas).

on

Re

tain

Non

Con

fi

gu

ra

tio

nIns

tance()

 

onS

top()

Notezparailleursque                                                                                    estappeléeaprès

on

Des

troy()

Adap

ter

maisavantetquevousferiezmieuxdenepasconserverdesobjetsquidépendent delaconfiguration(parexempledeschaînesdecaractèresquichangentenfonctiondelalangue) oudesobjetsquisontliésàl’activité(unparexemple).

Ainsi,unedesfaçonsdeprocéderestdecréeruneclassespécialementdédiéeàladétentionde cesinformations:

 

on

Create(Bundle)

Enfin,ilestpossiblederécupérercetobjetdansleàl’aidedelaméthode

pu

blic

Ob

ject

get

Last

Non

Con

fi

gu

ra

tio

nIns

tance()

:

 

13.5.0.2. Empêcher le changement de ressources

Detoutefaçon,ilarriveparfoisqu’uneapplicationn’ lire un livre, il vaut mieux rester toujours en orientation portrait par exemple, de même il est plus agréable de regarder un film en mode paysage. L’idée ici est donc de conserver des fichiersderessourcesspécifiquesàuneconfiguration,mêmesicelleduterminalchangeencours d’utilisation.

Pour ce faire, c’est très simple, il suffit de rajouter dans le nœud des composants concernés leslignesandroid:screenOrientation="portrait"pourbloquerenmodeportraitouan droid:screenOrientation="landscape",leproblème, c’est qu’Android va quand même détruire l’activité pour la recréer si on laisse ça comme ça,

an

droid:config

Changes="orien

ta

tion"

c’estpourquoionvaluidirequ’ongèrenous-mêmesleschangementsd’orientationenajoutant lalignedanslesnœudsconcernés:

 

Voilà,maintenantvousaurezbeautournerleterminaldanstouslessens,l’applicationrestera toujoursorientéedelamêmemanière.

 

— LefichierManifestestindispensableàtouslesprojetsAndroid.C’estluiquidéclarera touteuneséried’informationssurvotreapplication.

<ap

pli

ca

tion>

— Lenœudlisteralesdifférentscomposantsdevotreapplicationainsique lesservicesqu’ilsoffrent.

per

mis

sion

per

mis

sion

— Vouspouvezsignalerquevousutiliserezdespermissionsparl’élémentusesouquevousencréezparl’élément.

— Comprendre le cycle de vie d’une activité est essentiel pour construire des activités robustesetergonomiques.

— Lesterminauxpeuventsetenirenmodepaysageouenmodeportrait.Vousvousdevezde gérerunminimumcechangementdeconfigurationpuisqu’aubasculementdel’appareil, votre système reconstruira toute votre interface et perdra par conséquent les données quel’utilisateurauraitpusaisir.


14.   La communication entre composants

C’esttrèsbientoutça,maisonnesaittoujourspascommentlanceruneactivitédepuisune autre activité. C’est ce que nous allons voir dans ce chapitre, et même un peu plus. On va apprendreàmanipulerunmécanismepuissantquipermetdefaireexécutercertainesactionset defairecirculerdesmessagesentreapplicationsouàl’intérieurd’unemêmeapplication.Ainsi, chaqueapplicationestcenséevivredansuncompartimentcloisonnépournepasdérangerle système quand elle s’exécute et surtout quand elle plante. À l’aide de ces liens qui lient les compartiments,Androiddevientunvraipuzzledontchaquepièceapporteunefonctionnalité quipourraitfournirsonaideàuneautrepièce,ouaucontrairequiauraitbesoindel’aided’une autrepièce.

in

tents

Lesagentsquisontchargésdecemécanismed’échanges’appellentles.Parexemple,si l’utilisateurcliquesurunnumérodetéléphonedansvotreapplication,peut-êtresouhaiteriez-vous queletéléphoneappellelenumérodemandé.Avecunintent,vousallezdireàtoutlesystème quevousavezunnuméroqu’ilfautappeler,etc’estlesystèmequiferaensortedetrouverles écanismeesttellementimportantqu’Android lui-mêmel’utilisemassivementeninterne.

14.1. Aspect technique

Unintentestenfaitunobjetquicontientplusieurschamps,représentésàlafiguresuivante.

 

Figure 14.1.–Remarquezquelechamp«Données»déterminelechamp«Type»etquece n’estpasréciproque

Lafaçondontsontrenseignésceschampsdéterminelanatureainsiquelesobjectifsdel’intent. Ainsi,pourqu’unintentsoitdit«explicite»,ilsuffitquesonchampcomposantsoitrenseigné. Ce champ permet de définir le destinataire de l’intent, celui qui devra le gérer. Ce champ est constitué de deux informations : le package où se situe le composant, ainsi que le nom ducomposant.Ainsi,quandl’intentseraexécuté,Androidpourraretrouverlecomposantde destinationdemanièreprécise.

Àl’opposédesintentsexplicitessetrouventlesintents«implicites».Danscecasdefigure,on neconnaîtpasdemanièrepréciseledestinatairedel’intent,c’estpourquoionvas’appliquerà renseignerd’autreschampspourlaisserAndroiddéterminerquiestcapablederéceptionnercet intent.Ilfautaumoinsfournirdeuxinformationsessentielles:

— Uneaction:cequ’ondésirequeledestinatairefasse.

— Unensemblededonnées:surquellesdonnéesledestinatairedoiteffectuersonaction. Ilexisteaussid’autresinformations,pasforcémentobligatoires,maisquiontaussileurutilité proprelemomentvenu:

— Lacatégorie:permetd’apporterdesinformationssupplémentairessurl’actionàexécuter etletypedecomposantquidevragérerl’intent.

— Letype:pourindiquerquelestletypedesdonnéesincluses.Normalementcetypeest contenudans les données, mais en précisant cet attribut vous pouvezdésactiver cette vérificationautomatiqueetimposeruntypeparticulier.

— Les extras : pour ajouter du contenu à vos intents afin de les faire circuler entre les composants.

— Lesflags:permettentdemodifierlecomportementdel’intent.

14.1.1. Injecter des données dans un intent

14.1.1.1. Types standards

pu

tEx

tra(String

key,

X

va

lue)

key

va

lue

Nous avons vu à l’instant que les intents avaient un champ « extra » qui leur permet de contenirdesdonnéesàvéhiculerentrelesapplications.Unextraestenfaitunecléàlaquelle onassocieunevaleur.Pourinsérerunextra,c’estfacile,ilsuffitd’utiliserlaméthodeIntent avec          laclédel’extraet           lavaleurassociée.Vous

voyezquej’aimisunXpourindiquerletypedelavaleur—cen’estpassyntaxiquementexact, je le sais. Je l’utilise juste pour indiquer qu’on peut y mettre un peu n’importe quel type de base,parexempleint,Stringoudouble[].

Bundle

ge

tEx

Puisvouspouvezrécuperertouslesextrasd’unintentàl’aidedelaméthode tras(),auquelcasvoscouplesclé-valeurssontcontenusdansleBundle.Vouspouvezencore récupérerunextraprécisàl’aidedesacléetdesontypeenutilisantlaméthodeXget{X}Ex

tra(String

key,

X

de

fault

Va

lue)

X

de

fault

Va

lue

                                                                                                , étant le type de l’extra et                                   la valeur

float[]

get

Floa

tAr

rayEx

tra(String

quiseraretournéesilaclépasséenecorrespondàaucunextradel’intent.Enrevanche,pourles typesunpeupluscomplexestelsquelestableaux,onnepeutpréciserdevaleurpardéfaut,par conséquentondevraparexempleutiliserlaméthode key)pouruntableaudefloat.

Enrèglegénérale,laclédel’extracommenceparlepackageduquelprovientl’intent.

 

Intent

pu

tEx

tras(Bundle

ex

tras)

Intent

Intent

pu

tEx

tras(Intent

ex

tras)

IlestpossiblederajouterununiqueBundleenextraaveclaméthode etun unique         aveclaméthode     .

14.1.1.2. Les parcelables

Par

ce

lable

Par

ce

lable

Par

cel

Par

cel

Cependant,Bundlenepeutpasprendretouslesobjets,commejevousl’aiexpliquéprécédemment,ilfautqu’ilssoientsé,danslecasd’Android,onconsidèrequ’unobjetest sérialisableàpartirdumomentoùilimplémentecorrectementl’interface     .Si on devait entrer dans les détails, sachez qu’unest un objet qui sera transmis à un    , et que l’objectif des est de transmettre des messages entre différents processusdusystème.

Par

ce

lable

Pourimplémenterl’interface,ilfautredéfinirdeuxméthodes:

int

des

cri

be

Con

tents()

Par

ce

lable

Fi

le

Des

crip

tor

Fi

le

Des

crip

tor

—,quipermetdedéfinirsivousavezdesparamètresspéciaux dansvotre.Encemoisdejuillet2012(àl’heureoùj’écrisceslignes),les seulsobjetsspéciauxàconsidérersontles  .Ainsi,sivotreobjetne contientpasd’objetdetype,vouspouvezrenvoyer0,sinonrenvoyez

Par

ce

lable.CONTENT_FILE_DES

CRIP

TOR

.

void

wri

te

To

Par

cel(Par

cel

dest,

int

flags)

dest

Par

cel

Par

cel

—, avec le dans lequel nousallonsinsérerlesattributsdenotreobjetetflagsunentierquivautlaplupartdu temps0.C’estdanscetteclassequenousallonsécriredanslequitransmettrale message.

!

LesattributssontàinsérerdansleParceldansl’ordredanslequelilssontdéclarésdans laclasse!

Sionprendl’exemplesimpled’uncontactdansunrépertoiretéléphonique:

 

Par

cel

Tousnosattributssontdésormaisdansle,onpeuttransmettrenotreobjet.

Par

ce

C’est presque fini, cependant, il nous faut encore ajouter un champ statique de type

tor

etquis’appelleraimpérativement«CREATOR»,sinonnousserionsincapables

Par

cel

dereconstruireunobjetquiestpasséparun:

 

pu

tEx

tra

get

Par

ce

la

bleEx

tra

Enfin,commen’importequelautreobjet,onpeutl’ajouterdansunintentaveceton peutlerécupéreravec.

 

14.2. Les intents explicites

Créerunintentexpliciteesttrèssimplepuisqu’ilsuffitdedonnerunContextquiappartienne aupackageoùsetrouvelaclassededestination:

 

Parexemple,silaclassededestinationappartientaupackageduContextactuel:

 

Intent

set

Class(Context

pa

cka

ge

Con

À noter qu’on aurait aussi pu utiliser la méthode

text,

Class<?>

cls)

 

pa

cka

ge

Con

text

                                                          avec                                               unContextquiappartientaumêmepackage

quelecomposantdedestinationetclslenomdelaclassequihébergecetteactivité. Ilexisteensuitedeuxfaçonsdelancerl’intent,selonqu’onveuillequelecomposantdedestination nousrenvoieuneréponseoupas.

14.2.1. Sans retour

void

star

tAc

ti

vity

(Intent

intent)

on

Create

Sivousnevousattendezpasàcequelanouvelleactivitévousrenvoieunrésultat,alorsvous pouvezl’appelertrèsnaturellementavecdansvotre activité.Lanouvelleactivitéseraindépendantedel’actuelle.Elleentreprendrauncycled’activité normal,c’est-à-direencommençantparun.

Voiciunexempletoutsimple:dansunepremièreactivité,vousallezmettreunboutonetvous allezfaireensortequ’appuyersurceboutonlanceunesecondeactivité:

 

Lasecondeactiviténeferariendeparticulier,sicen’estafficherunlayoutdifférent:

 

Enfin,n’oubliezpasdepréciserdansleManifestquevousavezdésormaisdeuxactivitésausein devotreapplication:

 

Ainsi,dèsqu’oncliquesurleboutondelapremièreactivité,onpassedirectementàlaseconde activité,commelemontrelafiguresuivante.

 

Figure 14.2.–Encliquantsurleboutondelapremièreactivité,onpasseàlaseconde

14.2.2. Avec retour

void

star

tAc

ti

vi

ty

For

Re

sult(Intent

Cettefois,onveutqu’auretourdel’activitéquivientd’êtreappeléecettedernièrenousrenvoie unpetitfeedback.Pourcela,onutiliseralaméthode

intent,

int

re

quest

Code)

 

re

quest

Code

                                                                        , avec                                   un code passé qui permet d’identifier de

manièreuniqueunintent.

!

Cecodedoitêtresupérieurouégalà0,sinonAndroidconsidéreraquevousn’avezpas demandéderésultat.

void

onAc

ti

vi

ty

Re

sult(int

re

quest

Code,

int

re

sult

Code,

Intent

Quand l’activité appelée s’arrêtera, la première méthode de callback appelée dans l’activité précédente sera

re

quest

Code

 

star

tAc

ti

vi

data).Onretrouve                                      ,quiseralemêmecodequeceluipassédansle

ty

For

Re

sult

etquipermetderepérerquelintentaprovoquél’appeldel’activitédontlecycle

re

sult

Code

Ac

ti

SULT_OK

Ac

ti

SULT_CAN

CE

LED

vientdes’interrompre.estquantàluiuncoderenvoyéparl’activitéquiindique comment elle s’est terminée (typiquementsi l’activité s’est terminée normalement,ous’ilyaeuunproblèmeouqu’aucuncodede retourn’aétéprécisé).Enfin,intentestunintentquicontientéventuellementdesdonnées.

i

Pardéfaut,lecoderenvoyéparuneactivitéestActivity.RESULT_CANCELEDdefaçon que,sil’utilisateurutiliselebouton Retour avantquel’activitéaitfinides’exécuter,vous puissiezsavoirquelerésultatfournineserapasadaptéàvosbesoins.

void

se

tRe

sult(int

Danslasecondeactivité,vouspouvezdéfinirunrésultataveclaméthode

re

sult

Code,

Intent

data)

,cesparamètresétantidentiquesàceuxdécritsci-dessus.

re

quest

Code

 

void

star

tAc

ti

vi

ty

For

Re

sult(Intent

intent,

int

re

Ainsi,l’attribut                                de

quest

Code)

 

re

quest

Code

                                   sera similaire au                                    que nous fournira la méthode de callback void

onAc

ti

vi

ty

Re

sult(int

re

quest

Code,

int

re

sult

Code,

Intent

data)

, de manière à pouvoiridentifierquelintentestàl’originedeceretour.

Mai

nAc

ti

vity

Lecodedecenouvelexempleserapresquesimilaireàceluidel’exempleprécédent,saufque cettefoislasecondeactivitéproposeraàl’utilisateurdecliquersurdeuxboutons.Cliquersur undecesboutonsretourneraàl’activitéprécédenteenluiindiquantlequeldesdeuxboutonsa étépressé.Ainsi,ressembledésormaisà:

 

Alorsquelasecondeactivitédevient:

 

Etvoilà,dèsquevouscliquezsurundesboutons,lapremièreactivitévalancerunToastqui afficheraquelboutonaétépressé,commelemontrelafiguresuivante.

 

Figure 14.3.–UnToastaffichequelboutonaétépressé

14.3. Les intents implicites

Ici,onferaensorted’envoyerunerequêteàundestinataire,sanssavoirquiilest,etd’ailleurs ons’enfichetantqueletravailqu’onluidemandedefaireesteffectué.Ainsi,lesapplications destinatairessontsoitfourniesparAndroid,soitpard’autresapplicationstéléchargéessurle PlayStoreparexemple.

14.3.1. Les données

14.3.1.1. L’URI

Lapremièrechosequ’onvaétudier,c’estlesdonnées,parcequ’ellessontorganiséesselonune certainesyntaxequ’ilvousfautconnaître.Enfait,ellessontformatéesàl’aidedesURI.UnURI estunechaînedecaractèresquipermetd’identifierunendroit.Parexemplesurinternet,oudans lecasd’Androidsurlepériphériqueouuneressource.Afind’étudierlesURI,onvafairel’analogie aveclesadressesURLquinouspermettentd’accéderàdessitesinternet.Eneffet,unpeuàla manièred’unserveur,nosfournisseursdecontenuvontrépondreenfonctiondel’URIfournie.

te

du

rum/an

Deplus,laformegénéraled’uneURIrappellefortementlesURL.Prenonsl’exempleduSitedu Zéro avec une URL inventée :.

Onidentifieplusieursparties:

— http://

te

du

/fo

rum/an

LesURIsecomportentd’unemanièreunpeusimilaire.Lasyntaxed’unURIpeutêtreanalysée delamanièresuivante(lespartiesentreaccolades{}sontoptionnelles):

 

— Leschémadécritquelleestlanaturedel’information.S’ils’agitd’unnumérodetéléphone, alorsleschémaseratel,s’ils’agitd’unsiteinternet,alorsleschémaserahttp,etc.

in

for

ma

tion

— L’estladonnéeentantquetelle.Cetteinformationrespecteelleaussiune syntaxe,maisquidépendduschémacettefois-ci.Ainsi,pourunnumérodetéléphone,vous pouvezvouscontenterd’insérerlenumérotel:0606060606,maispourdescoordonnées GPSilfaudraséparerlalatitudedelalongitudeàl’aided’unevirgulegeo:123.456789,12.345678.Pourunsiteinternet,ils’agitd’uncheminhiérarchique.

re

quête

frag

ment

— Lapermetdefourniruneprécisionparrapportàl’information. — Lepermetenfind’accéderàunesous-partiedel’information.

Uri

Uri.parse(String

PourcréerunobjetURI,c’estsimple,ilsuffitd’utiliserlaméthodestatique uri).Parexemple,pourenvoyerunSMSàunepersonne,j’utiliserail’URI:

 

Maisjepeuxaussiindiquerplusieursdestinatairesetuncorpspourcemessage:

 

Commevouspouvezlevoir,lecontenudelachaînedoitêtreencodé,sinonvousrencontrerez desproblèmes.

14.3.1.2. Type MIME

au

dio

 

vi

deo

au

dio/mp3

 

au

dio/wav

LeMIMEestunidentifiantpourlesformatsdefichier.Parexemple,ilexisteuntypeMIME text. Si une donnée est accompagnée du type MIME text, alors les données sont du texte. Ontrouveaussi           et          parexemple.Ilestensuitepossibledepréciserunsous-type afind’affinerlesinformationssurlesdonnées,parexemple     et         sontdeux typesMIMEquiindiquentquelesdonnéessontsonores,maisaussidequellemanièreellessont encodées.

pi

tre

Trois.contact_te

le

LestypesMIMEquenousvenonsdevoirsonstandards,c’est-à-direqu’ilyauneorganisationqui lesareconnuscommeétantlégitimes.MaissivousvouliezcréervosproprestypesMIME?Vous n’allezpasdemanderàl’organisationdelesvalider,ilsneserontpasd’accordavecvous.C’est pourquoiilexisteunepetitesyntaxeàrespecterpourlestypespersonnalisés:vnd.votre_pa ckage.le_type,cequipeutdonnerparexemple

pho

nique

.

i

Pourêtretoutàfaitexact,sousAndroidvousnepourrezjamaisquepréciserdessous-types, jamaisdestypes.

Pour les intents, ce type peut être décrit de manière implicite dans l’URI (on voit bien par exemple que sms:0606060606 décrit un numéro de téléphone, il n’est pas nécessaire de le préciser),maisilfaudraparmomentsledécriredemanièreexplicite.Onpeutlefairedansle champ type d’un intent. Vous trouverez une liste non exhaustive des types MIME sur cette pageWikipédia  .

Préciseruntypeestsurtoutindispensablequandondoitmanipulerdesensemblesdedonnées, commeparexemplequandonveutsupprimeruneouplusieursentréesdanslerépertoire,car danscecasprécisils’agirad’unpointeurverscesdonnées.AvecAndroid,ilexistedeuxmanières de manipuler ces ensembles de données, les curseurs (cursor) et les fournisseurs de contenus (content provider).Cesdeuxtechniquesserontétudiéesplustard,parconséquentnousallons nouscantonnerauxdonnéessimplespourl’instant.

14.3.2. L’action

Une action est une constante qui se trouve dans la classe Intent et qui commence toujours par«ACTION » suivi d’un verbe (en anglais, bien sûr) de façon à bien faire comprendre qu’il

AC

TION_VIEW

AC

TION_VIEW

s’agit d’une action. Si vous voulez _voir quelquechose,onvautiliserl’action. Par exemple, si vous utilisezsur un numéro de téléphone, alors le numéro de téléphones’afficheradanslecomposeurdenumérosdetéléphone.

tion.NOM_DE_L_AC

TION

Vouspouvezaussicréervospropresactions.Pourcela,ilvauxmieuxrespecterunesyntaxe,qui estdecommencerparvotrepackagesuivide:

 

Voiciquelquesactionsnativesparmilesplususitées:

Intitulé

Action

Entrée attendue

 

Sortie attendue

 

AC

TION_MAIN

Pour indiquer qu’il s’agit du point d’entrée dans l’application

/

 

/

 

AC

TION_DIAL

Pourouvrirle composeurdenuméros téléphoniques

Unnumérode téléphonesembleune bonneidée:-p

/

 
 

AC

TION_DE

LETE*

Supprimerdesdonnées

UnURIverslesdonnées àsupprimer

/

 
 

AC

TION_EDIT*

 

Ouvrir un éditeur adapté pour modifier lesdonnéesfournies

UnURIverslesdonnées àéditer

/

 

AC

TION_IN

SERT

*

Insérerdesdonnées

L’URIdurépertoireoù insérerlesdonnées

L’URI des nouvelles donnéescréées

 

AC

TION_PICK*

 

Sélectionnerunélément dans un ensemble de

données

L’URI qui contient un répertoirededonnéesà partir duquel l’élément serasélectionné

L’URI de l’élément qui aétésélectionné

   

Effectuerunerecherche

Letexteàrechercher

/

 

AC

TION_SEARCH

 

AC

TION_SENDTO

 

Envoyer un message à

quelqu’un

La personne à qui envoyerlemessage

/

 

AC

TION_VIEW

 

Permetdevisionnerune donnée

Un peu tout. Une adresse e-mail sera

visionnée dans l’application pour les e-mails, unnumérodetéléphone danslecomposeur,une adresseinternetdansle navigateur,etc.

/

AC-

TION_WEB_S

EARCH

Effectuerunerecherche surinternet

S’ils’agitd’untextequi commencepar«http», lesites’afficheradirectement,sinonc’estunerecherchedansGooglequi sefera

/

               

!

Lesactionssuiviesd’uneastérisquesontcellesquevousnepourrezpasutilisertantque nousn’auronspasvulesContentProvider.

Pour créer un intent qui va ouvrir le composeur téléphonique avec le numéro de téléphone 0606060606,j’adaptemoncodeprécédentenremplaçantlecodeduboutonpar:

 

Cequidonne,unefoisquej’appuiedessus,lafiguresuivante.

 

Figure 14.4.–Lecomposeurtéléphoniqueestlancéaveclenumérosouhaité

14.4. La résolution des intents

AC

TION_VIEW

AC

TION_VIEW

fil

ter>

Quandonlanceunavecuneadresseinternet,c’estlenavigateurquiselance,et quandonlanceunavecunnumérodetéléphone,c’estlecomposeurdenuméros quiselance.Alors,commentAndroiddéterminequidoitrépondreàunintentdonné? CequevafaireAndroid,c’estqu’ilvacomparerl’intentàdesfiltresquenousallonsdéclarer dansleManifestetquisignalentquelescomposantsdenosapplicationspeuventgérercertains intents.Cesfiltressontlesnœuds<intent-,nouslesavonsdéjàrencontrésetignorés parlepassé.Uncomposantd’uneapplicationdoitavoirautantdefiltresquedecapacitésde traitement.S’ilpeutgérerdeuxtypesd’intent,ildoitavoirdeuxfiltres. Letestdeconformitéentreunintentetunfiltresefaitsurtroiscritères.

14.4.1. L’action

Ac

tion

Ac

tion

Permetdefiltrerenfonctionduchampd’unintent.Ilpeutyenavoirunoupluspar filtre.Sivousn’enmettezpas,tousvosintentsserontrecalés.Unintentseraacceptésicequi setrouvedanssonchampestidentiqueàaumoinsunedesactionsdufiltre.Etsiun intentneprécisepasd’action,alorsilseraautomatiquementacceptépourcetest.

 

AC

TION_VIEW

Cetteactiviténepourraintercepterquelesintentsquiontdansleurchampaction

AC

TION_SENDTO

AC

TION_VIEW

 

AC

TION_SEARCH

et/ou,cartoutes sesactionssontacceptéesparlefiltre.Siunintentapour action         et          ,alorsilserarecalé,carunedesesactionsn’estpas acceptéeparlefiltre.

14.4.2. La catégorie

Cettefois,iln’estpasindispensabled’avoiruneindicationdecatégoriepourunintent,mais, s’ilyenauneouplusieurs,alorspourpassercetestilfautquetoutes lescatégoriesdel’intent correspondentàdescatégoriesdufiltre.Pourlesmatheux,onditqu’ils’agitd’uneapplication «injective»maispas«surjective».

star

tAc

ti

vity()

CA

TE

GORY_DE

FAULT

On pourrait se dire que par conséquent, si un intent n’a pas de catégorie, alors il passe automatiquementcetest,maisdèsqu’unintentestutiliséaveclaméthode, alorsonluiajoutelacaté,sivousvoulezquevotrecomposant acceptelesintentsimplicites,vousdevezrajoutercettecatégorieàvotrefiltre.

Pourlesactionsetlescatégories,lasyntaxeestdifférenteentreleJavaetleXML.Parexemple,

AC

TION_VIEW

 

an

CA

TE

GORY_DE

FAULT

 

an

te

FAULT

pour l’action en Java, on utilisera et pour la categorie on utilisera . De plus,

quand vous créez vos propres actions ou catégories, le mieux est de les préfixer avec le nom de votre package afin de vous assurer qu’elles restent uniques. Par exemple, pour l’action

DE

SEM

BROUILLER

 

pi

tre

SEM

BROUILLER

                                               ,onpourraitutiliser                                                                                           .

 

AC

TION_VIEW

 

AC

TION_SEARCH

CA

TE

GORY_DE

FAULT

 

CA

TE

GORY_DE

SEM

BROUILLEUR

Ilfauticiquel’intentaitpouraction et/ou .Encequiconcerne lescatégories,ildoitavoir et .

VoicilesprincipalescatégoriespardéfautfourniesparAndroid:

Catégorie

Description

 

CA

TE

GORY_DE

FAULT

Indique qu’il faut effectuer le traitement par défaut sur les données

correspondantes. Concrètement, on

l’utilise pour déclarer qu’on accepte que ce composant soit utilisé par des intents implicites.

 

CA

TE

GORY_BROW

SABLE

Utilisépourindiquerqu’uneactivitépeutêtre appeléesansrisquedepuisunnavigateurweb. Ainsi,siunutilisateurcliquesurunliendans votreapplication,vouspromettezqueriende dangereuxnesepasseraàlasuitede l’activationdecetintent.

 

CA

TE

GORY_TAB

Utilisépourlesactivitésqu’onretrouvedansdes onglets.

 

CA

TE

GORY_AL

TER

NA

TIVE

Permet de définir une activité comme un traitementalternatifdanslevisionnaged’éléments. C’estparexempleintéressantdanslesmenus,si voussouhaitezproposeràvotreutilisateurderegardertellesdonnéesdelamanièreproposéepar votreapplicationoud’unemanièrequepropose uneautreapplication.

 

CA

TE

GORY_SE

LEC

TED_AL

TER

NA

TIVE

Comme ci-dessus, mais pour des éléments qui ontétésélectionnés,passeulementpourlesvoir.

 

CA

TE

GORY_LAUN

CHER

Indiquequec’estcecomposantquidoits’afficher danslelanceurd’applications.

 

CA

TE

GORY_HOME

Permet d’indiquer que c’est cette activité qui doitsetrouversurl’écrand’accueild’Android.

 

CA

TE

GORY_PRE

FE

RENCE

Utilisépouridentifierles

Pre

fe

ren

ceAc

ti

vity

(dontnousparleronsauchapitresuivant).

14.4.3. Les données

Ilestpossibledepréciserplusieursinformationssurlesdonnéesquecetteactivitépeuttraiter.

an

droid:scheme

an

droid:mi

me

Type

Principalement,onpeutpréciserleschémaqu’onveutavec,onpeutaussi préciserletypeMIMEavec.Parexemple,sinotreapplicationtraitedes fichiers textes qui proviennent d’internet, on aura besoin du type « texte » et du schéma « internet»,cequidonne:

Etilsepassequoieninterneunefoisqu’onalancéunintent?

Ehbien,ilexisteplusieurscasdefigure:

Ac

ti

vi

ty

Not

Foun

dEx

cep

tion

— Soit votre recherche est infructueuse et vous avez 0 résultat, auquel cas c’est grave et uneseralancée.Ilvousfautdoncpenseràgérercetype d’erreurs.

— Sionn’aqu’unrésultat,commedanslecasdesintentsexplicites,alorscerésultatva directementselancer.

Intent

crea

te

Choo

ser(Intent

tar

get,

Char

Se

quence

titre)

— En revanche, si on a plusieurs réponses possibles, alors le système va demander à l’utilisateurdechoisiràl’aided’uneboî’utilisateurchoisituneaction par défaut pour un intent, alors à chaque fois que le même intent sera émis ce sera toujourslemêmecomposantquiserasélectionné.D’ailleurs,ilpeutarriverquecesoit unemauvaisechoseparcequ’unmêmeintentnesignifiepastoujoursunemêmeintention (ironiquement). Il se peut qu’avec ACTIONSEND, on cherche un jour à envoyer un SMS et un autre jour à envoyer un e-mail, c’est pourquoi il est possible de forcer la main à Android et à obliger l’utilisateur à choisir parmi plusieurs éventualités à l’aide de. On peut ainsi insérer l’_intent àtraiteretletitre delaboîtededialoguequipermettraàl’utilisateur dechoisiruneapplication.

Pa

ckage Ma

na

ger

Pa

ckage Ma

na

ger

Pa

cka

ge

Ma

na

ger

get

Pa

cka

ge

Ma

na

ger()

Com

po

nent

Name

re

sol

veAc

ti

vity

(Pa

cka

ge

Ma

na

ger

pm)

Dans tous les cas, vous pouvez vérifier si un composant va réagir à un intent de manière programmatique à l’aide du  . Le est un objet qui vous permet d’obtenir des informations sur les packages qui sont installés sur l’appareil. On y fait appel avec la méthodedans n’importe quel composant.Puisondemandeàl’intentlenomdel’activitéquivapouvoirlegéreràl’aidedela méthode:

 

14.5. Pour aller plus loin : navigation entre des activités

Uneapplicationpossèdeengénéralplusieursactivités.Chaqueactivitéestdédiéeàunensemble cohérentd’actions,maistoujourscentréesversunmêmeobjectif.Pouruneapplicationquilit desmusiques,ilyauneactivitépourchoisirlamusiqueàécouter,uneautrequiprésenteles contrôlessurlesmusiques,encoreuneautrepourparamétrerl’application,etc.

Je vous avais présenté au tout début du tutoriel la pile des activités. En effet, comme on ne peut avoir qu’une activité visible à la fois, les activités étaientprésentéesdans une pile où il étaitpossibled’ajouteroud’enleverunélémentausommetafindechangerl’activitéconsultée actuellement.C’estbiensûrtoujoursvrai,àundétailprès.Ilexisteenfaitunepilepartâche. Onpourraitdirequ’unetâcheestuneapplication,maisaussilesactivitésquiserontlancéespar cetteapplicationetquisontextérieuresàl’application.Ainsiquelesactivitésquiserontlancées parcesactivitésextérieures,etc.

Audémarrage de l’application, une nouvelle tâche est créée et l’activité principale occupe la racinedelapile.

Aulancementd’unenouvelleactivité,cettedernièreestajoutéeausommetdelapileetacquiert ainsilefocus.L’activitéprécédenteestarrêtée,maisl’étatdesoninterfacegraphiqueestconservé. Quandl’utilisateurappuiesurlebouton Retour ,l’activitéactuelleestéjectéedelapile(elleest doncdétruite)etl’activitéprécédentereprendsondéroulementnormal(avecrestaurationdes élémentsdel’interfacegraphique).S’iln’yapasd’activitéprécédente,alorslatâcheesttout simplementdétruite.

Dansunepile,onnemanipulejamaisquelesommet.Ainsi,sil’utilisateurappuiesurunbouton del’activité1pouralleràl’activité2,puisappuiesurunboutondel’activité2pourallerdans l’activité 1, alors une nouvelle instance de l’activité 1 sera créée, comme le montre la figure suivante.

 

Figure 14.5.–Onpassedel’activité1àl’activité2,puisdel’activité2àl’activité1,cequi faitqu’onadeuxdifférentesinstancesdel’activité1!

Pour changer ce comportement, il est possible de manipuler l’affinité d’une activité. Cette affinitéestunattributquiindiqueavecquelletâcheellepréfèretravailler.Touteslesactivités quiontuneaffinitéavecunemêmetâcheselancerontdanscettetâche-là.

×

Elle permet surtout de déterminer à quelle tâche une activité sera apparentée ainsi que la tâche qui va accueillir l’activité quand elle est lancée avec le flag FLAG_ACTI VITY_NEW_TASK. Par défaut, toutes les activités d’une même application ont la même affinité.Eneffet,sivousneprécisezpasd’affinité,alorscetattributprendralavaleurdu packagedel’application.

Cecomportementestceluiquiestpréférablelaplupartdutemps.Cependant,ilpeutarriver quevousayezbesoind’agirautrement,auquelcasilyadeuxfaçonsdefaire.

14.5.1. Modifier l’activité dans le Manifest

Ilexistesixattributsquenousn’avonspasencorevusetquipermettentdechangerlafaçon dontAndroidréagitàlanavigation.

14.5.1.1. android :taskAffinity

Cetattributpermetdepréciseravecquelletâchecetteactivitépossèdeuneaffinité.Exemple:

 

14.5.1.2. android :allowTaskReparenting

Est-cequel’activitépeutsedéconnecterd’unetâchedanslaquelleelleacommencéàtravailler pourallerversuneautretâcheaveclaquelleelleauneaffinité?

Parexemple,danslecasd’uneapplicationpourlirelesSMS,sileSMScontientunlien,alors cliquerdessuslancerauneactivitéquipermettrad’afficherlapagewebdésigné onappuiesurlebouton Retour ,onrevientàlalectureduSMS.Enrevanche,aveccetattribut, l’activitélancéeseraliéeàlatâchedunavigateuretnonplusduclientSMS. Lavaleurpardéfautestfalse.

14.5.1.3. android :launchMode

Définit comment l’application devra être lancée dans une tâche. Il existe deux modes : soit l’activitépeutêtreinstanciéeplusieursfoisdanslamêmetâche,soitelleesttoujoursprésente demanièreunique.

Danslepremiermode,ilexistedeuxvaleurspossibles:

stan

dard

—estlemodepardéfaut,dèsqu’onlanceuneactivitéunenouvelleinstanceest crééedanslatâche.Lesdifférentesinstancespeuventaussiapparteniràplusieurstâches.

sin

gle

Top

void

on

Ne

— Avec,siuneinstancedel’activitéexistedéjàausommetdelatâcheactuelle, alors le système redirigera l’intent vers cette instance au lieu de créer une nouvelle instance.Leretourdans l’activitéseferaàtraverslaméthode decallback

wIntent(Intent

intent)

.

Le second mode n’est pas recommandé et doit être utilisé uniquement dans des cas précis. Surtout,onnel’utilisequesil’activitéestcelledelancementdel’application.Ilpeutprendre deuxvaleurs:

sin

gle

Task

— Avec,lesystèmecréel’activitéàlaracined’unenouvelletâche.Cependant, siuneinstancedel’activitéexistedéjà,alorsonouvriraplutôtcetteinstance-là.

sin

gleIns

tance

— Enfin avec, à chaque fois on crée une nouvelle tâche dont l’activité seralaracine.

14.5.1.4. android :clearTaskOnLaunch

Est-ce que toutes les activités doivent être enlevées de la tâche — à l’exception de la racine

—quandonrelancelatâchedepuisl’écrandedémarrage?Ainsi,dèsquel’utilisateurrelance l’application, il retournera à l’activité d’accueil, sinon il retournera dans la dernière activité qu’ilconsultait.

Lavaleurpardéfautestfalse.

14.5.1.5. android :alwaysRetainTaskState

Est-cequel’étatdelatâchedanslaquellesetrouvel’activité—etdontelleestlaracine—doit êtremaintenuparlesystème?

Typiquement,unetâcheestdétruitesiellen’estpasactiveetquel’utilisateurnelaconsultepas pendantuncertaintemps.Cependant,danscertainscas,commedanslecasd’unnavigateurweb avecdesonglets,l’utilisateurserabiencontentderécupérerlesongletsquiétaientouverts. Lavaleurpardéfautestfalse.

14.5.1.6. android :finishOnTaskLaunch

Est-ceque,s’ilexistedéjàuneinstancedecetteactivité,ilfautlafermerdèsqu’unenouvelle instanceestdemandée? Lavaleurpardéfautestfalse.

14.5.2. Avec les intents

Ilestaussipossibledemodifierl’associationpardéfautd’uneactivitéàunetâcheàl’aidedes flagscontenusdanslesintents.OnpeutrajouterunflagàunintentaveclaméthodeIntent

add

Flags(int

flags)

.

Ilexistetroisflagsprincipaux:

FLAG_AC

TI

VITY_NEW_TASK

sin

gle

Task

—permetdelancerl’activitédansunenouvelletâche,saufsi l’activitéexistedéjàdansunetâche.C’estl’équivalentdumode.

FLAG_AC

TI

VITY_SINGLE_TOP

 

sin

gle

Top

—  est un équivalent de . On lancera l’activité dansunenouvelletâche,quelquessoientlescirconstances.

FLAG_AC

TI

VITY_CLEAR_TOP

FLAG_AC

TI

VITY_NEW_TASK

—permetdefaireensorteque,sil’activitéestdéjàlancée dans la tâche actuelle, alors au lieu de lancer une nouvelle instance de cette activité touteslesautresactivitésquisetrouventau-dessusd’elleserontferméesetl’intentsera délivréàl’activité(souventutiliséavec).Quandonutilise cesdeuxflagsensemble,ilspermettentdelocaliseruneactivitéquiexistaitdéjàdans uneautretâcheetdelamettredansunepositionoùellepourrarépondreàl’intent.

14.6. Pour aller plus loin : diffuser des intents

On a vu avec les intents comment dire « Je veux que vous traitiez cela, alors que quelqu’un le fasse pour moi s’il vous plaît ». Ici on va voir comment dire « Cet évènement vient de se dérouler, je préviens juste, si cela intéresse quelqu’un ». C’est donc la différence entre « Je viensderecevoirunSMS,jechercheuncomposantquipourrapermettreàl’utilisateurdelui répondre » et « Je viens de recevoir un SMS, ça intéresse une application de le gérer? ». Il s’agiticiuniquementdenotifications,pasdedemandes.Concrètement,lemécanismenormal desintentsestvisiblepourl’utilisateur,alorsqueceluiquenousallonsétudieresttotalement transparentpourlui.

Nousutiliseronstoujoursdesintents,saufqu’ilsserontanonymesetdiffusésàtoutlesystème. Cetyped’intentesttrèsutiliséauniveaudusystèmepourtransmettredesinformations,comme parexemplel’étatdelabatterieouduréseau.Cesintentsparticulierss’appellentdesbroadcast intents. On utilise encore une fois un système de filtrage pour déterminer qui peut recevoir l’intent,maisc’estlafaçondontnousallonsrecevoirlesmessagesquiestunpeuspéciale.

void

send

Broad

cast(Intent

intent)

La création des broadcast intents est similaire à celle des intents classiques, sauf que vous allezlesenvoyeraveclaméthode.Decettemanière,

l’intentneserareçuqueparlesbroadcast receivers,quisontdesclassesquidériventdelaclasse

Broad

cas

tRe

cei

ver

 .Deplus,quandvousallezdéclarercecomposantdansvotreManifest,

ilfaudraquevousannonciezqu’ils’agitd’unbroadcastreceiver:

 

void

on

Re

ceive

(Context

context,

Intent

intent)

Il vous faudra alors redéfinir la méthode de callback qui est lancée dès qu’on reçoit un broadcast intent. C’est dans cette classe

qu’ongéreralemessagereçu.

Parexemple,sij’aiunintentquitransmetàtoutlesystèmelenomdel’utilisateur:

 

on

Re

ceive

Un broascast receiver déclaré de cette manière sera disponible tout le temps, même quand l’application n’est pas lancée, mais ne sera viable que pendant la durée d’exécution de sa méthode.Ainsi,nevousattendezpasàretrouvervotrereceiversivouslancezun thread,uneboîtededialogueouunautrecomposantd’uneapplicationàpartirdelui.

Deplus,ilnes’exécuterapasenparallèledevotreapplication,maisbiendemanièreséquentielle

(danslemêmethread,donc),cequisignifieque,sivouseffectuezdegroscalculsquiprennent dutemps,lesperformancesdevotreapplicationpourraients’entrouveraffectées.

Maisilestaussipossiblededéclarerunbroadcastreceiverdemanièredynamique,directement dans le code. Cette technique est surtout utilisée pour gérer les évènements de l’interface graphique.

Broad

cas

tRe

cei

ver

Pour procéder, vous devrez créer une classe qui dérive de, mais sans l’enregistrerdansleManifest.Ensuite,vouspouvezluirajouterdesloisdefiltrageaveclaclasse

In

tent

Fil

ter

re

gis

ter

Re

cei

ver(Broad

cas

tRe

cei

ver

re

cei

ver,

In

tent

Fil

ter

fil

ter)

void

un

re

gis

ter

Re

cei

,puisvouspouvezl’enregistrerdansl’activitévoulueaveclaméthodeIntent et surtout, quand vous n’en n’aurez plus besoin, il faudra la désactiver avec

ver(Broad

cas

tRe

cei

ver

re

cei

ver).

Ainsi,sionveutrecevoirnosbroadcastintentspourdirecoucouàl’utilisateur,maisuniquement quandl’applicationselanceetqu’ellen’estpasenpause,onfait:

 

AC

TION_CA

MERA_BUT

TON

Deplus,ilexistequelquesmessagesdiffusésparlesystèmedemanièrenativeetquevouspouvez écouter,commeparexemplequiestlancédèsquel’utilisateurappuie surleboutondel’appareilphoto.

14.6.0.1. Sécurité

N’importe quelle application peut envoyer des broadcast intents à votre receiver, ce qui est une faiblesse au niveau sécurité. Vous pouvez aussi faire en sorte que votre receiver déclaré dansleManifestnesoitaccessiblequ’àl’intérieurdevotreapplicationenluiajoutantl’attribut

an

droid:ex

por

ted="false"

:

 

Notezquecetattributestdisponiblepourtouslescomposants.

void

send

Broad

cast

(Intent

intent,

String

re

cei

ver

Per

mis

sion)

Deplus,quandvousenvoyezunbroadcastintent, dedéterminerquipeutrecevoirunbroadcastintent,ilsuffitdeluiajouterunepermissionàl’aide delaméthode,avec

re

cei

ver

Per

mis

sion

unepermissionquevousaurezdéterminée.Ainsi,seulslesreceiversqui

déclarentcettepermissionpourrontrecevoircesbroadcastintents:

 

PuisdansleManifest,ilsuffitderajouter:

 

— Lesintentssontdesobjetspermettantd’envoyerdesmessagesentrevosactivités,voire entre vos applications. Ils peuvent, selon vos préférences, contenir un certain nombre d’informationsqu’ilserapossibled’exploiterdansuneautreactivité.

Par

ce

lable

— Engénéral,lesdonnéescontenuesdansunintentsontassezlimitéesmaisilestpossiblede partageruneclasseentièresivousétendezlaclasseetquevousimplémentez touteslesméthodesnécessairesàsonfonctionnement.

— Lesintentsexplicitessontdestinésàserendreàuneactivitétrèsprécise.Vouspourriez également définir que vous attendez un retour suite à cet appel via la méthode void

star

tAc

ti

vi

ty

For

Re

sult(Intent

intent,

int

re

quest

Code)

.

— Lesintentsimplicitessontdestinésàdemanderàuneactivité,sansquel’onsachelaquelle, detraitervotremessageendésignantletyped’actionsouhaitéetlesdonnéesàtraiter.

fil

ter>

 

<ac

ti

vity>

— Définir un nœud <intent- dans le nœud d’une de votre fichier Manifest vous permettra de filtrer vos activités en fonction du champ d’action de vos intents.

— Nousavonsvuqu’Androidgèrenosactivitésvia unepileLIFO.Pourchangercecomportement,ilestpossibledemanipulerl’affinitéd’uneactivité.Cetteaffinitéestunattribut quiindiqueavecquelletâcheellepréfèretravailler.

<re

cei

ver>

fil

ter>

— Les broadcast intents diffusentdes intentsà travers tout le système pour transmettre desinformationsdemanièrepubliqueàquiveut.Celasemetenplacegrâceàunnœud filtréparunnœud<intent-.


15. Le stockage de données

Laplupartdenosapplicationsaurontbesoindestockerdesdonnéesàunmomentouàunautre. Lacouleurpréféréedel’utilisateur,saconfigurationréseauouencoredesfichierstéléchargés surinternet.Enfonctiondecequevoussouhaitezfaireetdecequevoussouhaitezenregistrer, Android vous fournit plusieurs méthodes pour sauvegarder des informations. Il existe deux solutionsquipermettentd’enregistrerdesdonnéesdemanièrerapideetflexible,sionexclutles basesdedonnées:

— Nous aborderons tout d’abord les préférences partagées, qui permettent d’associer à unidentifiantunevaleur.Lecoupleainsicréépermetderetenirlesdifférentesoptions que l’utilisateur souhaiterait conserver ou l’état de l’interface graphique. Ces valeurs pourront être partagées entre plusieurs composants. Encore mieux, Android propose unensembled’outilsquipermettrontdefacilitergrandementletravailetd’unifierles interfacesgraphiquesdesactivitésdédiéesàlasauvegardedespréférencesdesutilisateurs.

— Ilpeutaussiarriverqu’onaitbesoind’écrireoudeliredesfichiersquisontstockéssurle terminalousurunpériphériqueexterne.

Ici,onneparlerapasdesbasesdedonnées.Maisbientôt,promis.

15.1. Préférences partagées

Utilevoireindispensablepourungrandnombred’applications,pouvoirenregistrerlesparamètres desutilisateursleurpermettradeparamétrerdemanièreminutieusevosapplicationsdemanière àcequ’ilsobtiennentlerenduquiconviennelemieuxàleursexigences.

15.1.1. Les données partagées

Sha

red

Pre

fe

Le point de départ de la manipulation des préférences partagées est la classe rences  . Elle possède des méthodes permettant d’enregistrer et récupérer des paires de typeidentifiant-valeurpourlestypesdedonnéesprimitifs,commelesentiersouleschaînesde caractères.L’avantageréelétantbiensûrquecesdonnéessontconservéesmêmesil’application estarrêtéeoutuée.Cespréférencessontdeplusaccessiblesdepuisplusieurscomposantsausein d’unemêmeapplication.

Sha

red

Pre

fe

rences

Ilexistetroisfaçonsd’avoiraccèsaux:

Sha

red

Pre

fe

rences

Pre

fe

ren

ce

Ma

— Laplussimpleestd’utiliserlaméthodestatique

na

De

fault

Sha

red

Pre

fe

rences(Context

context)

.

Sha

red

Pre

fe

rences

get

Pre

fe

rences(int

mode)

— Si vous désirez utiliser un fichier standard par activité, alors vous pourrez utiliser la méthode.

Sha

red

Pre

fe

rences

get

Sha

red

Pre

fe

rences

(String

name,

int

— En revanche, si vous avez besoin de plusieurs fichiers que vous identifierez par leur nom,alorsutilisez mode)oùnameseralenomdufichier.

Encequiconcernelesecondparamètre,mode,ilpeutprendretroisvaleurs:

Context.MODE_PRI

VATE

—,pourquelefichiercréénesoitaccessiblequeparl’application quil’acréé.

Context.MODE_WORLD_REA

DABLE

—,pourquelefichiercréépuisseêtreluparn’importe quelleapplication.

Context.MODE_WORLD_WRI

TEABLE

—,pourquelefichiercréépuisseêtreluet modifiépar n’importequelleapplication.

i

Petit détail, appeler SharedPreferences PreferenceManager.getDefaultShared Preferences(Context context) revient à appeler SharedPreferences getPrefe rences(MODE_PRIVATE)etutiliserSharedPreferencesgetPreferences(intmode) revient à utiliser SharedPreferences getSharedPreferences (NOM_PAR_DEFAUT, mode)avecNOM_PAR_DEFAUTunnomgénéréenfonctiondupackagedel’application.

Sha

red

Pre

fe

rences

Sha

red

Pre

fe

tor

Sha

red

Pre

fe

tor

edit()

 

Sha

red

Pre

fe

rences

Afind’ajouteroudemodifierdescouplesdansun,ilfaututiliserunobjet de type. Il est possible de récupérer cet objet en utilisant la méthodesurun .

Sha

red

Pre

fe

va

lue

boo

lean

com

mit()

Si vous souhaitez ajouter des informations, utilisez une méthode du genre rences.Editor putX(String key, X value) avec X le type de l’objet, key l’identifiant etlavaleurassociée.Ilvousfautensuiteimpérativementvalidervoschangementsavec laméthode.

i

Les préférences partagées ne fonctionnent qu’avec les objets de type boolean, float, int,longetString.

Co

lor

Parexemple,pourconserverlacouleurpréféréedel’utilisateur,iln’estpaspossibled’utiliserla classepuisqueseulslestypesdebasesontacceptés,alorsonpourraitconserverlavaleur delacouleursouslaformed’unechaînedecaractères:

key,

X

def

Va

lue)

            X                                                        key

def

Va

lue

Demanièrenaturelle,pourrécupérerunevaleur,onpeututiliserlaméthodeXgetX(String avec letypedel’objetdésiré,  l’identifiantdevotrevaleuret

unevaleurquevoussouhaitezvoirretournéeaucasoùiln’yaitpasdevaleurassociéeàkey:

 

Sha

red

Pre

fe

Sivoussouhaitezsupprimerunepréférence,vouspouvezlefaireavec

tor

re

mo

veS

tring(String

key)

Sha

red

Pre

fe

tor

clear()

,ou,pourradicalementsupprimertouteslespréférences,il existeaussi.

Map<String,

?>

ge

tAll()

Enfin,sivousvoulezrécupérertouteslesdonnéescontenuesdanslespréférences,vouspouvez utiliserlaméthode.

15.1.2. Des préférences prêtes à l’emploi

Pourenregistrervospréférences,vouspouveztrèsbienproposeruneactivitéquipermetd’insérer différents paramètres (voir figure suivante). Si vous voulez développer vous-mêmes l’activité, grandbienvousfasse,çaferadesrévisions,maissachezqu’ilexisteunframeworkpourvousaider. Vousenavezsûrementdéjàvusdansd’autresapplications.C’estd’ailleursunénormeavantage d’avoirtoujoursunécransimilaireentrelesapplicationspourlasélectiondespréférences.

 

Figure 15.1.–L’activitépermettantdechoisirdesparamètrespourlePlayStore

Pre

fe

ren

ceAc

ti

vity

Cetyped’activitéss’appelleles« ».Unplusindéniableiciestque chaquecoupleidentifiant/valeurestcrééautomatiquementetserarécupéréautomatiquement, d’oùungaindetempsééationsefaitenplusieursétapes, nousallonsvoirlapremière,quiconsisteàétabliruneinterfacegraphiqueenXML.

15.1.2.1. Étape 1 : en XML

Pre

fe

ren

ceS

creen

Laracinedecefichierdoitêtreun.

i

Commecen’estpasvraimentunlayout,onledé.

Pre

fe

ren

ce

Ca

te

gory

an

droid:title

Toutd’abord,ilestpossiblededésignerdescatégoriesdepréférences.Unepourlespréférences destinéesàinternetparexemple,uneautrepourlespréférencesesthétiques,etc.Onpeutajouter des préférences avec le nœud. Ce nœud est un layout, il peut donc contenird’autrevues.Ilnepeutprendrequ’unseulattribut,,pourpréciserle textequ’ilaffichera.

Ainsilecodesuivant:

 

…donnelerésultatvisibleàlafiguresuivante.

 

Figure 15.2.–Lecodeenimage

Nousavonsnoscatégories,ilnousfautmaintenantinsérerdespréférences!Cestroisvuesont cinqattributsencommun:

an

droid:key

—estl’identifiantdelapréférencepartagée.C’estunattributindispensable, nel’oubliezjamais.

an

droid:title

—estletitreprincipaldelapréférence.

an

droid:sum

mary

—estuntextesecondairequipeutêtrepluslongetquiexpliquemieux cequeveutdirecettepréférence.

an

droid:de

pen

dency

— Utilisez,sivousvoulezliervotrepréférenceàuneautreactivité.

an

droid:key

Ilfautyinsérerl’identifiantdelapréférencedontondépend.

an

droid:de

fault

Va

lue

—estlavaleurpardéfautdecettepréférence.

Ilexisteaumoinstroistypesdepréférences,lapremièreétantunecaseàcocheravecCheck

Box

Pre

fe

rence

,avectrueoufalsecommevaleur(soitlacaseestcochée,soitellenel’est

pas).

an

droid:sum

ma

ryOn

 

an

droid:sum

ma

Àlaplacedurésuméstandard,vouspouvezdéclarerunrésuméquines’affichequequandlacase estcochée,           ,ouuniquementquandlacaseestdécochée, ryOff.

 

Cequidonnelafiguresuivante.

 

Figure 15.3.–Regardezlapremièrepréférence,lacaseestcochéepardéfautetc’estlerésumé associéquiestaffiché

Le deuxième type de préférences consiste à permettre à l’utilisateur d’insérer du texte avec

Edit

Text

Pre

fe

rence

 

Edit

Text

                                                          , qui ouvre une boîte de dialogue contenant un                         permettant

an

droid:dia

log

Title

an

droid:ne

ga

ti

ve

But

ton

Text

 

an

droid:po

si

ti

àl’utilisateurd’insérerdutexte.Onretrouvedesattributsquivousrappelleronsfortementle chapitresurlesboîtesdedialogue.Parexemple,permetdedéfinirle textedelaboîtededialogue,alorsqueet

ve

But

ton

Text

permettent respectivement de définir le texte du bouton à droite et celui du

boutonàgauchedanslaboîtededialogue.

 

Cequidonnelafiguresuivante.

 

Figure 15.4.–Lecodeenimage

Check

Box

Pre

fe

rence

an

droid:de

pen

dency="check

Box

Pref"

check

Box

Pref

Deplus,commevousavezpulevoir,ceparamètreestliéàlaprécédente parl’attribut,cequifaitqu’ilneseraaccessibleque silacaseàcocherdeestactivée,commeàlafiguresuivante.

 

Figure 15.5.–Leparamètren’estaccessiblequesilacaseestcochée

an

droid:dia

lo

gLayout

Deplus,commenousl’avonsfaitaveclesautresboîtesdedialogue,ilestpossibled’imposerun layoutàl’aidedel’attribut.

List

Pre

fe

rence

Letroisièmetypedepréférencesestunchoixdansunelisted’optionsavec.

Danscettepréférence,ondifférenciecequiestaffichédecequiestréel.Pratiquepourtraduire sonapplicationenplusieurslangues!Encoreunefois,ilestpossibled’utiliserlesattributsan

droid:dia

log

Title

 

an

droid:ne

ga

ti

ve

But

ton

Text

 

an

droid:po

si

ti

ve

But

ton

Text

an

droid:en

tries

an

droid:en

try

Va

,         et. Lesdonnéesdelalistequeliral’utilisateursontàprésenterdansl’attribut, alorsquelesdonnéesquiserontenregistréessontàindiquerdansl’attribut

ar

ray

lues.Lamanièrelaplusfacilederemplircesattributssefaitàl’aided’uneressourcedetype ,parexemplepourlalistedescouleurs:

 

Qu’onpeutensuitefournirauxattributssusnommés:

 

Cequidonnelafiguresuivante.

 

Figure 15.6.–Lecodeenimage

Onasélectionné«Vert»,cequisignifiequelavaleurenregistréeseragreen.

15.1.2.2. Étape 2 : dans le Manifest

Pourrecevoircettenouvelleinterfacegraphique,nousavonsbesoind’uneactivité.Ilnousfaut doncladéclarerdansleManifestsionveutpouvoiryaccéderaveclesintents.Cetteactivité seradéclaréecommen’importequelleactivité:

 

15.1.2.3. Étape 3 : en Java

Pre

fe

ren

ceAc

ti

vity

set

Con

tent

View

void

add

Pre

fe

ren

ces

From

Re

source(int

pre

fe

ren

ces

Re

sId)

Notreactivitéseraenfaitdetype.Onpeutlatraitercommeuneactivité classique, sauf qu’au lieu de lui assigner une interface graphique avec, on utiliseenluiassignantnotre layout:

 

15.2. Manipulation des fichiers

Onadéjàvucommentmanipulercertainsfichiersprécisàl’aidedesressources,maisilexiste aussidescasdefigureoùilfaudraprendreencompted’autresfichiers,parexempledanslecas d’untéléchargementoudel’explorationdefichierssurlacarteSDd’untélééorie, vousneserezpastrèsdépaysésicipuisqu’onmanipuleenmajoritélesmêmesméthodesqu’en Java.Ilexistebienentenduquandmêmedesdifférences.

Il y a deux manières d’utiliser les fichiers : soit sur la mémoire interne du périphérique à un endroitbienspécifique,soitsurunemémoireexterne(parexempleunecarteSD).Danstousles cas,onparttoujoursduContextpourmanipulerdesfichiers.

15.2.1. Rappels sur l’écriture et la lecture de fichiers

Ce n’est pas un sujet forcément évident en Java puisqu’il existe beaucoup de méthodes qui permettentd’écrireetdeliredesfichiersenfonctiondelasituation.

Fi

leIn

Lecasleplussimpleestdemanipulerdesfluxd’octets,cequinécessitedesobjetsdetype

putS

tream

 

Fi

leOut

putS

tream

int

read()

 

void

write(byte[]

pourlireunfichieret       pourécriredansunfichier.Lalecture s’effectue avec la méthode        et on écrit dans un fichier avec

b).Voiciunprogrammetrèssimplequilitdansunfichierpuisécritdansunautrefichier:

 

15.2.2. En interne

L’avantage ici est que la présence des fichiers dépend de la présence de l’application. Par conséquent,lesfichiersserontsuppriméssil’utilisateurdésinstallel’activité.Enrevanche,comme lamémoireinternedutéléphonerisqued’êtrelimitée,onéviteengénéraldeplacerlesplusgros fichiersdecettemanière.

Fi

leOut

putS

tream

Fi

leOut

putS

tream

open

Fi

leOut

put

(String

name,

int

mode)

Afinderécupérerunquipointeraverslebonrépertoire,ilsuffitd’utiliser la méthodeavec name le nomdufichieretmodelemodedanslequelouvrirlefichier.Ehoui,encoreunefois,ilexiste plusieursméthodespourouvrirunfichier:

MODE_PRI

VATE

—permetdecréer(ouderemplacer,d’ailleurs)unfichierquiserautilisé uniquementparl’application.

MODE_WORLD_REA

DABLE

—pourcréerunfichierquemêmed’autresapplicationspourront lire.

MODE_WORLD_WRI

TABLE

—pourcréerunfichieroùmêmed’autresapplicationspourront lireetécrire.

MODE_AP

PEND

—pourécrireàlafind’unfichierpréexistant,aulieudecréerunfichier. Parexemple,pourécriremonpseudodansunfichier,jeferai:

 

Fi

leIn

putS

tream

open

Fi

leIn

put

(String

name)

De manière analogue, on peut retrouver un fichier dans lequel lire à l’aide de la méthode .

!

N’essayez pas d’insérer des « / » ou des « \ » pour mettre vos fichiers dans un autre répertoire,sinonlesméthodesrenverrontuneexception.

File

get

Fi

les

Dir()

boo

lean

de

le

te

File(String

name)

String[]

fi

le

List()

Ensuite, il existe quelques méthodes qui permettent de manipuler les fichiers au sein de cet emplacementinterne,afind’avoirunpeuplusdecontrôle.Déjà,pourretrouvercetemplacement, ilsuffitd’utiliserlaméthode.Poursupprimerunfichier,onpeutfaire appelàetpourrécupérerunelistedesfichierscrééspar l’application,onemploie.

15.2.2.1. Travailler avec le cache

Lesfichiersnormauxnesontsupprimésquesiquelqu’unlefait,quecesoitvousoul’utilisateur. A contrario,lesfichierssauvegardésaveclecachepeuventaussiêtresupprimésparlesystème d’exploitation afin de libérer de l’espace. C’est un avantage, pour les fichiers qu’on ne veut garderquetemporairement.

File

get

Ca

che

Dir()

Pourécriredanslecache,ilsuffitd’utiliserlaméthodepourrécupérerle répertoireàmanipuler.Demanièregénérale,onévited’utilisertropd’espacedanslecache,il s’agitvraimentd’unespacetemporairedestockagepourpetitsfichiers.

!

Ne vous attendez pas forcément à ce qu’Android supprime les fichiers, il ne le fera que quandilenaurabesoin,iln’yapasdemanièredeprédirececomportement.

15.2.3. En externe

Le problème avec le stockage externe, c’est qu’il n’existe aucune garantie que vos fichiers soientprésents.L’utilisateurpourralesavoirsupprimésouavoirenlevélepériphériquedeson emplacement.Cependant,cettefoislatailledisponibledestockageestaurendez-vous!Enfin, quandnousparlonsdepériphériqueexterne,nousparlonsprincipalementd’unecarteSD,d’une cléUSB…ouencored’unordinateur!

!

Pourécriresurunpériphériqueexterne,ilvousfaudraajouterlapermissionWRITE_EXTER

NAL_STORAGE.Pourcefaire,ilfautrajouterlalignesuivanteàvotreManifest:<uses-per

 

String

En

vi

ron

tEx

ter

nal

Sto

ra

geS

tate()

Tout d’abord, pour vérifier que vous avez bien accès à la mémoire externe, vous pouvez utiliserlaméthodestatique.Lachaîne decaractèresretournéepeutcorrespondreàplusieursconstantes,dontlaplusimportantereste

En

vi

ron

DIA_MOUN

TED

pour savoir si le périphérique est bien monté et peut être lu

En

vi

ron

DIA_MOUN

TED_READ_ONLY

(pourunpériphériquebienmontémaisquinepeutpasêtrelu,onutilisera ):

Voustrouverezd’autresstatutsàutiliserdansladocumentation .

File

En

vi

ron

tEx

ter

nal

Sto

ra

ge

Di

rec

tory()

/An

droid/data/<votre_pa

Afin d’obtenir la racine des fichiers du périphérique externe, vous pouvez utiliser la méthode statique. Cependant, il est conseilléd’écriredesfichiersuniquementàunemplacementprécis:

ckage>/files/.Eneffet,lesfichiersquisetrouventàcetemplacementserontautomatiquement supprimésdèsquel’utilisateureffaceravotreapplication.

15.2.3.1. Partager des fichiers

/Mu

sic/

 

/Down

load/

/Ring

tones/

Il arrive aussi que votre utilisateur veuille partager la musique qu’il vient de concevoir avec d’autresapplicationsdutéléphone,pourlamettreensonnerieparexemple.Cesontdesfichiers quinesontpasspécifiquesàvotreapplicationouquel’utilisateurnesouhaiterapassupprimer àladésinstallationdel’application.Onvadoncfaireensortedesauvegardercesfichiersàdes endroitsspécifiques.Unepetitesélectionderépertoires:pourlamusiqueonmettralesfichiers dans           ,pourlestéléchargementsdiversonutilisera     etpourlessonneries detéléphoneonutilisera.

15.2.4. Application

15.2.4.1. Énoncé

Trèssimple,onvafaireensorted’écrirevotrepseudodansdeuxfichiers:unenstockageinterne, l’autreenstockageexterne.N’oubliezpasdevérifierqu’ilestpossibled’écriresurlesupport externe!

15.2.4.2. Détails techniques

En

vi

ron

DIA_MOUN

Il existe une constante qui indique que le périphérique est en lecture seule (et que par conséquent il est impossible d’écrire dessus), c’est la constante TED_READ_ONLY.

boo

lean

crea

te

New

File()

Siunfichiern’existepas,vouspouvezlecréeravec.

15.2.4.3. Ma solution

 

Sha

red

Pre

fe

— Ilestpossibled’enregistrerlespréférencesdel’utilisateuraveclaclasse rences.

fe

ren

ceAc

ti

vity

 

Check

Box

— Pourpermettreàl’utilisateurdesélectionnersespréférences,onpeutdéfinirunePre qui facilite le processus. On peut ainsi insérer des , des

Edit

Text

,etc.

— Il est possible d’enregistrer des données dans des fichiers facilement, comme en Java. Cependant,ontrouvedeuxendroitsaccessibles:eninterne(surunemplacementmémoire réservé à l’application sur le téléphone) ou en externe (sur un emplacement mémoire amovible,commeparexempleunecarteSD).

— Enregistrerdesdonnéessurlecachepermetdesauvegarderdesfichierstemporairement.


16.   TP : un explorateur de fichiers

Petitàpetit,onserapproched’uncontenuquipourraits’apparenteràceluidesapplications professionnelles.Bienentendu,ilnousresteducheminàparcourir,maisoncommenceàvraiment voircommentfonctionneAndroid!

Afindesymbolisernotreentréedanslesentraillesdusystème,onvas’affairericiàdéambuler danssesméandres.Notreobjectif:créerunpetitexplorateurquipermettradenaviguerentreles fichierscontenusdansleterminaletfaireensortedepouvoirexécutercertainsdecesfichiers.

16.1. Objectifs

16.1.1. Contenu d’un répertoire

L’activitéprincipaleaffichelecontenudurépertoiredanslequelonsesitue.Afindedifférencier rapidementlesfichiersdesrépertoires,cesderniersserontreprésentésavecunecouleurdifférente.

Lafiguresuivantevousdonneunavant-goûtdecequel’onobtiendra.

 

Figure 16.1.–Ledernierrépertoirequecontientlerépertoirecourantest«yume_android_sdk »

sd

card

Notezaussiqueletitredel’activitéchangeenfonctiondurépertoiredanslequelonsetrouve. On voit sur la figure précédente que je me trouve dans le répertoire, lui-même situé dansmnt.

16.1.2. Navigation entre les répertoires

Re

tour Ar

Re

tour Ar

rière

Sioncliquesurunrépertoiredanslaliste,alorsnotreexplorateurvaentrerdedansetafficher lanouvellelistedesfichiersetrépertoires.Deplus,sil’utilisateurutiliselebouton rière,alorsilreviendraaurépertoireparentdurépertoireactuel.Enrevanche,sionsetrouve àlaracinedetouslesrépertoires,alorsappuyerdeuxfoissurfaitsortirde l’application.

16.1.3. Préférences

Ilfaudraunmenuquipermetd’ouvrirlespréférencesetoùilserapossibledechangerlacouleur d’affichagedesrépertoires,commeàlafiguresuivante.

 

Figure 16.2.–L’applicationcontiendraunmenudepréférences

Cliquersurcetteoptionouvreuneboîtededialoguequipermetdesélectionnerlacouleurvoulue, commelemontrelafiguresuivante.

 

Figure 16.3.–Ilserapossibledemodifierlacouleurd’affichagedesrépertoires

16.1.4. Action sur les fichiers

Cliquersurunfichierfaitensortederechercheruneapplicationquipourralelire.Faireunclic longouvreunmenucontextuelquipermetsoitdelancerlefichiercommeavecunclicnormal, soitdesupprimerlefichier,ainsiquelemontrelafiguresuivante.

 

Figure 16.4.–Ilestpossibled’ouvriroudesupprimerunfichier

Biensûr,faireuncliclongsurunrépertoireneproposepasd’exécutercedernier(onpourrait envisagerdeproposerdel’ouvrir,j’aioptépoursupprimerdirectementl’option).

16.2. Spécifications techniques

16.2.1. Activité principale

16.2.1.1. Un nouveau genre d’activité

List

View

List

View

Ac

ti

vity

 

Lis

tAc

ti

vity

 

Lis

tAc

ti

vity

List

View

Ac

ti

vity

void

set

Con

tent

View

(View

view)

Lapremièrechoseàfaireestdevérifierqu’ilestpossibledelirelacarteSDaveclesméthodesvues auxchapitresprécédents.S’ilestbienpossibledelirelacarte,alorsonaffichelalistedesfichiers durépertoire,cequiseferadansune.Cependant,commenotremiseenpagesera uniquementconstituéed’uneliste,nousallonsprocéderdifféremmentparrapportàd’habitude. Aulieud’avoiruneactivitéquiafficheunlayoutquicontientune,onvaremplacer notre parune .Commel’indiquelenom,une estune activitéquiestprincipalementutiliséepourafficherune.Commeils’agitd’uneclasse qui dérive de, il faut la traiter comme une activité normale, si ce n’est que vous n’avezpasbesoindepréciserunlayoutavec,puisqu’on saitqu’iln’yaqu’unelistedanslamiseenpage.Elleseraalorsajoutéeautomatiquement.

List

View

 

Lis

tAc

ti

vity

Il est possible de récupérer la                          qu’affiche la                                 à l’aide de la méthode

List

View

get

List

View

()

 

List

View

 

List

View

                                                                   . Cette                     est une                         tout à fait banale que vous

pouveztraitercommecellesvuesdanslecours.

16.2.1.2. Adaptateur personnalisé

Onassocieralesitemsàlalisteàl’aided’unadaptateurpersonnalisé.Eneffet,c’estlaseule solutionpouravoirdeuxcouleursdanslesélé’oublierapasd’optimiser cetadaptateurafind’avoirunelistefluide.Ensuite,onvoudraquelesélémentssoienttriésde lamanièresuivante:

— Lesrépertoiresenpremier,lesfichiersensecond.

— Danschacunedecescatégories,lesélémentssonttriésdansl’ordrealphabétiquesans tenircomptedelacasse.

void

sort

(Com

pa

ra

tor<?

su

per

T>

com

pa

ra

tor)

Pourcela,onpourrautiliserlaméthode

Com

pa

ra

tor

int

com

pare(T

lhs,

quipermetdetrierdesélémentsenfonctionderèglesqu’onluipasseenparamèègles implémentent l’interfacede manière à pouvoir définir comment seront triés les objets.Votreimplémentationdecetteinterfacedevraredéfinirlaméthode

Trhs)dontl’objectifestdedirequiestleplusgrandentrelhsetrsh.Silhsestplusgrand querhs,onrenvoieunentiersupérieurà0,silhsestpluspetitquerhs,onrenvoieunentier inférieurà0,ets’ilssontégaux,onrenvoie0.Vousdevrezvérifierquecetteméthoderespectela logiquesuivante:

com

pare(a,a)

com

pare(a,b)

com

pare(b,a)

—renvoie0pourtoutaparcequea==a.

com

pare(a,b)

 

com

pare(b,a)

—renvoie l’opposé depour toutes les paires (a,b) (par exemple,sia > b,alors renvoieunentiersupérieurà0et unentierinférieurà0).

com

pare(a,b)

>0

 

com

pare(b,c)

>0

 

com

pare(a,c)

— Si          et         ,alors   0quelquequesoit lacombinaison(a,b,c).

Jecomprendsquecesoitunpeucompliquéàcomprendre,alorsvoiciunexemplequitrieles entiers:

 

Ensuite,danslecode,onpeutl’utiliserpourtrieruntableaud’entiers:

 

16.2.2. Préférences

re

per

toi

re

Co

lor

Pref

Nousn’avonsqu’unepréférenceici,quichezmoiapouridentifiantet quicontientlacouleurdanslaquellenoussouhaitonsafficherlesrépertoires.

Co

lor

Pi

cker

View

Comme il n’existe pas de vue qui permette de choisir une couleur, on va utiliser une vue développée par Google dans ses échantillons et qui n’est pas incluse dans le code d’Android. Toutcequ’ilfautfaire,c’estcréerunfichierJavaquis’appelleetd’yinsérer lecodesuivant:

 

Cen’estpasgravesivousnecomprenezpascecodecompliqué,ilpermetjusted’afficherlejoli ronddecouleuretdesélectionnerunecouleur.Enfait,lavuecontientunlistenerquis’appelle

On

Co

lor

Chan

ged

Lis

te

ner

.Celistenersedéclenchedèsquel’utilisateurchoisitunecouleur.

Co

lor

Pi

cker

View

 

Co

lor

Pi

Afin de créer un objet de type                                           , on doit utiliser le constructeur

cker

View(Context

c,

On

Co

lor

Chan

ged

Lis

te

ner

lis

te

ner,

int

co

lor)

 

lis

te

ner

co

lor

avec lelistenerquiseradéclenchédèsqu’unecouleurestchoisieetlacouleurquiserachoisie pardéfautaulancementdelavue.

Co

lor

Pi

cker

View

Notrepréférence,elle,serauneboîtededialoguequiafficherace.Comme il s’agira d’une boîte de dialogue qui permettra de choisir une préférence, elle dérivera de

Dia

log

Pre

fe

rence

.

void

on

Pre

pa

re

Aumomentdelaconstructiondelaboîtededialogue,laméthodedecallback

Dia

log

Buil

der(Buil

der

buil

der)

 

Alert

Dia

log

                                                                                            est appelée, comme pour toutes les                             . On

buil

der

Alert

Dia

der

set

View(View

view)

utilisepourconstruirelaboîte,ilestd’ailleursfaciled’yinsérerunevueàl’aidedela méthode.

On

Co

lor

Chan

ged

Lis

te

ner

On

Co

lor

Chan

ged

Lis

te

ner

void

co

lor

Chan

ged(int

co

lor)

 

co

lor

Notre préférence a un attribut de type int qui permet de retenir la couleur que choisit l’utilisateur.Ellepeutavoirunattributdetypeouimplémenter elle-même, dans tous les cas cette implémentation implique de redéfinirlafonction avec lacouleurquiaétéchoisie.

Dèsquel’utilisateurchoisitunecouleur,onchangenotreattributpourdésignercettenouvelle couleur.

void

on

Dia

log

Clo

sed(boo

lean

po

si

ti

ve

Re

sult)

On n’enregistrera la bonne couleur qu’à la fermeture de la boîte de dialogue, celle-ci étant marquéeparl’appelàlaméthodeavec

po

si

ti

ve

Re

sult

quivauttruesil’utilisateuracliquésurOK.

16.2.2.1. Réagir au changement de préférence

On

Sha

red

Pre

fe

ren

ce

Chan

ge

Lis

te

ner

void

on

Sha

red

Pre

fe

ren

ce

Chan

ged(Sha

red

Pre

fe

rences

sha

red

Pre

fe

rences,

String

key)

 

sha

red

Dèsquel’utilisateurchangedecouleur,ilfaudraitquecechangementserépercuteimmédiatement surl’affichagedesrépertoires.Ilnousfautdoncdé cela, on va utiliser l’interface. Cette interface fait appel à la méthode de callback dèsqu’unchangementdepréférencearrive,avec

Pre

fe

rences

l’ensembledespréférencesetkeylaclédelapréférencequivientd’êtremodifiée.

Sha

red

Pre

fe

rences

On peut indiquer àqu’on souhaite ajouter un listener à l’aide de la

void

re

gis

te

rOn

Sha

red

Pre

fe

ren

ce

Chan

ge

Lis

te

ner

(Sha

red

Pre

fe

méthode

Sha

red

Pre

fe

ren

ce

Chan

ge

Lis

te

ner

lis

te

ner)

.

16.2.3. Options

Pre

fe

ren

ceAc

ti

vity

Ouvrirlemenud’optionsnepermetd’accéderqu’àuneoption.Cliquersurcelle-cienclencheun intentexplicitequiouvrirala.

16.2.4. Navigation

boo

lean

is

Di

rec

tory()

File[]

list

Files()

IlestrecommandédeconserverunFilequireprésentelerépertoirecourant.Onpeutsavoir si un fichier est un répertoire avec la méthodeet, s’il s’agit d’un répertoire,onpeutvoirlalistedesfichiersqu’ilcontientavec.

boo

lean

on

Key

Down(int

key

Code,

KeyEvent

Poureffectuerdesretoursenarrière,ilfautdétecterlapressionduboutonadéquat.Àchaquefois qu’onpresseunbouton,laméthodedecallback

key

Code

Re

tour ar

rière

 

CODE_BACK

event)estlancée,avecuncodequireprésenteleboutonpresséeteventl’évènement quis’estproduit.Lecodedubouton est .

Ilexistedeuxcaspourunretourenarrière:

File

get

Pa

rent

File()

— Soitonnesetrouvepasàlaracinedelahiérarchiedefichier,auquelcasonpeutrevenir enarrièredanscettehiérarchie.Ilfautpasseraurépertoireparentdurépertoireactuel etcerépertoirepeutserécupéreraveclaméthode.

void

fi

nish()

— Soitonsetrouveàlaracineetiln’estpaspossibledefaireunretourenarriè cas,onproposeàl’utilisateurdequitterl’applicationaveclaméthodedeContextque vousconnaissezdéjà,.

16.2.5. Visualiser un fichier

AC

TION_VIEW

File(File

file)

au

dio/mp3

au

dio/*

Nousallonsbienentenduutiliserdesintentsimplicitesquiaurontpouraction. Leproblèmeestdesavoircommentassocieruntypeetunedonnéeàunintent,depuisunfichier. Pour la donnée, il existe une méthode statique de la classe Uri qui permet d’obtenir l’URI d’unfichier:.Pourletype,c’estplusdélicat.Ilfaudradétecter l’extensiondufichierpourassocieruntypequicorresponde.Parexemple,pourunfichier.mp3, onindiqueraletypeMIME.Enfin,sionveutmoinss’embêter,onpeutaussipasser letypeMIMEpourchaquefichieraudio.

void

set

Pourrajouterunedonnéeetuntypeenmêmetempsàunintent,onutiliselaméthode

Da

taAnd

Type(Uri

data,

String

type)

 

void

set

Data(Uri)

,car,sionutiliselaméthode,

void

set

Type(String)

String

get

Name()

alors le champ type de l’intent est supprimé, et si on utilise, alors le champ data de l’intent est supprimé. Pour récupérer l’extension d’un fichier, il suffit de récupérersonnomavec,puisderécupérerunepartiedecenom:toutela partiequisetrouveaprèslepointquireprésentel’extension:

 

int

in

dexOf(String

str)

va trouver l’endroit où se trouve la première instance de str

String

sub

string(int

be

gi

nIn

dex)

be

gi

nIn

dex

chan

son.mp3

dans la chaîne de caractères, alors queva extraire la sous-chaîne de caractères qui se situe à partir dejusqu’à la fin de cette chaîne. Donc,silefichiers’appelle,lapositiondupointest7(puisqu’oncommenceà0), onprenddonclasous-chaîneàpartirducaractère8jusqu’àlafin,cequidonne«mp3».C’est lamêmechosequesionavaitfait:

 

16.3. Ma solution

16.3.1. Interface graphique

List

View

set

Con

tent

View

Facile,iln’yenapas!Commenotreactivitéestconstituéeuniquementd’une,pas besoindeluiattribueruneinterfacegraphiqueavec.

16.3.2. Choisir une couleur avec ColorPickerPreferenceDialog Toutleraisonnementadéjàétéexpliquédanslesspécificationstechniques:

 

IlfautensuiteajoutercetteboîtededialoguedanslefichierXMLdespréférences:

 

Ilsuffitensuitededéclarerl’activitédansleManifest:

 

…puisdecréerl’activité:

 

16.3.3. L’activité principale

16.3.3.1. Attributs

Voicilesdifférentsattributsquej’utilise:

 

On

Sha

red

Pre

fe

ren

ce

Chan

ge

Lis

te

ner

Comme je fais implémenterà mon activité, je dois redéfinirlaméthodedecallback :

 

16.3.3.2. L’adaptateur

Adap

ter

J’utilise unque j’ai créé moi-même afin d’avoir des items de la liste de différentes couleurs:

 

16.3.3.3. Méthodes secondaires

Ensuite,j’aiuneméthodequipermetdeviderl’adaptateur:

 

J’aiaussidéveloppéuneméthodequimepermetdepasserd’unrépertoireàl’autre:

 

on

Key

Down

Cetteméthodeestd’ailleursutiliséeparlaméthodedecallback:

 

16.3.3.4. Gestion de l’intent pour visualiser un fichier

 

16.3.3.5. Les menus

Riend’étonnantici,normalementvousconnaissezdéjàtout.Ànoterquej’aiutilisédeuxlayouts pourlemenucontextueldemanièreàpouvoirlechangerselonqu’ils’agitd’unrépertoireou d’unfichier:

 

16.3.3.6. onCreate

Voicilaméthodeprincipaleoùsesituenttouteslesinitialisations:

 

16.4. Améliorations envisageables

16.4.1. Quand la liste est vide ou le périphérique externe est indisponible

Lis

tAc

ti

vity

List

View

Lis

tAc

ti

vity

List

View

 

an

droid:id="@an

droid:id/list"

an

droid:id="@an

droid:id/empty"

Onsetrouveenfaced’unécranblancpastrèsintéressant…Cequipourraitêtreplusexcitant, c’est un message qui indique à l’utilisateur qu’il n’a pas accès à ce périphérique externe. On peutfaireçaenindiquantunlayoutpournotre!Oui,jesais,jevousaiditde ne pas le faire, parce que notre activité contient principalement une liste, mais là on pousse le concept encore plus loin. Le layout qu’on utilisera doit contenir au moins une pour représenter celle de notre, mais notre application sera bien incapable de la trouver si vous ne lui précisez pas où elle se trouve. Vous pouvez le faire en mettant comme identifiant à la. Si vous voulez q’un widget ou un layout s’affiche quand la liste est vide, vous devez lui attribuer l’identifiant .Pourmacorrection,j’aileXMLsuivant:

 

16.4.2. Détection automatique du type MIME

Mi

me

Ty

pe

Map

Mi

me

Ty

pe

Map

Mi

me

Ty

pe

Sin

gle

ton()

Parcequefaireunelonguelistede«Sionacetteextensionpourcefichier,alorsletypeMIME, c’estcelui-là»estquandmêmelongetcontraignant,jevousproposededétecterautomatiquement letypeMIMEd’unobjet.Pourcela,onutiliseraunobjetdetype.Afinderécupérer cetobjet,onpasseparlaméthodestatique.

i

Petitedigressionpourvousdirequeledesign pattern singletonapourobjectifdefaire ensortequevousnepuissiezavoirqu’uneseuleinstanced’unobjet.C’estpourquoion utiliselaméthodegetSingleton()quirenvoietoujourslemêmeobjet.Ilestimpossible deconstruireautrementunobjetdetypeMimeTypeMap.

get

Mi

me

Ty

pe

Fro

mEx

ten

sion(String

Ensuitec’estsimple,ilsuffitdedonneràlaméthodeString

ex

ten

sion)

l’extensiondenotrefichier.Onobtientainsi:

 

16.4.3. Détecter les changements d’état du périphérique externe

AC

TION_ME

DIA_RE

MO

VED

AC

TION_ME

DIA_MOUN

TED

C’est bien beau tout ça, mais si l’utilisateur se décide tout à coup à changer la carte SD en pleineutilisation,nousferonsfaceàungrosplantage!Alorscommentcontrercesouci?C’est simple.Dèsquel’étatdupériphériqueexternechange,unbroadcastintentesttransmispourle signaleràtoutlesystème.Ilexistetoutuntasd’actionsdifférentesassociéesàunchangement d’état, je vous propose de ne gérer que le cas où le périphérique externe est enlevé, auquel casl’actionest.Notezaupassagequel’actionpourdirequelacarte fonctionneànouveauest.

broad

cast re

cei

ver

Commenousl’avonsvudanslecours,ilfaudradéclarernotredansle

Manifest:

 

re

cei

ver

broad

cast Intent

AC

TION_ME

DIA_MOUN

TED

Ensuite,dansleenlui-même,onfaitensortedeviserlalistedesélémentss’ilyaun problèmeaveclepériphériqueexterne,ouaucontrairedelarepeuplerdèsquelepériphérique fonctionne correctement à nouveau. À noter que dans le cas d’unavec l’action, l’intent aura dans son champ data l’emplacement de la racinedupériphériqueexterne:

 

17.   Les bases de données

Cequenousavonsvuprécédemmentestcertesutile,maisnerépondrapasàtousnosbesoins. Nousavonsbesoind’unmoyenefficacedestockerdesdonnéescomplexesetd’yaccé,il nous faudrait des années pour concevoir un système de ce style. Imaginez le travail s’il vous fallait développer de A à Z une bibliothèque multimédia qui puisse chercher en moins d’une secondeparmiplusde100000titresunechansonbienprécise!C’estpourcelaquenousavons besoindesbasesdedonnées,quisontoptimiséespourcetypedetraitements.

LesbasesdedonnéespourAndroidsontfourniesàl’aidedeSQLite  L’avantagedeSQLite estqu’ils’agitd’unSGBDtrèscompactetparconséquenttrèsefficacepourlesapplications embarquées,maispasuniquementpuisqu’onletrouvedansSkype,AdobeReader,Firefox,etc.

17.1. Généralités

Vous comprendrez peut-être ce chapitre même si vous n’avez jamais manipulé de bases de donnéesauparavant.Tantmieux,maiscelanesignifiepasquevousserezcapablesdemanipuler correctementlesbasesdedonnéespourautant.C’estunevraiesciencequed’agencerlesbases dedonnéesetilfautbeaucoupplusdethéoriequenousn’enverronsicipourmodéliserpuis réaliserunebasededonnéescohérenteetefficace.

Ilvousestpossibled’apprendreàutiliserlesbasesdedonnéesetsurtoutMySQLgrâceaucours «AdministrezvosbasesdedonnéesavecMySQL  »rédigéparTaguan  .

17.1.1. Sur les bases de données

Une base de données est un dispositif permettant de stocker un ensemble d’informations de manièrestructurée.L’agencementadoptépourorganiserlesinformationss’appellele schéma.

L’unité de base de cette structure s’appelle la table. Une table regroupe des ensembles d’informations qui sont composés de manière similaire. Une entrée dans une table s’appelle un enregistrement, ou un tuple. Chaque entrée est caractérisée par plusieurs renseignements distincts,appelésdes champs ou attributs.

Parexemple,unetablepeutcontenirleprénom,lenometlemétierdeplusieursutilisateurs,on aura donc pour chaque utilisateur les mêmes informations. Il est possible de représenter une tableparuntableau,oùleschampsserontsymbolisésparlescolonnesdutableauetpourlequel chaquelignereprésenterauneentréedifférente.Regardezlafiguresuivante,celadevraitêtre plusclair.

 

Figure 17.1.–Cettetablecontientquatretuplesquirenseignenttoutesdesinformationsdu mêmegabaritpourchaqueattribut

Pré

nom

Unemanièresimpled’identifierlesélémentsdansunetableestdeleurattribuerune clé.C’està-direqu’onvachoisirunecombinaisondechampsquipermettrontderécupérerdemanière uniqueunenregistrement.Danslatableprésentéeàlafiguresuivante,l’attributNompeutêtre uneclépuisquetouteslesentréesontunNomdifférent.Leproblèmeestqu’ilpeutarriverque deuxutilisateursaientlemêmenom,c’estpourquoionpeutaussienvisagerlacombinaisonNom etcommeclé.

 

Figure 17.2.–OnchoisitcommeclélacombinaisonNom-Prénom

Iln’estpasrarequ’unebasededonnéesaitplusieurstables.Afindelierdestables,ilestpossible d’insérer dans une table une clé qui appartient à une autre table, auquel cas on parle de clé étrangère pourlatablequiaccueillelaclé,commeàlafiguresuivante.

 

Figure 17.3.–Dansnotrepremièretable,Métierestunecléétrangère,carelleestcléprimaire delasecondetable

Il est possible d’effectuer des opérations sur une base de données, comme créer des tables, supprimerdesentrées,etc.L’opérationquiconsisteàliredesinformationsquisetrouventdans unebasededonnéess’appellela sélection.

Poureffectuerdesopérationssurplusieurstables,onpasseparune jointure,c’est-à-direqu’on combinedesattributsquiappartiennentàplusieurstablespourlesprésenterconjointement.

Afin d’effectuer toutes ces opérations, on passe par un langage de requête. Celui dont nousavonsbesoins’appelle SQL.Nousverronsunrappeldesopérationsprincipalesdansce chapitre.

Enfin, une base de données est destinée à recueillir des informations simples, c’est pourquoi onévited’yinsérerdesdonnéeslourdescommedesfichiersoudesdonnéesbrutes.Aulieude mettredirectementdesimagesoudesvidéos,onpréfèrerainsérerunURIquidirigeversces fichiers.

17.1.2. Sur SQLite

Contrairement à MySQL par exemple, SQLite ne nécessite pas de serveur pour fonctionner, ce qui signifie que son exécution se fait dans le même processus que celui de l’application. Parconséquent,uneopérationmassivelancéedanslabasededonnéesauradesconséquences visibles sur les performances de votre application. Ainsi, il vous faudra savoir maîtriser son implémentationafindenepaspénaliserlerestantdevotreexécution.

17.1.3. Sur SQLite pour Android

/data/data/<pa

ckage>/da

ta

bases

MODE_PRI

VATE

SQLiteaétéinclusdanslecœurmêmed’Android,c’estpourquoichaqueapplicationpeutavoir sa propre base. De manière générale, les bases de données sont stockées dans les répertoires de la forme. Il est possible d’avoir plusieurs bases de donnéesparapplication,cependantchaquefichiercréél’estselonlemode,par conséquentlesbasesnesontaccessiblesqu’auseindel’applicationelle-même.Notezquecen’est paspourautantqu’unebasededonnéesnepeutpasêtrepartagéeavecd’autresapplications.

Enfin,pourdesraisonsquiserontexpliquéesdansunchapitreultérieur,ilestpréférabledefaire ensortequelaclédechaquetablesoitunidentifiantquis’incrémenteautomatiquement.Notre schémadevientdonclafiguresuivante.

 

Figure 17.4.–Unidentifiantaétéajouté

17.2. Création et mise à jour

SQ

Li

teO

pen

Hel

per

void

on

Create(SQ

Li

te

Da

ta

base

La solution la plus évidente est d’utiliser une classe qui nous aidera à maîtriser toutes les relationsaveclabasededonnées.Cetteclassedériverade.Aumomentde lacréationdelabasededonnées,laméthodedecallback

db)estautomatiquementappelée,avecleparamètredbquireprésenteralabase.C’estdanscette méthodequevousdevrezlancerlesinstructionspourcréerlesdifférentestablesetéventuellement lesrempliravecdesdonnéesinitiales.

Me

tier

Pourcréerunetable,ilvousfaudraréfléchiràsonnometàsesattributs.Chaqueattributsera définiàl’aided’untypededonnées.Ainsi,danslatabledenotreexemple,nousavons troisattributs:

— ID,quiestunentierauto-incrémentalpourreprésenterlaclé;

tier

Sa

laire

—,quiestunechaînedecaractères; —,quiestunnombreréel.

PourSQLite,c’estsimple,iln’existequecinqtypesdedonnées:

— NULLpourlesdonnéesNULL.

IN

TE

GER

—pourlesentiers(sansvirgule).

— REALpourlesnombresréels(avecvirgule).

— TEXTpourleschaînesdecaractères.

— BLOBpourlesdonnéesbrutes,parexemplesivousvoulezmettreuneimagedansvotre basededonnées(cequevousneferezjamais,n’est-cepas?). Lacréationdetablesefaitavecunesyntaxetrèsnaturelle:

 

Pourchaqueattribut,ondoitdéclareraumoinsdeuxinformations:

— Sonnom,afindepouvoirl’identifier; — Sontypededonnée.

Maisilestaussipossiblededéclarerdescontraintespourchaqueattributàl’emplacementde {contraintes}.Ontrouvecommecontraintes:

PRI

MARY

KEY

—pourdésignerlacléprimairesurunattribut;