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.

  1. 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"

  2. 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 () + " " + ...

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

  1. 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"

  2. 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

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

  2. 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) ;

  3. 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"

  1. 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

  2. Créer un objet Creator pour reconstruire les données à partir d'un Parcel

    • http://developer.android.com/reference/android/os/Parcelable.html

  3. 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) ;

  4. 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

  1. 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"...

  2. Modifier ce fichier de ressources en conséquence

  3. Tester la nouvelle application suite à un changement de langue du téléphone

Cinquième partie : autres exemples de communication par Intents

  1. Demander à voir le contenu du carnet d'adresses

      • Intent intent = new Intent (Intent.ACTION_VIEW, Uri.parse ("content://contacts/people/")) ;

      • startActivity (intent) ;

  2. 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 ;