Mobile Operating System: Component Model in Android

McGraw-Hill
Page 1 sur 37Lecteur de document UniversityLib

Mobile Operating System: Component Model in Android

Software Development (Android OS) · notes

http://www.zeddini.com/cours-isi

SSyyssttèèmmee dd’’EExxppllooiittaattiioonn MMoobbiillee

CChh44.. LLee mmooddèèllee ddee ccoommppoossaannttss

-. NAVIGATION ENTRE ACTIVITÉS.-

[email protected]

© ISI – Tunis

Objectifs Une des caractéristiques d’Android est son approche fortement modulaire qui permet aux applications de collaborer entre elles. Une application est constituée de plusieurs composants, chacun de ces composants pouvant être réutilisé depuis une autre application ce qui évite ainsi de devoir réinventer la roue. Ce chapitre traite de ce modèle d’architecture, les différents types de composants, la façon de les invoquer et leur cycle de vie sont passés en revue.

Ressources : http://developer.android.com/ tout, tout, tout Cours, TD/TP, code http://www.u-picardie.fr/ferment/android http://www.vogella.com/android.html tutoriel http://saigeethamn.blogspot.fr/ tutoriel http://www.franck-simon.com cours tres complet l'Art du developpement, M. Murphy, Pearson livre simplePro Android 4, S Komatineni D MacLean, Apress livre complet Le livre écrit par Florent Garin « Android » Le livre de Mark Murphy chez Pearson Le cours de Victor Matos : http://grail.cba.csuohio.edu/~matos/notes/cis-493/Android-Syllabus.pdf Plusieurs livres : Android A Programmers Guide - McGraw Hill Professional Android Application Development - Wrox

2

4.1 UNE FORTE MODULARITÉ

Il y a plus d’une dizaine d’années, l’avènement des langages objets a fait naître l’espoir de pouvoir développer facilement des éléments de code réutilisables d’une application à l’autre. Malheureusement, si le paradigme objet, avec des notions telles que l’encapsulation, favorise la création de librairies, il n’en demeure pas moins que développer une portion de code réellement exploitable dans un contexte autre que celui d’origine n’est toujours pas chose aisée.

Pour faciliter la collaboration entre les éléments de programme, le modèle applicatif d’Android définit la notion de composants d’applications. Un composant est un module de l’application qui pourra être activé depuis un autre programme Android. Lorsqu’un module est activé, l’application à laquelle il appartient est lancée si nécessaire, il est donc exécuté dans son propre processus.

Les fonctionnalités du module sont donc réutilisées en mettant en œuvre des

communications interprocessus.

4.2 QUATRE FAMILLES DE COMPOSANTS

Android prévoit quatre catégories de composants :

• les objets de la classe Activity, • les objets de la classe Service, • les objets de la classe BroadcastReceiver, • et enfin les objets du type ContentProvider.

Les objets de ces types sont donc des morceaux de l’application qui pourront être invoqués par d’autres applications pour remplir une tâche précise. C’est un peu comme si le programme avait un point d’entrée officiel, celui de l’activité principale qui se lance lorsque l’utilisateur clique sur l’icône de l’application, et des points d’entrée alternatifs démarrés par d’autres programmes.

4.3 LA NAVIGATION ENTRE ACTIVITÉS

Les activités sont des composants centraux des applications. Ce sont également les composants les plus remarquables car ils portent les éléments visuels de l’interface utilisateur agencés sur l’écran.

La navigation entre les écrans peut se faire de deux façons différentes : soit explicitement, soit implicitement. Dans les deux cas, l’ordre de changement d’activité est véhiculé par un objet de type Intent (intention en anglais).

Dans le mode explicite, les activités s’enchaînent les unes aux autres par invocation

3

directe. C’est-à-dire qu’une activité donnée déclenche l’affichage d’une autre activité en appelant la méthode startActivity avec un Intent mentionnant clairement le nom de l’activité. On verra par la suite comment créer concrètement des objets Intent.

Le mode explicite est donc très classique : comme dans la plupart des applications, les écrans à afficher sont invariablement les mêmes d’une exécution à l’autre et identi- fiés à l’avance. Aucune particularité n’est à noter dans ce mode de fonctionnement si ce n’est qu’Android permet d’afficher des activités n’appartenant pas à l’application d’origine.

