TP Prise en main d'android
Ce TP est très largement inspiré des TP de l'ISTIC réalisés par Marc Christie en 2013, en M2 Mitic et GL.
Première partie : création d'une IHM et association de quelques interactions.
Créer un projet Android (File / New Project...)
nommer le fichier principal du projet : "MainActivity.java"
nommer le fichier de description de l'IHM : "activity_main.xml"
Créer une IHM
avec des composants graphiques permettant de saisir les éléments suivants :
nom (TextView + EditText)
prénom (TextView + EditText)
date de naissance (TextView + EditText approprié ou éventuellement un widget Android spécifique)
ville de naissance (TextView + EditText)
définir les intitulés des textes dans le fichier de ressource "strings.xml"
Utiliser les "layouts" adéquats pour une présentation correcte de ces composants
Par exemple un "LinearLayout" vertical contenant quatre "LinearLayout"s horizontaux
Ajouter un bouton "Valider" qui prend toute la largeur de l'écran
Associer une action à ce bouton valider :
association de l'action :
soit directement dans le fichier XML de description de l'IHM (à la main ou via l'interface de développement d'AndroidStudio) :
android:onClick="actionValider"
il faut ensuite ajouter une méthode "public void actionValider (View v)" dans votre fichier "MainActivity.java"
soit via l'ajout d'un listener dans le fichier "MainActivity.java" :
il faut alors récupérer le bouton : Button b = (Button)findViewById (R.id.buttonValider) ;
et lui associer un listener : b.setOnClickListener (new View.OnClickListener () { ... }) ;
dans lequel on redéfinit la méthode : public void onClick (View v) { ... }
documentation éventuelle à consulter :
http://developer.android.com/reference/android/widget/Button.html
action à réaliser :
cette action consistera à afficher à l'écran un résumé des informations saisies par l'utilisateur à l'aide de la classe Toast
Toast.makeText(getApplicationContext(), textToShow, Toast.LENGTH_SHORT).show () ;
où il faudra avoir rempli la chaine textToShow avec les contenus des champs saisis par l'utilisateur
pour cela il faudra encore récupérer ces champs avec la fonction findViewById :
EditText etNom = (EditText)findViewById (R.id.editTextNom) ;
et les utiliser pour initialiser la chaîne à afficher :
String textToShow = new String ("" + etNom.getText () + " " + ...
Créer un menu en XML (menu_main.xml dans le répertoire res/menu) qui sera appelé par la touche menu du smartphone
ce menu devra permettre :
la remise à zéro des données des champs de saisie de l'IHM
l'ajout d'un composant graphique permettant l'ajout d'un numéro de téléphone dans les éléments de l'IHM
récupérer pour cela l'identifiant du layout contenant les éléments et y ajouter le (ou les) composant (s) graphique(s) à l'aide de ViewGroup.addView (...)
il faut ajouter des items dans le menu, dans le fichier menu_main.xml :
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/actionRaz" android:title="@string/RAZ"></item>
</menu>
pour afficher le menu il faut implémenter/étendre la méthode dans MainActivity.java :
public boolean onCreateOptionsMenu (Menu menu)
et y insérer votre menu XML sous la forme d'un objet Java Menu :
getMenuInflater ().inflate (R.menu.menu, menu) ;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
pour appeler les actions liées aux items, il faut soit (mauvaise méthode car il faut ensuite faire des vérifications sur l'item sélectionné) implémenter dans MainActivity.java la méthode :
public boolean onOptionsItemSelected (MenuItem item)
soit (bonne méthode car lien direct avec l'action à réaliser) :
indiquer dans le fichier menu_main.xml quelle action est associée à chaque item de menu :
<item android:id="@+id/actionRaz" android:title="@string/RAZ" android:onClick="actionRAZ"></item>
et implémenter dans MainActivity.java la méthode :
public boolean actionRAZ (MenuItem item)
Ajouter à l'IHM la possibilité de saisir le département de naissance à l'aide d'un composant de type Spinner
les valeurs peuvent être pré-saisies dans un tableau décrit dans un fichier XML departements.xml dans le répertoire res/values
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="departements">
<item>Côtes d\'Armor</item>
<item>Finistère</item>
<item>Ille et Vilaine</item>
<item>Morbihan</item>
</string-array>
</resources>
l'attribut entries du Spinner doit alors faire référence à ce fichier XML :
android:entries="@array/departements"
Ajouter une option au menu permettant d'invoquer un browser web en utilisant le mécanisme des "Intents" pour afficher la page wikipedia correspondant à la ville de naissance de l'utilisateur
spécifier l'action à réaliser et les données associées, par exemple demander à voir le résultat de la recherche de Brest sur wikipedia :
Intent intent = new Intent (Intent.ACTION_VIEW, Uri.parse ("http://fr.wikipedia.org/?search=" + "Brest")) ;
ensuite lancer l'intent : startActivity (intent) ;
Remarque : on utilise ici un mécanisme d'Intent implicite : c'est le système qui va devoir trouver/proposer une Activity capable de gérer une url.
Seconde partie : faire communiquer deux "Activity" différentes en utilisant le mécanisme des Intents explicites
Réaliser une seconde Activity Android : DisplayActivity : DisplayActivity.java + activity_display.xml
en étendant le projet existant et en lui ajoutant une seconde Activity
app / New / Activity / Blank Activity
en déclarant cette DisplayActivity dans le fichier AndroidManifest.xml
normalement AndroidStudio le fait tout seul...
en lui faisant afficher les informations saisies dans la première Activity :
nom, prénom, date de naissance, ville de naissance
via des composants adaptés (TextView par exemple)
Modifier la MainActivity (MainActivity.java) de façon à ce qu'un appui sur le bouton "Valider" lance le second Intent
créer un nouvel Intent :
Intent intent = new Intent (getApplicationContext (), DisplayActivity.class) ;
utiliser les champs "extra" de l'Intent pour transmettre les données
intent.putExtra ("nom", etNom.getText ().toString ()) ;
lancer la DisplayActivity
startActivity (intent) ;
Modifier la DisplayActivity (DisplayActivity.java) pour récupérer et afficher les données transmises
modifier la méthode protected void onCreate(Bundle savedInstanceState)
récupérer les champs à remplir
TextView tvNom = (TextView)findViewById (R.id.textViewNom) ;
les remplir avec les données récupérées dans les champs extra :
tvNom.setText (getIntent ().getStringExtra ("nom")) ;
Troisième partie : transférer les données en utilisant des objets "Parcelable"
Créer une classe qui implémente l'interface Parcelable et implémenter les méthodes :
describeContents ()
writeToParcel (Parcel dest, int flags)
utiliser Parcel.writeString (...) pour sérialiser les données dans dest
Créer un objet Creator pour reconstruire les données à partir d'un Parcel
http://developer.android.com/reference/android/os/Parcelable.html
Ajouter l'objet Parcelable à l'Intent
créer l'objet Parcelable
PersonalParcelableData ppd = new PersonalParcelableData () ;
renseigner son contenu, comme par exemple le nom de l'utilisateur :
ppd.setNom (etNom.getText ().toString ()) ;
faire de même pour toutes les autres caractéristiques de l'utilisateur
utiliser le champ "extra" de l'Intent pour transmettre cette donnée
intent.putExtra ("data", ppd) ;
Récupérer cette donnée dans la seconde Activity :
PersonalParcelableData ppd = getIntent ().getParcelableExtra ("data") ;
tvNom.setText (ppd.getNom ()) ;
faire de même pour les autres caractéristiques à afficher
Quatrième partie : gérer les langues
Différencier l'affichage des intitulés (nom, prénom, ...) en fonction de la langue du téléphone : créer un nouveau fichier de ressource
values -> New -> Values resource file -> strings.xml
avec "Locale" comme "chosen qualifiers" -> "en" ou "de" ou "br"...
Modifier ce fichier de ressources en conséquence
Tester la nouvelle application suite à un changement de langue du téléphone
Cinquième partie : autres exemples de communication par Intents
Demander à voir le contenu du carnet d'adresses
Intent intent = new Intent (Intent.ACTION_VIEW, Uri.parse ("content://contacts/people/")) ;
startActivity (intent) ;
Demander à récupérer un numéro à partir du carnet d'adresses (tiré du site android)
static final int REQUEST_SELECT_PHONE_NUMBER = 1 ;
.... // code créant l'interface et associant par exemple l'action à un bouton décrit dans la partie xml
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTelephone = (TextView) findViewById(R.id.tvTelephone);
}
public void actionValider (View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
if (intent.resolveActivity (getPackageManager()) != null) {
startActivityForResult (intent, REQUEST_SELECT_PHONE_NUMBER) ;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == RESULT_OK) {
// Get the URI and query the content provider for the phone number
Uri contactUri = data.getData();
String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor cursor = getContentResolver().query(contactUri, projection,
null, null, null);
// If the cursor returned is valid, get the phone number
if (cursor != null && cursor.moveToFirst()) {
int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String number = cursor.getString(numberIndex);
// Do something with the phone number
tvTelephone.setText (number) ;
}
}
}
TextView tvTelephone ;