Android pour l’entreprise – 2 – Vous habitez chez vos parents ?
Cet article est la suite de Android pour l’entreprise – 1 – Premiers contacts. Il appartient à la série Android pour l’entreprise, dont le fil conducteur est la réalisation d’une application Android d’annuaire d’entreprise : YMCA.
Aujourd’hui, nous allons étendre la couverture fonctionnelle de YMCA, et utiliser de nouveaux services fournis par Android : l’ajout de contact, et l’intégration avec Google Maps.
Mais auparavant, un avant goût des articles à venir…
Teaser
Voici la liste non exhaustive des sujets que je souhaite aborder au cours des prochains articles sur le thème “Android pour l’entreprise” :
- Mises à jour automatiques d’applications sans passer par le market
- Fonctionnement offline, tâches asynchrones et bd locale
- Tests unitaires et tests d’intégration
- Mise en place de Maven et intégration avec Hudson
- Intégration avec Jasig CAS
- Création de bibliothèques (JARs) utilisant des classes d’Android
- Injection de dépendances avec Google Guice

L’ordre n’est pas immuable, n’hésitez pas à indiquer dans les commentaires si certains sujets ont votre préférence pour être traités en priorité.
YMCA : évolution fonctionnelle
Voici le nouveau besoin :
- lorsque l’utilisateur tapote un élément de la liste, une nouvel écran apparaît. Il s’agit d’une fiche de contact, qui donne accès aux informations suivantes : nom du contact, numéro de téléphone, adresse,
- depuis cet écran, l’utilisateur peut réaliser les actions suivantes : appeler un contact, voir son adresse sur Google Maps, ajouter le contact à l’annuaire du téléphone.

YMCA : évolution des besoins fonctionnels
Comme d’habitude, les sources du projet sont disponibles à la fin de cet article. Notez que le code de l’archive est très largement commenté.
Une nouvelle activité
Qui dit nouvel écran, dit nouvelle activité. Il suffit pour cela de créer la classe ContactDetailsActivity qui étend de Activity, et de l’enregistrer au sein du AndroidManifest.xml :
1 <activity android:name=".activity.ContactDetailsActivity" />
Puis on fait en sorte qu’un clic sur un contact dans la liste démarre cette activité. Il faut pour cela modifier le listener associé à la liste. Le contact sélectionné sera passé en paramètre, grâce à la notion d’extra dans un intent :
1
2
3
4
5 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i = new Intent(ContactListActivity.this, ContactDetailsActivity.class);
i.putExtra(ContactDetailsActivity.CONTACT_EXTRA, contacts.get(position));
ContactListActivity.this.startActivity(i);
}
Vous habitez chez vos parents ?
L’ajout d’un champ adress à la classe Contact est un jeu d’enfant. On en profite pour faire évoluer le fichier de contacts (contacts.txt), et le service chargé de le parser.
Plus intéressant, on souhaite demander d’afficher cette adresse à l’application Google Maps :
1
2 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=" + address));
startActivity(intent);
Simple n’est-ce pas ? Le principe est exactement le même que pour la composition de numéro, vu dans l’article précédent :
1
2 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber));
startActivity(intent);
Donne moi ton numéro
L’ajout d’un contact au sein de l’annuaire du téléphone se révèle légèrement plus complexe, et nécessite l’utilisation d’un ContentResolver. Je ne rentrerai pas dans les détails du fonctionnement général d’un ContentResolver, je vous conseille cependant de lire la page de doc à ce sujet. Le principe est de transmettre au ContentResolver des requêtes adressées à une URI donnée.
Il faut au préalable demander les permissions de lecture et modification de contacts au sein du fichier AndroidManifest.xml :
1
2 <uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
Vérifions dans un premier temps si le contact existe déjà :
1
2
3
4
5
6
7
8
9
10 String name = contact.getName() + " (YMCA)";
ContentResolver resolver = getContentResolver();
Cursor cur = resolver.query(People.CONTENT_URI, new String[] { Contacts.People._ID }, Contacts.People.NAME + "=?", new String[] { name }, null);
int nbContacts = cur.getCount();
cur.close();
if (nbContacts != 0) {
return;
}
Il faut ensuite créer le contact, via l’utilisation d’une méthode helper qui fait un insert :
Insertion du numéro de téléphone mobile :
1
2
3
4 ContentValues personValues = new ContentValues();
personValues.put(Contacts.People.NAME, name);
personValues.put(Contacts.People.STARRED, 0); //Mettre 1 pour que le contact soit dans les favoris
Uri newPersonUri = Contacts.People.createPersonInMyContactsGroup(resolver, personValues);
1
2
3
4
5 Uri mobileUri = Uri.withAppendedPath(newPersonUri, Contacts.People.Phones.CONTENT_DIRECTORY);
ContentValues mobileValues = new ContentValues();
mobileValues.put(Contacts.Phones.NUMBER, contact.getPhoneNumber());
mobileValues.put(Contacts.Phones.TYPE, Contacts.Phones.TYPE_WORK);
resolver.insert(mobileUri, mobileValues);
Insertion de l’adresse postale du contact :
1
2
3
4
5
6 Uri addressUri = Uri.withAppendedPath(newPersonUri, Contacts.People.ContactMethods.CONTENT_DIRECTORY);
ContentValues addressValues = new ContentValues();
addressValues.put(Contacts.ContactMethods.KIND, Contacts.KIND_POSTAL);
addressValues.put(Contacts.ContactMethods.TYPE, Contacts.ContactMethods.TYPE_WORK);
addressValues.put(Contacts.ContactMethods.DATA, contact.getAddress());
resolver.insert(addressUri, addressValues);
Et voici le résultat, les contacts ajoutés sont dans l’annuaire :