Le mode implicite par contre est une spécificité d’Android extrêmement puissante. Dans ce mode, le nom de l’activité n’est pas précisé nominativement. L’objet Intent qui encapsule la demande de changement ne porte pas l’identification de l’activité mais un descriptif des caractéristiques ou plutôt des capacités de traitement dont l’activité devra être dotée. Ensuite, une mécanique de résolution se met en marche, Android recherche dans tout le système, et non pas uniquement dans l’application courante, les activités répondant aux exigences exprimées dans l’Intent. À la fin de cet algorithme, l’activité identifiée s’affiche alors. Au cas où il y aurait plusieurs activités en mesure d’assurer le service demandé, leur liste est proposée à l’utilisateur qui devra alors en sélectionner une. Il peut arriver aussi qu’aucune activité ne puisse couvrir le besoin. Si cela se produit, une exception est alors lancée.

4.3.1 L’objet Intent

L’objet au cœur du dispositif de la navigation des écrans est l’Intent qui informe des « intentions » de l’activité sur le traitement suivant à réaliser. Un Intent est composé de trois attributs essentiels qui participent à l’identification de l’activité à afficher :

• Action • Data/Type • Category

L’action est une chaîne de caractères qui symbolise le traitement à déclencher. De nombreuses constantes sont définies dans le SDK pour les actions nativement disponibles. Parmi elles, on peut citer à titre d’exemple Intent.ACTION_WEB_SEARCH pour demander de réaliser une recherche sur Internet ou encore Intent.ACTION_CALL pour passer un appel téléphonique.

L’attribut Data est une donnée qui détaille l’action de l’Intent dont elle dépend directement. Elle peut être d’ailleurs nulle, certaines actions n’appelant pas forcément à devoir être précisées. Pour illustration, dans l’exemple ACTION_CALL, l’attribut Data sera le numéro de téléphone à composer.

L’attribut Data est couplé avec un autre attribut qui est le type MIME de la donnée à traiter. En principe, on spécifie soit le type soit la « data ». L’appel à la méthode setType(String) efface l’attribut data qui aurait pu être renseigné par la méthode setData(Uri) et réciproquement. La raison de cela est que dans la majorité des cas, le type MIME peut être déterminé en fonction du data. Si on souhaite malgré tout explicitement fixer le type MIME de la donnée, il faut utiliser la méthode

4

setDataAndType(Uri,String).

On pourrait se demander pourquoi renseigner le type si on ne fournit pas de donnée. La réponse est que l’activité appelée et appelante communiquent dans les deux sens. L’intention (Intent) est créée par l’activité de départ et transmise à la suivante. Celle-ci a aussi la possibilité de retourner des données, toujours transportées par un objet de type Intent, à la première activité. On peut donc imaginer que l’Intent initial ne contienne pas de data mais seulement le type MIME souhaité pour le format de la réponse.

La catégorie, quant à elle, apporte une classification à l’action. La catégorie Intent.CATEGORY_LAUNCHER positionne l’activité comme étant exécutable, cette catégorie est utilisée de pair avec l’action Intent.ACTION_MAIN. Android positionne les activités de cette catégorie dans le lanceur d’applications. La catégorie CATEGORY_HOME marque l’activité à afficher au démarrage du téléphone.

L’objet Intent possède également d’autres attributs tels que les flags et les extras. Ces attributs sont d’autres possibilités de transmission d’informations à l’activité appelée. Ces attributs sont néanmoins accessoires dans la mesure où ils n’entrent pas en compte dans le processus de recherche de l’activité cible.

Une application Android pourrait inclure n'importe quel nombre d'activités.

• Une activité utilise le setContentView (...) méthode pour exposer (en général) une interface

utilisateur unique à partir de laquelle un certain nombre d'actions pourrait être effectué.

• Les activités sont indépendantes les unes des autres, mais ils coopèrent généralement par

l’échange des données et des actions.

• En règle générale, l'une des activités est désignée comme la première (principale) qui doit

être présentée à l'utilisateur lorsque l'application est lancée.

• Le passage d'une activité à l'autre se fait en demandant à la l'activité en cours d'exécution

d'une intention.

• Les Activités interagissent les uns avec les autres dans un mode asynchrone.

5

Les intentions sont invoquées avec des options suivantes :

from: http://code.google.com/android/reference/android/content/Intent.html

Les principaux arguments d'une intention sont les suivants:

1. Action : L'action intégré (built-in) pour être réalisé, tels comme ACTION_VIEW,

ACTION_EDIT, ACTION_MAIN, ... ou créé par l'utilisateur : user-created-activity

