DÉCOUVERTE DU DÉVELOPPEMENT ANDROID Date Nom Objet 06 Septembre 2012 M. Minelli Création 15 Novembre 2011 M. Minelli Vérification 22 Novembre 2011 M. Minelli Finalisation Etat : Terminé
TABLE DES MATIÈRES 1 INTRODUCTION... 3 1.1 Les méthodes dépassée... 3 2 CAHIER DES CHARGES... 4 3 PLANIFICATION... 5 4 PRÉSENTATION DES APPLICATIONS... 6 4.1 Transport Public Genevois... 6 4.1.1 Analyse de l existant... 6 4.1.2 Déroulement... 6 4.1.3 Résultat... 6 4.2 Code Postal Suisse... 7 4.2.1 Analyse de l existant... 7 4.2.2 Fonctionnalités... 7 4.2.3 Résultat... 7 5 PRÉSENTATION RAPIDE DU DÉVELOPPEMENT ANDROID... 8 5.1 Manifest... 8 5.2 Création d une interface / Activity... 8 5.3 Activity... 8 6 LISTVIEW PERSONNALISÉE... 9 7 GÉOLOCALISATION... 12 7.1 Recherches des informations sur un lieu... 13 8 GOOGLE MAPS... 14 8.1 Initialisation de la carte... 14 8.2 Ajout d un point sur la carte... 16 9 GOOGLE PLAY... 17 9.1 Inscription... 17 9.2 Publication... 17 9.3 Accès aux statistiques... 17 10 CONCLUSION... 20 10.1 Apport personnelle... 20 11 LIENS UTILES / SOURCES... 20 11.1 Français... 20 11.2 Anglais... 20 12 ANNEXES... 21 12.1 Table des illustrations... 21 12.2 Mail des TPG... 21 Découverte du développement Android Page 2 sur 21
1 INTRODUCTION Ce document va traiter du développement Android. Lors de la lecture de ce document vous pourrez découvrir certains des principaux éléments qui on put me permettre de concevoir les deux applications qui vous serons aussi présentée. Afin de pouvoir comprendre ce document il faut avoir des base en langage JAVA et dans le développement Android (Principe de fonctionnement des activity, fichier de manifest, etc.). Si vous n avez pas de base dans le développement Android une rapide présentation des principes de base vous serons proposé en chapitre 5. 1.1 Les méthodes dépassée Vous pourrez remarquer que certaine fonctions sons notée en tant que dépassée (deprecated), j ai tout de même continué à les utiliser car même Google utilise encore ces fonction dans les dernières versions de leurs applications de démonstration ainsi que dans leurs documentation, ce qui indique donc que ces fonction ne sont pas prête de disparaitre. En faisant quelque recherche sur internet j ai peu mieux comprendre pourquoi le «géant du net» continuait à les utiliser tout en les notant «deprecated». La réponse est de nouvelle méthode plus compliquée mais surtout ouvrant plus de possibilité de personnalisation sont sortie cependant les anciennes reste tout à fait utilisable si nous souhaitons rester dans des utilisations simple. Découverte du développement Android Page 3 sur 21
2 CAHIER DES CHARGES Sujet: But: Découverte du développement sur Smartphones Android Découvrir le développement pour Smartphones Android en réalisant une application se reposant sur le site internet mobile des TPG pour en réaliser les mêmes fonctionnalités (à part la fonctionnalité itinéraire). Travail: Le travail consistera à: Découverte du système de «fenêtre» Découverte des ListView Découverte des requêtes WEB Découverte d interaction avec une base de données MYSQL Découverte des cartes Google maps Découverte de la géolocalisation Si le temps le permet: Découverte de l utilisation de l appareil photo Utilisation du SDK DropBox Découverte des widgets Découverte des notifications Afin de mettre en pratique ces divers points une application Android basé sur l application web des TPG sera créée. Pour les divers éléments qui ne pourront pas être trouvé dans les données des TPG (ex : Localisation de tous les arrêts) des données fictives seront mises en place afin de pourvoir tout de même la mise en pratique de ces nouvelles connaissances. Environnement: - Un ordinateur de type PC ou MAC - Système d exploitation : Windows 7 ou MAC OS X - Environnement de développement : Eclipse (Java) avec SDK Android A remettre: - Code Source - Documentation technique - Eventuellement un mode d emplois si cela est nécessaire Découverte du développement Android Page 4 sur 21
3 PLANIFICATION Analyse Apprentissage android Petit programme de test Programmation Test Documentation Redition Analyse Apprentissage android Petit programme de test Programmation Test Documentation Redition Août Septembre Octobre Novembre 30 6 13 20 27 4 11 18 25 1 8 15 22 Août Septembre Octobre Novembre 30 6 13 20 27 4 11 18 25 1 8 15 22 L analyse est divisée en deux dû à un changement de projet (voir chapitre 4). Découverte du développement Android Page 5 sur 21
4 PRÉSENTATION DES APPLICATIONS 4.1 Transport Public Genevois 4.1.1 Analyse de l existant Les Transport Public Genevois (TPG) non à l heure d aujourd hui encore aucune réel application pour les appareils tournant sous Android. Cependant les TPG possèdent un site internet optimisé pour Smartphones, celui-ci est malheureusement très lent car la localisation doit passer par le browser et toutes les images se trouvent rechargée à chaque fois. C est pour cela que j ai pensé qu une application tournant directement sur Android et possèdent les images déjà dans ses ressources serrait plus rapide et pratique qu une WebApp. 4.1.2 Déroulement J ai tout d abord commencé par le développement de la fonctionnalité permettant de localiser le Smartphone afin d afficher les arrêts à proximité et de ainsi de voir les bus et le temps dans lequel ils arrivent. Le développement de cette application c est arrêté la car j ai pensé que trop tard à l aspect l égale d une tel application. J ai envoyé un e-mail aux TPG qui m ont répondu qu il ne pouvait autoriser cette application car ils ne pouvaient en assumer le support (pour le mail, voir annexes). 4.1.3 Résultat L application c est donc terminée avec la fonctionnalité décrite précédemment tout à fait fonctionnelle. Cette fonctionnalité est tout de même apparemment recherchée car en moins de 3 heures (entre le moment de la publication de l application sur le Google Play et son retrait) celle-ci a totalisé 9 téléchargement rester tous actif jusqu à récemment ou ce nombre est descendu à 6, Ces nombre n ont été faites qu en trois heures sans compter les divers personnes de mon entourage qui mon demandé de leurs donné le fichier APK. Après l annulation de ce projet je me suis penché sur une autre idée que j avais eue (Voir le prochain point). Découverte du développement Android Page 6 sur 21
4.2 Code Postal Suisse 4.2.1 Analyse de l existant Venant du monde Apple (iphone) j ai recherché divers applications pouvant combler mes besoins tels que j en avais sur mon iphone. C est en recherchant un programme permettant de données les correspondances numéro postale<-> localité que je n ai rien trouvé. C est donc pour cela que je me suis décidé à créer un programme permettant cela sur Android. 4.2.2 Fonctionnalités Les fonctionnalités recherchées au départ de l application étaient : - Recherche de NPA - Recherche de localité - Affichage sur une MAP 4.2.3 Résultat Etant allé plus vite que prévu (grâce à la grande similitude entre le langage JAVA et C#) j ai pu ajouter les fonctionnalités suivantes : - Localisation et affichage sur Google Maps - Multi-langue - Synthèse vocale - Reconnaissance vocale - Interface paramétrable Découverte du développement Android Page 7 sur 21
5 PRÉSENTATION RAPIDE DU DÉVELOPPEMENT ANDROID Le développement Android ce réalise à l aide du logiciel gratuit «Eclipse» auquel il faut ajouter une surcouche qui est le SDK Android distribué lui aussi gratuitement par Google. Le langage de programmation utilisé est le JAVA. Voici maintenant quelques précisions utiles afin de pouvoir suivre la suite du document. 5.1 Manifest Android demande un fichier appelé «AndroidManifest.xml» ou on peut trouver le listage des activity, la version de l application, son nom, les librairies ainsi que les droits demandé par celle-ci. 5.2 Création d une interface / Activity Les interfaces se trouvent dans le dossier «res/layout». Celles-ci sont programmables en xml ou en wysiwyg depuis l interface d oracle (très peu maniable). Si vous souhaitez créer deux interfaces différentes en fonction de l orientation de l appareil il vous faut mettre les fichiers avec le même nom, l une dans le dossier «res/layout_land» pour le mode portrait et l autre dans le dossier «res/layout_port» pour le mode portrait. 5.3 Activity Une activity est une classe d interface. Elle est toujours reliée soit à un fichier xml dans le dossier «layout» soit à une création de vue dans son code. Découverte du développement Android Page 8 sur 21
6 LISTVIEW PERSONNALISÉE Les ListView sont des éléments d interface permettant d afficher une liste d élément sur lesquels l utilisateur peut «cliquer». De base ces listes laissent peu de possibilité d affichage aux développeurs. Heureusement Google a prévu la possibilité de créer des ListView personnalisée. Le principe de ces ListView consiste en un layout répété pour chaque élément de la liste. J ai eu besoin de ces listes dans l application TPG qui en contient deux : 1) Liste des arrêts à proximité 2) Liste des bus arrivants Voici un exemple afin de montrer comment les créer. Le rendu final de cet exemple est le suivant : Figure 1 Résultat de la ListView d'exemple Tout d abord, dans le fichier de l interface, il faut ajouter un élément de type ListView possèdent un id unique. <ListView android:id="@+id/listarret" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@+id/maj" /> Découverte du développement Android Page 9 sur 21
En second, il faut créer un fichier xml qui va contenir le layout qui sera répété pour chaque élément de la liste. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:paddingleft="5dp" android:layout_weight="1" > <TextView android:layout_width="fill_parent" android:layout_height="fill_parent" android:textsize="10dp" android:textstyle="bold" /> <TextView android:id="@+id/nom" android:layout_width="fill_parent" android:layout_height="fill_parent" android:textsize="20dp" android:textstyle="bold" android:text="croix-de-chavant" /> <TextView android:id="@+id/distance" android:layout_width="fill_parent" android:layout_height="fill_parent" android:textsize="13dp" android:text="~190 m" /> <TextView android:layout_width="fill_parent" android:layout_height="fill_parent" android:textsize="10dp" android:textstyle="bold" /> </LinearLayout> <ImageView android:id="@+id/img" android:layout_gravity="center_vertical" android:layout_width="20dp" android:layout_height="30dp" android:src="@drawable/fleche_droite" /> </LinearLayout> Découverte du développement Android Page 10 sur 21
En troisième, il faut passer dans le code de l activity ou se trouve la liste. Ainsi il sera possible de lier le ListView et son layout d élément et ainsi de construire la liste. Ce bout de code est raccourci car contenait aussi une boucle et d autres appels. //Récupération de la listview ListView lv_arrets = (ListView) findviewbyid(r.id.listarret); //Création de l ArrayList qui nous permettra de remplir la listview ArrayList<HashMap<String, String>> listitem = new ArrayList<HashMap<String, String>>(); //On déclare la HashMap qui contiendra les informations pour un item HashMap<String, String> map; [ ] //Code récupérant les arrêts //Pour chaque arrêt trouvé for (Arret current_arret : arrets) { //L'incère ˆ la liste map = new HashMap<String, String>(); map.put("nom", current_arret.nom); Log.e("nom", current_arret.nom); map.put("distance", current_arret.distance); map.put("img", String.valueOf(R.drawable.fleche_droite)); listitem.add(map); } //Création d'un SimpleAdapter qui se chargera de mettre les items présent dans notre liste (listitem) dans la vue affichageitem SimpleAdapter mschedule = new SimpleAdapter(this.getBaseContext(), listitem, R.layout.select_arret_affichageitem, new String[] { "img", "nom", "distance" }, new int[] { R.id.img, R.id.nom, R.id.distance }); //On attributàˆ notre listview l'adapter que l'on vient de créer lv_arrets.setadapter(mschedule); Enfin pour détecter le click //Enfin on met un écouteur d'évènement sur notre listview lv_arrets.setonitemclicklistener(new OnItemClickListener() { public void onitemclick(adapterview<?> a, View v, int position, long id) { //Créer un nouveau Intent avec passage de paramètre de l'arret Intent intent = new Intent(Select_Arret_Activity.this, Bus_Arret_Activity.class); intent.putextra("nom", arrets.get((int) id).nom); intent.putextra("distance", arrets.get((int) id).distance); intent.putextra("lien", arrets.get((int) id).lien); startactivity(intent); } }); Découverte du développement Android Page 11 sur 21
7 GÉOLOCALISATION La localisation est utilisée dans l application TPG afin de pouvoir détecté les arrêts aux alentours ainsi que dans l application Code Postal Suisse. Il existe plusieurs types de localisations : la localisation par le GPS et la localisation par le réseau (triangulation, WIFI, etc.). Android ne permet que de faire une de celle-ci par LocationManager. Pour surmonter cette «limitation» la solution à utiliser est tout simplement de déclarer deux LocationManager avec chacun un des deux moyens puis des que l un des deux aura trouvé une solution il faudra désactiver l autre afin de ne pas avoir deux réponse. Voici comment procédé pour obtenir les coordonnées de l appareil. Tous d abord, il faut ajouter les droits demandé dans le fichier manifest : <uses-permission android:name="android.permission.access_coarse_location" /> <uses-permission android:name="android.permission.access_fine_location" /> <uses-permission android:name="android.permission.access_gps" /> <uses-permission android:name="android.permission.location" /> Puis, il faut ajouter la ligne suivante sur la ligne de déclaration de la class : implements LocationListener Cette ligne permet de pourvoir appeler la fonction de réussite de la localisation directement au sein de la class activity. Ensuite, il faut déclarer les variables globales qui sont les LocationManager : private LocationManager lmanager, lmanager_gps; Ensuite, dans la procédure d appel de la géolocalisation : //Obtient la localisation lmanager = (LocationManager) getsystemservice(context.location_service); lmanager_gps = (LocationManager) getsystemservice(context.location_service); lmanager.requestlocationupdates(locationmanager.network_provider, 60000, 0, this); lmanager_gps.requestlocationupdates(locationmanager.gps_provider, 60000, 0, this); La technique utilisée si dessus demande l envoi des données de localisation toute les XX mètres (ici 60000 mètres) parcouru. Si le développeur souhaite comme ici n avoir qu un seule résultat, il lui faut désactiver les LocationManager après avoir eu le premier résultat. Il existe une fonction permettant de ne demander qu une seule position (requestsingleupdate) cependant celle-ci n a été introduit qu à partir de la version 2.3 d Android et donc ne permet pas de faire d application universellement fonctionnelle. Découverte du développement Android Page 12 sur 21
Enfin le résultat de la localisation sera envoyé à la fonction suivante : public void onlocationchanged(location location) { //On stocke les differentes coordonées et on les affiche Int lat = location.getlatitude(); Int lng = location.getlongitude(); } //et on spécifie au service que l'on ne souhaite plus avoir de mise à jour lmanager.removeupdates(this); lmanager_gps.removeupdates(this); 7.1 Recherches des informations sur un lieu Avec Android il est possible de rechercher les informations d un lieu à partir de ses coordonnées ou d un nom. Cela passe par l utilisation d un service de Google. Cette recherche nécessite une connexion internet car va rechercher dans les bases de données Google. Il faut donc ajoute le droit suivant au manifest : <uses-permission android:name="android.permission.internet" /> Puis, voici le code permettant de rechercher une adresse à partir de ses coordonnées. Google en renvoie plusieurs cependant la première de la liste est toujours la plus précise donc il est possible d ignorer les autres. //Le geocoder permet de récupérer ou chercher des adresses gràce à un mot clé ou une position Geocoder geo = new Geocoder(Select_Arret_Activity.this); try { //Ici on récupère la premiere adresse trouvé gràce à la position que l'on a récupéré List<Address> adresses = geo.getfromlocation(location.getlatitude(), location.getlongitude(), 1); //Vérifie qu'une adresse a bien été trouvée if (adresses!= null && adresses.size() == 1) { Address adresse = adresses.get(0); } else { /* adresse.getaddressline(0) adresse.getpostalcode() adresse.getlocality(); */ ((TextView) findviewbyid(r.id.adresse)).settext("l'adresse n'a pu ètre déterminée"); } } catch (IOException e) ((TextView) findviewbyid(r.id.adresse)).settext("l'adresse n'a pu ètre déterminée"); Si il faut rechercher par un nom la ligne de code change légèrement : List<Address> adresses = geo.getfromlocationname(nom, 1); Google renvoi une liste d objet Adress dans lesquels se trouvent diverses informations. La documentation Google les listes toutes : http://developer.android.com/reference/android/location/address.html Découverte du développement Android Page 13 sur 21
8 GOOGLE MAPS Les cartes sont souvent utilisées dans les applications et l application Code Postale Suisse ne fait pas exception. L ajout de Google Map dans une application se fait en deux principales phases. La première étant l ajout de la carte en elle-même puis l ajout de points sur la carte. 8.1 Initialisation de la carte Tout d abord il faut commencer par changer le sdk de votre projet par le même mais en Google API. Pour cela il faut faire un clic droit sur le projet puis aller dans ses propriétés et le changer comme cela : Figure 2 Ecran de sélection du SDK Ensuite, il faut commencer par ajouter les droits d accès à internet et l indication de l utilisation de la librairie Google Maps.dans le fichier manifest : <uses-permission android:name="android.permission.internet" /> <uses-library android:name="com.google.android.maps" /> Découverte du développement Android Page 14 sur 21
La particularité dans ce cas est qu il n y a pas besoin de lier l activity à un fichier layout. Tout d abord l activity n est pas un enfant de la class activity traditionnelle mais celui de la MapActivity : public class XXX extends MapActivity Ensuite, il faut déclarer les variables globales suivantes : private MapView mapview; private MapController mc; Puis, les initialiser a la création de l activity : // Initialise la MapView avec la MAP API KEY de publication mapview = new MapView(this, "MAP API KEY"); mapview.setclickable(true); mapview.setsatellite(true); mapview.invalidate(); setcontentview(this.mapview); Le «MAP API KEY» est une clé que Google fourni au développeur afin de pouvoir accéder a ses services. Il existe deux sortes de clé : la première est la clé de développement (débogage) et la deuxième de publication (lorsque l application est distribuée sur le Google Play Store). Pour obtenir ces clés il faut suivre la marche à suivre de Google à cette adresse : https://developers.google.com/maps/documentation/android/mapkey Une fois tout cela fait, la carte s affichera sur l écran sur Smartphone. Découverte du développement Android Page 15 sur 21
8.2 Ajout d un point sur la carte Dans le projet Code Postale Suisse j utilise une class personalisée pour affiché les points car j ai besoin de pouvoir ouvrir une fenètre lors du clic sur un des points. Cet exemple sera donc basé sur cette même class. Il faut donc, avant tout, la télécharger (http://android.famille-minelli.ch/class/customitemizedoverlay.java) puis la mettre dans le projet. Une fois cela fait, il est possible d ajouter des points sur la carte comme cela : mapview.setclickable(true); // Définition de l image utilisée pour afficher le point Drawable locate = this.getresources().getdrawable(r.drawable.localisation_rouge); // Déclaration de la variable de class ItemizedOverlay CustomItemizedOverlay Overlay_Locate = new CustomItemizedOverlay(locate, this, tts, ttsisinit); // Ajout du point à la variable de class (A refaire pour chaque point devant posséder le même icone OverlayItem Overlayitem_Locate = new OverlayItem(GEOPOINT DE L ENDROIT,TITRE, TEXTE); Overlay_Locate.addOverlay(Overlayitem_Locate); // Ajout des points mapoverlays.add(overlay_locate); MapController mapcontroller = mapview.getcontroller(); // Rafraichissement de la carte mapview.invalidate(); Cela ouvrira une fenêtre contenant le titre et le texte au clic sur le point. Découverte du développement Android Page 16 sur 21
9 GOOGLE PLAY Le Google Play Store permet de distribuer sur la plateforme de Google les applications conçu par les développeurs. 9.1 Inscription Pour s inscrire il suffit de se rendre sur le site développeur de Google (https://play.google.com/apps/publish/signup) puis de suivre les étapes. 9.2 Publication Pour publier une application il faut se rendre dans la partie développeur (même adresse que précédemment). Puis de cliquer sur «Publier une application». Et pour finir remplir le formulaire. 9.3 Accès aux statistiques L application Code Postal Suisse a été mise en ligne dès qu une première version utilisable fus faite puis a été mise à jour trois fois pour y ajouté les fonctionnalités manquante et corrigé certains bugs. Les statistiques d exemple présenté si dessous sont celles de l application. Le Google Play laisse accès à certaines statistiques pouvant être intéressant. Savoir la nationalité dominante des utilisateurs, leur langue, la versions d Android et le pays peuvent servir à mieux cibler l application ou voir ou se trouve les points faible de celle-ci (mauvaise traduction, compatibilité avec certaines version et autres). Figure 3 Statistique de nombre d installations Découverte du développement Android Page 17 sur 21
Figure 4 Nb de chaque version d Android Figure 5 Nationalité des utilisateurs ayant téléchargé l'application Découverte du développement Android Page 18 sur 21
Figure 6 Langues des utilisateurs Figure 7 Le nombres de versions installées Découverte du développement Android Page 19 sur 21
10 CONCLUSION En conclusion, malgré le revirement de situation avec l application des TPG, le fait d avoir trouvé une autre idée a pu me permettre de continuer à progresser dans le développement Android comme le sujet du travail de semestre le demandait. J ai pu dépasser les exigence du cahier des charges avec l ajout de certaines fonctionnalité tel que la reconnaissance vocale, le TextToSpeech, le téléchargement de fichier, le multithread, le multi-langue et les paramètres d applications. 10.1 Apport personnelle Ne connaissant pas du tout le développement Android avant de réaliser ce projet. Cela m a apporté beaucoup. J ai ainsi pu découvrir le langage JAVA qui est finalement pas si loin du C#. Certain points ont été difficile à comprendre au début, notamment la comparaison de string que je ne fessais pas correctement et qui donc ne marchais pas, mais finalement la documentation sur internet étant tellement dense cela n a pas été difficile de trouver les réponses à mes question. En comparaison avec le système d Apple, celui de Google est plus simple sur plusieurs points. Tout d abord, le langage JAVA est plus simple pour moi que l Objective-C. En second, il n y a pas besoin de licence pour pouvoir tester son application directement sur un appareil. Enfin le mécanisme de publication (et les prix) sont aussi plus simple et plus rapide. A mon avis, avec tous ces points fort le dévellopement Android possède encore un grand désavantage qui est le logiciel de dévellopement Eclipse. Celui ci (et dans sa dernière version) possède encore trop de bugs et de lenteur. J estime le temps de travail hors des heures de cours à un moins de 10%. Celui-ci a surtout été consacré aux recherches, à l apprentissage et à la publication de l application. 11 LIENS UTILES / SOURCES Voici quelques liens utiles pour apprendre à développer sur Android. 11.1 Français - FrAndroid (http://www.frandroid.com/developpement/) - Developpez.com (http://android.developpez.com/cours/) - Tutos-android (http://www.tutos-android.com/) 11.2 Anglais - Android developers (http://developer.android.com) - XDA Developers (http://www.xda-developers.com) Découverte du développement Android Page 20 sur 21
12 ANNEXES 12.1 Table des illustrations FIGURE 1 RÉSULTAT DE LA LISTVIEW D'EXEMPLE... 9 FIGURE 2 ECRAN DE SÉLECTION DU SDK... 14 FIGURE 3 STATISTIQUE DE NOMBRE D INSTALLATIONS... 17 FIGURE 4 NB DE CHAQUE VERSION D ANDROID... 18 FIGURE 5 NATIONALITÉ DES UTILISATEURS AYANT TÉLÉCHARGÉ L'APPLICATION... 18 FIGURE 6 LANGUES DES UTILISATEURS... 19 FIGURE 7 LE NOMBRES DE VERSIONS INSTALLÉES... 19 12.2 Mail des TPG Bonjour Monsieur, Faisant suite à votre message nous ne sommes pas en mesure de donner une suite favorable immédiate à votre initiative. Ceci pour des raisons de respect du graphisme, de la justesse des données et du service client qui pourraient en découler. Nous ne pouvons répondre à des clients qui se baseraient sur des informations ou bugs produits par votre application même si je n ai pas de doute sur sa qualité. [ ] En vous félicitant pour votre approche et en vous souhaitant bon courage pour la suite de vos travaux, je vous prie d agréer, cher monsieur Minelli, mes cordiales salutations. Michaël Chopard Adjoint à la direction ventes, marketing et promotion Responsable marketing, promotion et web transports publics genevois Route de la Chapelle - Case postale 950 1212 Grand-Lancy 1 - Suisse Découverte du développement Android Page 21 sur 21