Pour aller plus loin
Au cours de cet article, je vous ai présenté les points essentiels, sans livrer l’intégralité du code source.
Pour comprendre plus en détail le fonctionnement de YMCA, je vous propose de coder vous même une nouvelle fonctionnalité : l’ajout d’un champ email.
Un nouveau champ doit donc apparaître sur la page des détails d’un contact, et un clic sur ce champ doit ouvrir l’application d’envoi d’email.
Afin de modulariser le code, les différentes actions réalisables (appeler / voir sur Google Maps / ajouter aux contacts) ont été encapsulées dans des commandes (cf design pattern command).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 //L'interface Command
public interface Command { void execute(); }
//Une implémentation
public class DialPhoneNumberCommand implements Command {
private final Context context;
private final String phoneNumber;
public DialPhoneNumberCommand(Context context, String phoneNumber) {
this.context = context;
this.phoneNumber = phoneNumber;
}
public void execute() {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber));
context.startActivity(intent);
}
}
La page de détails d’un contact comprend une liste d’actions. A chaque action est associée un titre, un contenu, et une commande.
Le contenu de la liste est donné par un SimpleAdapter, et cet adapter est construit par un builder, créé pour l’occasion. La méthode ContactDetailsActivity.addContent() insère les éléments dans le builder :
1
2
3
4
5 // Composer un numéro de téléphone
title = getString(R.string.contact_details_call_text);
content = contact.getPhoneNumber();
command = new DialPhoneNumberCommand(this, contact.getPhoneNumber());
builderAndInvoker.addAction(title, content, command);
Si je résume, pour ajouter ce champ email, il faut :
- ajouter un champ email à la classe Contact, dans le fichier de liste de contacts, et en tenir compte dans le service qui lit ce fichier distant,
- créer la commande qui va bien,
- insérer une nouvelle action dans le builder.
Alors, qu’attendez-vous ? Ah, peut-être vous manque t’il une dernière clé : comment ouvrir l’application d’envoi d’email en lui donnant en paramètre l’adresse email ?
Cela fonctionne exactement comme pour voir une adresse sur Google Maps, si ce n’est que l’URI est différente :
1
2 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:" + emailAddress));
startActivity(intent);
Attention : cet intent ne fonctionnera pas si l’application d’email n’a pas été configurée au préalable. Pour cela, il suffit de lancer l’application “Email”, et de suivre les étapes de configuration.
Conclusion
Comme promis :
- le code source de l’application : YMCA_code_2.tar.gz
- le tag sur le svn Google Code : http://excilys.googlecode.com/svn/projects/ymca/tags/ymca_article_2/
- l’application packagée (à renommer en YMCA.apk) : YMCA_2.apk.zip
Notez que la solution pour l’envoi d’email fait partie des sources de l’article suivant : Android pour l’entreprise – 3 – Déploiement hors market.
Vous venez probablement de réaliser à quel point il est aisé de s’intégrer au sein de l’écosystème Android, en tout sécurité. Les applications d’entreprises y trouveront un terrain fertile pour répondre à leur besoins spécifiques.

L’article 1 mentionnait l’utilisation du “Build Target : Android 1.5″ lors de la création de l’AVD. On notera que pour l’article 2, faisant appel à Google Maps, il faut donc se servir d’un AVD avec un Build Target : Google APIs.