2. Data : Les données primaires pour fonctionner sur, par exemple un numéro de téléphone à

appeler (exprimée en Uri).

Typiquement l'intention est appelée comme suit: Intent myActivity = new Intent (action, data);

startActivity (myActivity);

action intégrée ou activité créé par l'user

Les données primaires (comme URI) tel :/ / http://

6

Examples de pairs action/data sont :

from: http://code.google.com/android/reference/android/content/Intent.html

ACTIONS INTÉGRÉES STANDARD (BUILT‐IN STANDARD ACTIONS)Liste des actions standard que les intentions peuvent utiliser pour les activités de lancement (généralement par le biais startActivity (intention). ACTION_MAIN ACTION_VIEW ACTION_ATTACH_DATA ACTION_EDIT ACTION_PICK ACTION_CHOOSER ACTION_GET_CONTENT ACTION DIAL ACTION_ANSWER ACTION_INSERT ACTION_DELETE ACTION_RUN ACTION_SYNC ACTION_PICK_ACTIVITY ACTION_SEARCH ACTION WEB SEARCH ACTION_ACTION_CALL ACTION_SEND ACTION_SENDTO ACTION_WEB_ACTION_FACTORY_TEST

7

Publicité

ACTION_ANSWER ACTION_BATTERY_LOW

ACTION_ALL_APPS ACTION_BATTERY_CHANGED ACTION_EXTERNAL_APPLICATIONS_AVAILABLE ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE ACTION_GET_CONTENT ACTION_MEDIA_SHARED ACTION_MY_PACKAGE_REPLACED ACTION_SCREEN_ON ACTION_SEND ACTION_BOOT_COMPLETED ACTION_CALL_BUTTON ACTION_CLOSE_SYSTEM_DIALOGS

Pour la liste des actions voir: http://developer.android.com/reference/android/content/Intent.html

ACTION_AIRPLANE_MODE_CHANGED ACTION_ATTACH_DATA ACTION_EDIT ACTION_FACTORY_TEST ACTION_MEDIA_SCANNER_STARTED ACTION_MEDIA_UNMOUNTED ACTION_SCREEN_OFF ACTION_SEARCH_LONG_PRESS ACTION_BATTERY_OKAY ACTION_CALL ACTION_CHOOSER ACTION_GTALK_SERVICE_DISCONNECTED ACTION_HEADSET_PLUG ACTION_INSERT_OR_EDIT ACTION_INSERT ACTION_MANAGE_PACKAGE_STORAGE ACTION_MAIN ACTION_PACKAGE_CHANGED ACTION_PACKAGE_ADDED ACTION_PACKAGE_INSTALL ACTION_PACKAGE_FIRST_LAUNCH ACTION_PACKAGE_RESTARTED ACTION_PACKAGE_REPLACED ACTION_SET_WALLPAPER ACTION_SEND_MULTIPLE ACTION_SYSTEM_TUTORIAL ACTION_SYNC ACTION_TIME_TICK ACTION_TIME_CHANGED ACTION_DATE_CHANGED ACTION_CREATE_SHORTCUT ACTION_DEVICE_STORAGE_LOW ACTION_DELETE ACTION_DOCK_EVENT ACTION_DIAL ACTION_MEDIA_EJECT ACTION_MEDIA_CHECKING ACTION_MEDIA_REMOVED ACTION_MEDIA_NOFS ACTION_PICK ACTION_MEDIA_SCANNER_SCAN_FILE ACTION_POWER_DISCONNECTED ACTION_POWER_CONNECTED ACTION_REBOOT ACTION_PROVIDER_CHANGED ACTION_UMS_DISCONNECTED ACTION_UMS_CONNECTED ACTION_VIEW ACTION_VOICE_COMMAND ACTION_WEB_SEARCH

ACTION_GTALK_SERVICE_CONNECTED ACTION_MEDIA_UNMOUNTABLE ACTION_NEW_OUTGOING_CALL ACTION_SEARCH ACTION_SENDTO ACTION_BUG_REPORT ACTION_CAMERA_BUTTON ACTION_CONFIGURATION_CHANGED ACTION_INPUT_METHOD_CHANGED ACTION_LOCALE_CHANGED ACTION_MEDIA_BAD_REMOVAL ACTION_PACKAGE_DATA_CLEARED ACTION_PACKAGE_REMOVED ACTION_PASTE ACTION_SHUTDOWN ACTION_TIMEZONE_CHANGED ACTION_UID_REMOVED ACTION_DEFAULT ACTION_DEVICE_STORAGE_OK ACTION_MEDIA_BUTTON ACTION_MEDIA_MOUNTED ACTION_MEDIA_SCANNER_FINISHED ACTION_PICK_ACTIVITY ACTION_POWER_USAGE_SUMMARY ACTION_RUN ACTION_USER_PRESENT ACTION_WALLPAPER_CHANGED

Les Attributs secondaires d’une Intention:

En plus des attributs primaires action/data (principaux arguments), il existe un nombre d'attributs secondaires que vous pouvez également inclure avec un Intent, par exemple:

1. Category

2. Components

3. Type

4. Extras

8

ACTIONS INTÉGRÉES STANDARD BROADCAST

Liste des actions standard que les intentions peuvent utiliser pour la réception des Broadcast (BroadcastReceiver, IntentFilter) ou une balise (généralement par registerReceiver <receiver>dans le manifeste) :

ACTION_TIME_TICK ACTION_TIME_CHANGED ACTION_TIMEZONE_CHANGED ACTION_BOOT_COMPLETED ACTION_PACKAGE_ADDED ACTION_PACKAGE_CHANGED ACTION PACKAGE REMOVED ACTION_PACKAGE_ACTION_UID_REMOVED ACTION_BATTERY_CHANGED

« Un exemple valant mieux qu’un long discours »

Exemple complet 1:

Une Activity1 affiche une interface pour accepter un numéro de téléphone et demande à une Activity2 (intégré) pour faire l'appel

Avec 20123456 est le N° de téléphone d’un contact déjà enregistré

9

Tag XML :

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" >

<TextView android:id="@+id/label1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ff0000cc" android:text="@string/lb" android:textSize="20sp" android:textStyle="bold" />

<EditText android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="54dp" android:text="tel:5554-20123456" android:inputType="text" />

<Button android:id="@+id/btnPickContact" android:layout_width="149dp" android:layout_height="wrap_content" android:text="@string/bt" > </Button> </LinearLayout>

10

La classe MainActivity.java package tn.rnu.isi.intentdemo1;

import android.os.Bundle; import android.app.Activity; import android.view.View.OnClickListener; import android.content.Intent; import android.net.Uri; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast;

public class MainActivity extends Activity { TextView label1; EditText text1; Button btnCallActivity2;

@Override protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState); try {

setContentView(R.layout.activity_main); label1 = (TextView) findViewById(R.id.label1); text1 = (EditText) findViewById(R.id.text1); btnCallActivity2 = (Button)

findViewById(R.id.btnPickContact);

btnCallActivity2.setOnClickListener(new ClickHandler());

} catch (Exception e) { Toast.makeText(getBaseContext(), e.getMessage(),

Toast.LENGTH_LONG).show(); } }

