Première application Android
Organisation des classes
Les packages
Une application Java est composée de dizaines voire de centaines de classes.
On range ces classes dans des packages, ce qui permet de rassembler les classes par fonctionnalités ou par responsabilités.
C'est une arborescence de packages, les premiers niveaux devant correspondre au nom du projet, précédé du nom de domaine du projet ou du créateur, inversé. Cela permet d'être certain que les packages sont uniques.
Voici un exemple d'arborescence pour une application "MaMeteo" bientot réalisée au Cnam, qui affiche des pictogrammes sur une carte pour indiquer le temps qu'il fait, à partir d'une requête à un serveur :
- fr.cnam.mameteo.
- fr.cnam.mameteo.maps.MapView.java
- fr.cnam.mameteo.maps.PictoMap.java
- fr.cnam.mameteo.server.RequestMeteo.java
- fr.cnam.mameteo.server.RequestXmlParser.java
- fr.cnam.mameteo.activity.MeteoActivity.java
Importer des packages
Java et Android, tout comme de nombreux développeurs indépendants fournissent des classes toutes-faites, prêtes à être inclues dans un projet.
Elles sont aussi rangées dans des packages, ces packages nous permettant de bien différencier nos classes de celles qui sont extérieures.
- Les classes de base de java sont dans le package java.
- Celles du framework Android sont dans le framework android.
Les packages java et android contiennent de nombreux sous-packages : android.bluetooth, android.database, android.view, java.lang, java.math, java.io, etc.
Les classes que nous utilisons doivent être importée dans nos classes par la commande import.
La commande import est optionnelle est quand on travaille dans le même package que la classe que l'on utilise, ou que l'on utilise les classes de base du package java.lang.
Préparation de l'environnement
Eclipse doit être lancé, l'emplacement du workspace choisi. C'est ici qu'Eclipse sauvegardera les projets et leurs fichiers.
Android SDK Manager
Accessible depuis le menu Window/Android SDK Manager.
Il faut commencer par installer le ou les plateformes qui nous interessent. Nous choisissons donc de travailler sur la version 2.3 (API 10).
Il suffit de cocher le dossier correspondant à cette version dans l'Android SDK Manager, et d'accepter les licences. Le téléchargement peut être long.
Android Virtual Device Manager
Accessible depuis le menu Window/Android Virtual Device Manager.
Il faut ensuite créer un émulateur à la version voulue, grace à l'Android Virtual Device Manager. Le plus simple consistant à choisir un "device definition" et à lui redéfinir la version de plateforme attendue (API 10).
Création du projet Android
Accessible depuis le menu File/New/Project... (et non pas Java project !).
Un projet Android doit être défini par :
- un nom "commercial"
- un nom de travail
- un package de base
- une version minimale de la plateforme, et les versions avec lesquelles notre application à été testée : API 10 pour tous.
- un theme : nous devons mettre "none" (aucun) car les themes proposés sont valides pour des versions d'API plus élevées.
Les écrans s'enchainent : nouveau projet -> info du projet -> options de créations -> génération d'une icone -> création de l'activity -> option de l'activity principale.
Après avoir validés ces écrans avec les valeurs par défaut (sauf pour les infos du projet), le squelette de notre projet est créé.
Lancement du programme
Pour lancer l'application que l'on vient de créer, il suffit d'utiliser le menu Run/RunLe layout
Le layout est basé sur des fichiers XML. Eclipse nous offre cependant la possibilité d'éditer certains éléments avec un éditeur graphique. On peut switcher de l'un à l'autre avec l'onglet en bas de page.
Attention, dans le mode graphique, les éléments proposés dépendent de la version d'API définie dans la barre d'outil au dessus du layout (petit robot vert). Il faut donc changer cette valeur pour ne voir que les éléments de notre version.
Le layout en XML
Pour le layout d'une activity, il faut absolument que l'élément parent soit de type Layout. Celui ci peut ensuite contenir des Views.
Les Layouts permettent d'organiser des Views, sachant que les Layout en sont eux même. Cela permet de les imbriquer les uns les autres pour arriver à la mise en page voulue.
Les 2 principaux Layouts sont le RelativeLayout et le LinearLayout.
Voici le code le plus simple pour utiliser le RelativeLayout :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout>
Et pour utiliser le LinearLayout :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:text="@string/hello_world" /> </LinearLayout>
Largeur et hauteur
Tous les élements dans un fichier de layout doivent définir les propriétés layout_width et layout_height. Les valeurs les plus courantes sont :- wrap_content : "englobe le contenu", prends la place dont l'élément à besoin. Dans le cas d'un texte ou d'une image, il prendra précisement la taille de l'élément
- match_parent : "correspond au parent", agrandi jusqu'a prendre la meme taille que le parent direct. Attention aux chevauchements si plusieurs éléments de même niveau ont cette valeur.
Identifier les éléments
Chaque élément peut être identifié avec un identifiant unique dans toute l'application. C'est indispensable lorsque l'on souhaite intervenir dessus depuis le code Java, ou le positionner avec un RelativeLayout par exemple.
Il suffit d'ajouter l'attribut à l'élément :
android:id="@+id/identifiantdelelement"
Le LinearLayout
C'est le layout le plus simple. Tous ces enfants sont placés les uns à la suite des autres, verticalement ou horizontalement, selon l'attribut orientation.
Comme tous les autres layouts, il peut être imbriqué.
Plus d'infos sur la documentation : http://developer.android.com/guide/topics/ui/layout/linear.html
Exercice
Comment réaliser une mise en page de ce genre ?
Le RelativeLayout
Plus complexe que le linearLayout, il est aussi beaucoup plus puissant. Il permet de placer des éléments les uns par rapport aux autre. Il nous oblige à identifier les éléments que l'on souhaite manipuler.- android:layout_below : place l'élément sous un autre élément
- android:layout_toRightOf : place l'élément à droite d'un autre élément
- android:layout_alignRight : place l'élément aligné à droite de l'élément
- android:layout_alignLeft : place l'élément aligné à gauche de l'élément
Par exemple, pour une mise en page de ce type :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello_world" android:gravity="center_horizontal" /> <TextView android:id="@+id/text2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" android:layout_below="@id/text1" android:layout_alignRight="@id/text1" /> <TextView android:id="@+id/text3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" android:layout_below="@id/text1" android:layout_alignLeft="@id/text1" /> </RelativeLayout>
Plus d'infos sur la documentation : http://developer.android.com/guide/topics/ui/layout/relative.html
Les views
Il existe de nombreux éléments pour construire un interface graphique. Chacun pourra être personnalisable selon son type.
Les plus communs sont :
- Les TextView : un simple texte.
- Les EditText : un texte éditable par l'utilisateur.
- Les Button : un bouton classique.
- Les ImageView : affiche un "drawable".
- Les TimePicker : un selecteur d'heure ou de date.
- Les CheckBox : une case à cocher
- etc...
Certains éléments réagissent à des interactions utilisateur, comme le click, la selection, le changement de date, etc.
Il est possible que notre code Java puisse être executé en réponse à un évenement utilisateur. Nous devons pour cela récupérer l'élément dans le code Java et indiquer que nous souhaitons être notifié de certains évenements.
Récuperation dans le code java
Du coté du XML, il faut commencer par identifier les éléments que l'on souhaite manipuler.
Ensuite, dans le code java, il faut utiliser la fonction findViewById( id ), et éventuellement caster le type attendu.
Par exemple pour récuperer un TextView identifié myText :
TextView monTexte = (TextView) findViewById(R.id.myText);
Pour un Button identifié myButton :
Button monBoutton = (Button) findViewById(R.id.myButton);
Ceci me permet d'avoir dans mon code Java une variable correspondant à mon texte, à mon bouton ou tout autre élément de mon XML.
A partir de la je peux modifier certaines de ses propriétés depuis le code.
Exemple
Layout
Soit une simple page :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/myText" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Salut" /> <Button android:id="@+id/myButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Cliquez !" /> </LinearLayout>
Activity
Le code de base de l'activity ...
package fr.cnam.premierprogramme; import android.os.Bundle; import android.app.Activity; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
...deviendra :
package fr.cnam.premierprogramme; import android.os.Bundle; import android.widget.TextView; import android.widget.Button; import android.app.Activity; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView monTexte = (TextView) findViewById(R.id.myText); monTexte.setText("Bonjour JAVA !"); Button monButton = (Button) findViewById(R.id.myButton); monButton.setText("Cliquez s'il vous plait !"); } }
Répondre à un Evenement
Une fois notre élément récupéré, on peut inscrire notre activity pour qu'elle soit notifiée de la réception d'un évenement donné.
La premiere étape consiste donc à indiquer à notre boutton par exemple que l'on souhaite être notifié lorsqu'il est est cliqué en appellant sa méthode setOnClickListener et en passant l'instance de notre activity.
Ensuite, il faut prévoir le code qui sera exécuté au moment du click. Pour cela on ajoute à notre classe : implements OnClickListener, et la fonction correspondante onClick.
package fr.cnam.premierprogramme; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.app.Activity; public class MainActivity extends Activity implements OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView monTexte = (TextView) findViewById(R.id.myText); monTexte.setText("Bonjour JAVA !"); Button monButton = (Button) findViewById(R.id.myButton); monButton.setText("Cliquez s'il vous plait !"); monButton.setOnClickListener(this); } @Override public void onClick(View v) { TextView monTexte = (TextView) findViewById(R.id.myText); monTexte.setText("CLICK!"); } }
Mise en pratique
Mise en pratique : Vérif Majorité
Créez une application qui affiche dans une TextView si la personne est majeure.
Version 1 :
L'age et le nom de la personne sont des variables dans l'activity. Le résultat s'affiche dès le lancement de l'application.
Version 2 :
La fenetre est composé de 2 champs textes éditables, d'un boutton, et d'un texte pour le resultat.
L'age et le nom de la personne sont des champs éditables. Le résultat s'affiche apres avoir cliqué sur le bouton.
Mise en pratique : Le choc des Titans Mobile
- Met en scène 2 personnages : celui du joueur, et un ennemi.
- Chaque personnage commence avec 20 points de vie.
- Le jeu se déroule sur plusieurs tours.
- A chaque tour, les 2 personnages s'attaquent "automatiquement" et font perdre à l'autre entre 1 et 6 points de vie (tirés au hasard).
- A la fin du tour, si au moins un personnage n'a plus de points de vie, la partie s’arrête.
- Si les 2 personnages n'ont plus de vie, on affiche « ex aequo ». Sinon, on affiche le nom du personnage vainqueur.
Version 1 :
Le jeu commence dès que l'application se lance.
Elle affiche le résultat sur la page dans une TextView.
Version 2 :
Au lancement, on affiche un bouton. Un click sur ce bouton lance et relance le jeu.
Version 3 :
2 champs texte pour le nom des participants. Le jeu refuse de se lancer s'il sont vides.
Version 4 :
Tour par tour : à chaque tour, on affiche 3 boutons : Attaque (+3 dégats aux 2 personnages à ce tour), défense (-3 dégats aux 2 personnages à ce tour) ou standard (dégats normaux ce tour). Le joueur doit choisir l'une des 3 stratégies à chaque tour, jusqu'a la fin du jeu.
Annexe pour la mise en pratique
Tirer un nombre au hasard entre 1 et 6 :
Pour obtenir un "long" :
double hasard = Math.random(); //entre 0.0 et 1.0 double hasardBorne = hasard * 5 //entre 0.0 et 5.0 long resultatLong = Math.round(hasardBorne) + 1; //entre 1 et 6
oulong resultatLong = Math.round(Math.random() * 5) + 1;
Pour obtenir un "int" :
long resultatLong = Math.round(Math.random() * 5) + 1; int resultatInt = (int) resultatLong;
ou
int resultatInt = (int) (Math.round(Math.random() * 5) + 1);
Recuperer le contenu "String" d'un EditText
String contenu = monEditText.getText().toString()
Obtenir un "int" à partir d'un String
int resultat = Integer.parseInt( string );