private class ClickHandler implements OnClickListener {

@Override public void onClick(View v) { try {

// myActivity2 palce un appel téléphonique // pour ACTION_CALL ou ACTION_DIAL // utilise 'tel:' data formatté: "tel:555-20123456" // pour ACTION_VIEW utilise data: "http://www.youtube.com" // (On a besoin aussi INTERNET permission - Manifest)

String myData = text1.getText().toString(); Intent myActivity2 = new Intent(Intent.ACTION_DIAL, Uri.parse(myData)); startActivity(myActivity2);

} catch (Exception e) {

label1.setText(e.getMessage()); }

}// onClick

}// ClickHandler

}// MainActivity

11

1- Appeler immédiatement

String myData = "tel:20123456"; Intent myActivity2 = new Intent(Intent.ACTION_CALL, Uri.parse(myData)); startActivity(myActivity2);

Il ne faut pas oublier d’ajouter les permissions nécessaires dans le fichier manifeste : <uses-permission android:name="android.permission.CALL_PHONE" > </uses-permission>

2- Afficher tous les contacts Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

String myData = "content://contacts/people/"; Intent myActivity2 = new Intent(Intent.ACTION_VIEW, Uri.parse(myData)); startActivity(myActivity2);

3- Afficher un contact particulier Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

String myData = "content://contacts/people/2"; Intent myActivity2 = new Intent(Intent.ACTION_VIEW, Uri.parse(myData)); startActivity(myActivity2);

4- Editer un contact particulier Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

String myData = "content://contacts/people/2"; Intent myActivity2 = new Intent(Intent.ACTION_EDIT, Uri.parse(myData)); startActivity(myActivity2);

12

5- Faire une recherche sur Google à la recherche des associations tunisiennes

Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

Intent intent = new Intent (Intent.ACTION_WEB_SEARCH );

intent.putExtra(SearchManager.QUERY,

"associations tunisiennes ");

startActivity(intent);

Data Secondaire

texte (en utilisant des attributs

Publicité

6- Envoi d'un message supplémentaires) “address”, “sms_body” sont des mot clé Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

Intent intent = new Intent( Intent.ACTION_SENDTO, Uri.parse("sms:5551234")); intent.putExtra("sms_body", "Vous allez au stade?"); startActivity(intent);

7- Afficher photos (à l'aide des attributs supplémentaires)

Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

Intent myIntent = new Intent(); myIntent.setType("image/pictures/*"); myIntent.setAction(Intent.ACTION_GET_CONTENT); startActivity(myIntent);

13

8- Voir une page web Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

String myData = "http://www.youTube.com"; Intent myActivity2 = new Intent(Intent.ACTION_VIEW, Uri.parse(myData)); startActivity(myActivity2);

Il ne faut pas oublier d’ajouter les permissions nécessaires dans le fichier manifeste : <uses-permission android:name="android.permission.INTERNET " > </uses-permission>

9- Géolocalisation par coordonnées Long/Lat Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

String geoCode ="geo:41.5020952,-81.6789717"; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(geoCode)); startActivity(intent); Il ne faut pas oublier d’ajouter les permissions nécessaires dans le fichier manifeste : <uses-permission android:name=" android.permission.ACCESS_COARSE_LOCATION " > </uses-permission>

10- Lancer Music player

Modifier "clickHandler" par le code suivant :

l' Exemple complet 1 en remplaçant

la méthode

Intent myActivity2 = new Intent("android.intent.action.MUSIC_PLAYER"); startActivity(myActivity2);

11- Ecouter Music SD Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

// écouter une chanson "tiratata.mp3" sauvegardé sur la carte SD Intent myActivity2 = new Intent(android.content.Intent.ACTION_VIEW); Uri data = Uri.parse("file:///sdcard/tiratata.mp3"); String type = "audio/mp3"; myActivity2.setDataAndType(data, type); startActivity(myActivity2);

14

12- Envoyer Email Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

Uri uri = Uri.parse("mailto:[email protected]"); Intent myActivity2 = new Intent(Intent.ACTION_SENDTO, uri); // On peut sauter les deux étapes [subject/text] myActivity2.putExtra(Intent.EXTRA_SUBJECT, "subject sera ici"); myActivity2.putExtra(Intent.EXTRA_TEXT, "Le corps de l'email ici"); startActivity(myActivity2);

13- “Paramètres” du Système Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS); startActivity(intent);

14- “Paramètres Régionaux” du Système Modifier l' Exemple complet 1 en remplaçant la méthode "clickHandler" par le code suivant :

Intent intent = new Intent( android.provider.Settings.ACTION_LOCALE_SETTINGS); startActivity(intent);

15

Démarrage des activités et obtenir des résultats

La méthode startActivity (intention) est utilisée pour démarrer une nouvelle activité, qui sera placé au sommet de la pile de l'activité. L’appelant continue, cependant, à exécuter dans son propre thread.

Parfois, vous voulez obtenir un résultat en retour de la dite sous-activité lorsqu'elle se termine.

Par exemple, vous pouvez démarrer une activité qui permet à l'utilisateur de choisir une personne à partir d'une liste de contacts; lorsqu'elle se termine, elle retourne la personne qui a été sélectionné.

Afin d'obtenir des résultats retour de la dite activité, nous utilisons la méthode : startActivityForResult ( Intent, requestCodeID )

Où requestCodeID est une valeur arbitraire que vous choisissez pour identifier l'appel.

Le résultat envoyé par la sous-activité pourrait être repris par le Listener comme méthode asynchrone.

onActivityResult (requestCodeID, resultCode, Intent )

Avant qu’une activité invoquée, quitte ou sort, elle peut appeler SetResult(resultCode) pour renvoyer un signal de terminaison à l'activité parente.

• Il est commode de fournir un code de résultat, qui peut être des résultats standard : Activity.RESULT_CANCELED, Activity.RESULT_OK, ou des valeurs personnalisés.

• Toutes ces informations peuvent être renvoyées au parent avec la méthode :

onActivityResult (int requestCodeID, int resultCode, Intention data)

• Si une activité enfant échoue pour une raison quelconque (comme un crash), l'activité parente recevra un résultat avec le code RESULT_CANCELED.

16

Exemple complet 2:

1. Afficher tous les contacts et en choisir un particulier (Intent.ACTION_PICK).

2. Pour une interaction réussie, l'activité principale accepte l'URI renvoyé identifiant la

personne que nous voulons appeler (contenu :/ / contacts / people / n).

3. Afficher l'entrée du contact sélectionné permettant de faire des appels, envoyer des SMS,

emailing (Intent.ACTION_VIEW).

Main Activity

Intent.ACTION_PICK

Intent.ACTION_VIEW

Placer l’appel

Terminer l’appel

URI du contact sélectionné

17

2 Activity‐1

Activité Principale de l’User

Intent.ACTION_PICK

Uri des Contacts

Intent.ACTION_VIEW

Activité-2 Intégrée

(Afficher de la liste des contacts)

Activité-3 Intégrée (Afficher le contact sélectionné)

Appeler Envoyer SMS Envoyer E-mail

Tag XML :

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" >

Publicité

<TextView android:id="@+id/label1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ff0000cc" android:text="Activité Intent" android:textSize="20sp" android:textStyle="bold" />

<EditText android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="54px" android:text="content://contacts/people/" android:textSize="18sp" />

<Button android:id="@+id/btnPickContact" android:layout_width="149px" android:layout_height="wrap_content" android:text="Sélectionner Contact" > </Button> </LinearLayout>

18

La classe IntentDemo2.java package tn.rnu.isi.intentdemo2;

import android.os.Bundle; import android.app.Activity; import android.view.View.OnClickListener; import android.content.Intent; import android.net.Uri; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast;

public class IntentDemo2 extends Activity { TextView label1; EditText text1; Button btnCallActivity2;

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try {

setContentView(R.layout.activity_intent_demo2); label1 = (TextView) findViewById(R.id.label1); text1 = (EditText) findViewById(R.id.text1); btnCallActivity2 = (Button) findViewById(R.id.btnPickContact); btnCallActivity2.setOnClickListener(new ClickHandler());

} catch (Exception e) { Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_LONG) .show(); } }

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); try { //utiliser requestCode pour savoir qui va communiquer, de nouveau // avec nous switch (requestCode) { case (222): { // 222 C'est notre activité amicale contact sélecteur if (resultCode == Activity.RESULT_OK) {

String selectedContact = data.getDataString(); // On retourne un URI qui ressemble à:

// content://contacts/people/n // où n est l’ID du contact sélectionné label1.setText(selectedContact.toString());

19

// montre unécran avec le contact sélectionné Intent myAct3 = new Intent(Intent.ACTION_VIEW,

Uri.parse(selectedContact));

startActivity(myAct3);

} else {

// utilisateur a appuyé sur la touche BACK

label1.setText("Selection CANCELLED " + requestCode + " "

+ resultCode);

} break;

} }// switch } catch (Exception e) {

Toast.makeText(getBaseContext(), e.getMessage(),

Toast.LENGTH_LONG)

}

}// onActivityResult

.show();

private class ClickHandler implements OnClickListener { @Override public void onClick(View v) { try {

// myData se refère à : content://contacts/people/ String myData = text1.getText().toString(); // vous pouvez également essayer ACTION_VIEW Intent myActivity2 = new Intent(Intent.ACTION_PICK,

Uri.parse(myData));

// démarrer myActivity2. // Dites-lui que notre requestCodeID (ou pseudo) est de 222 startActivityForResult(myActivity2, 222); // Toast.makeText(getApplicationContext(), // "Je ne peux pas attendre", 1).show(); } catch (Exception e) {

label1.setText(e.getMessage());

}

}// onClick }// ClickHandler

}// IntentDemo2

20

Exemple complet 3:

Affichage des photos et vidéo - Appel d’une sous-activité, la réception des résultats.

La classe IntentDemo3.java package tn.rnu.isi.intentdemo3;

import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.widget.Toast;

public class IntentDemo3 extends Activity {

@Override protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState); setContentView(R.layout.activity_intent_demo3); showVideosImages();

}

private void showVideosImages() { Intent myIntent = new Intent(); // tous les videos et les images myIntent.setType("video/*, images/*"); myIntent.setAction(Intent.ACTION_GET_CONTENT);

startActivityForResult(myIntent, 0);

}// showVideosImages

@Override protected void onActivityResult(int requestCode, int resultCode,

Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if ((requestCode == 0) && (resultCode == Activity.RESULT_OK)) {

String selectedImage = intent.getDataString(); Toast.makeText(this, selectedImage, 1).show(); Intent myAct3 = new Intent(Intent.ACTION_VIEW,

Uri.parse(selectedImage));

startActivity(myAct3);

}

}// onActivityResult

} // IntentDemo3

21

Exemple complet 4: Affichage / Lecture de pistes sonores - Appel d’une sous-activité, la réception des résultats.

La classe IntentDemo4.java package tn.rnu.isi.intentdemo3;

import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.widget.Toast;

public class IntentDemo4 extends Activity {

@Override protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState); setContentView(R.layout.activity_intent_demo4); showSoundTracks();

}

Publicité

private void showSoundTracks() {

Intent myIntent = new Intent(); myIntent.setType("audio/mp3"); myIntent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(myIntent, 0); }//showSoundTracks

@Override protected void onActivityResult(int requestCode, int resultCode,

Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if ((requestCode == 0) && (resultCode == Activity.RESULT_OK)) {

String selectedTrack = intent.getDataString(); Toast.makeText(this, selectedTrack, 1).show(); Intent myAct3 = new Intent(Intent.ACTION_VIEW,

Uri.parse(selectedTrack));

startActivity(myAct3);

}

}// onActivityResult

}//IntentDemo4

22

Retenons Une activité présente habituellement une seule interface utilisateur visuelle à partir de laquelle un certain nombre d'actions pourrait être effectué. Le passage d'une activité à l'autre est accompli par avoir l'activité courante lancer la suivante à travers des intents.

4.3.2 Bundles (packs) Android La plupart des langages de programmation supportent la notion de méthode IPC1-appel avec des arguments circulant bi-directionnellement de l'appelant à la méthode appelée. Dans android l'appel de l'activité est issu d’une invocation à une autre activité à l'aide d'un Objet Intent. Notamment dans Android, l'appelant ne cesse pas d'attendre l'activité appelée pour renvoyer les résultats. A sa place, une méthode d’écouter le (Listener) [onActivityResult (...)] devrait être utilisée. Le conteneur Bundle Android est un mécanisme simple utilisé pour transmettre des données entre activités. Un Bundle est une collection de type sécurisé de paires <valeur , nom>. Il ya un ensemble de méthodes de putXXX et getXXX pour stocker et récupérer (simple et array) des valeurs de types de données primitifs de / vers les paquets (bundles). Par exemple :

Bundle myBundle = new Bundle(); myBundle.putDouble ("var1", 3.1415); ... Double v1 = myBundle.getDouble("var1");

1 Inter-Process Communication

23

24

Android Bundles http://developer.android.com/reference/android/os/Bundle.html Example des Méthodes publiques void clear() Removes all elements from the mapping of this Bundle. Object clone() Clones the current Bundle. boolean containsKey(String key) Returns true if the given key is contained in the mapping of this Bundle. void putIntArray(String key, int[] value) Inserts an int array value into the mapping of this Bundle, replacing any existing value for the given key. void putString(String key, String value) Inserts a String value into the mapping of this Bundle, replacing any existing value for the given key. void putStringArray(String key, String[] value) Inserts a String array value into the mapping of this Bundle, replacing any existing value for the given key. void putStringArrayList(String key, ArrayList<String> value) Inserts an ArrayList value into the mapping of this Bundle, replacing any existing value for the given key. void remove(String key) Removes any entry with the given key from the mapping of this Bundle. int size() Returns the number of mappings contained in this Bundle.

25

Exemple complet 5:

Activity1 recueille deux valeurs de son interface utilisateur et appelle Activity2 pour calculer la somme d'eux. Le résultat est renvoyé de l'Activity 2 à Activity1.

Etape 1. Créer GUI pour Activity1 (main1.xml)

Tag XML : main1.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ff0000ff" android:text="Activity1" android:textSize="22sp" /> <EditText android:id="@+id/EditText01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="Première valeur (double signé)" android:inputType="numberDecimal|numberSigned|number" /> <EditText android:id="@+id/EditText02" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="Seconde valeur (un entier positif)" android:inputType="number" /> <Button android:id="@+id/btnAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Additionner" /> <TextView android:id="@+id/TextView01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ff0000ff" android:text="La somme est..." android:textSize="28sp" /> </LinearLayout>

L'élément android:inputType indique que la première valeur peut être numérique, avec en option décimales et signe.

26

Etape 2. Créer GUI pour Activity2 (main2.xml)

Tag XML : main2.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ff888888" android:orientation="vertical" >

<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ff0000ff" android:text="Activity2" android:textSize="22sp" />

<EditText android:id="@+id/etDataReceived" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Donnée reçu..." />

<Button android:id="@+id/btnDone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Fait ‐ Callback" />

</LinearLayout>

Etape 3. Dans l’Activity1 : Après avoir cliqué sur le bouton des données, de l'interface utilisateur est placé dans un paquet et envoyé à Activity2. Un listener reste attentif attendre des résultats à venir de l'activité appelée.

27

package tn.rnu.isi.intentbundledemo;

import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView;

//Activity 1: obtenir deux valeurs entrées par l'utilisateur, //les mettre dans un bourdons. //appeler Activity2 à ajouter les deux chiffres, //montrer résultat

public class Activity1 extends Activity {

EditText txtVal1; EditText txtVal2; TextView lblResult; Button btnAdd;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main1); txtVal1 = (EditText) findViewById(R.id.EditText01); txtVal2 = (EditText) findViewById(R.id.EditText02); lblResult = (TextView) findViewById(R.id.TextView01); btnAdd = (Button) findViewById(R.id.btnAdd);

btnAdd.setOnClickListener(new OnClickListener() { public void onClick(View v) { // obtenir des valeurs de l'interface utilisateur Double v1 = Double.parseDouble(txtVal1.getText().toString()); Double v2 = Double.parseDouble(txtVal2.getText().toString());

// créer intent pour appeler Activity2 Intent myIntentA1A2 = new Intent(Activity1.this,Activity2.class); // créer un conteneur pour envoyer des données Bundle myData = new Bundle(); // ajouter des éléments données <key,value> au conteneur myData.putDouble("val1", v1); myData.putDouble("val2", v2); // attacher le conteneur à l'intent myIntentA1A2.putExtras(myData); // Appeler Activity2 , dire au listenr local d'attendre la // réponse // requestCode = 101 startActivityForResult(myIntentA1A2, 101); } }); } // onCreate()

////////////////////////////////////////////////////////////////////////////

28

// local listener recevant callbacks (rappels) des autres activités

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); try { if ((requestCode == 101) && (resultCode == Activity.RESULT_OK)) { Bundle myResults = data.getExtras(); Double vresult = myResults.getDouble("vresult"); lblResult.setText("La somme est " + vresult); } } catch (Exception e) {

lblResult.setText("Problèmes :" + requestCode +" " +resultCode); } }// onActivityResult }// Activity1

Etape 4. Activity2 . Appelée à partir Activity1. Extrait des données d'entrée du paquet attaché à l'intent. Effectue le calcul local. Ajoute le résultat bundle. Retourne signal OK. package tn.rnu.isi.intentbundledemo;

import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText;

public class Activity2 extends Activity implements OnClickListener {

EditText dataReceived; Button btnDone;

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main2);

dataReceived = (EditText) findViewById(R.id.etDataReceived); btnDone = (Button) findViewById(R.id.btnDone); btnDone.setOnClickListener(this);

// récupérer appel fait au Activity2 via Intent

Intent myLocalIntent = getIntent(); // chercher dans le tas envoyé à Activity2 des éléments de données Bundle myBundle = myLocalIntent.getExtras(); Double v1 = myBundle.getDouble("val1"); Double v2 = myBundle.getDouble("val2");

29

// opérer sur les données d'entrée Double vResult = v1 + v2; // à titre d'illustration. Afficher les données reçues et le résultat dataReceived.setText("Données reçues : \n" + "val1= " + v1 + "\nval2= " + v2 + "\n\nresult= " + vResult); // ajouter au paquet le résultat calculé myBundle.putDouble("vresult", vResult); // oindre bourdon mis à jour pour invoquer l'intention myLocalIntent.putExtras(myBundle); // renvoyer en envoyant un signal OK pour appeler l'activité setResult(Activity.RESULT_OK, myLocalIntent); // finish(); }// onCreate

@Override public void onClick(View v) {

//fermer l'écran en cours - fin Activity2 finish();

}// onClick }// Activity2

Exemple 6:

Activity1 invoque Activity2 l'aide d'une intention. Un paquet contenant un