I. Prérequis▲
Ce tutoriel se veut simple et compréhensible pour tout débutant dans la programmation Android. Son but n'est pas d'initier à la programmation Android, pour cela il existe déjà de très bons tutoriels sur Internet. Cependant, pour une bonne compréhension, il est nécessaire d'avoir les connaissances de base en:
- développement Java ;
- développement Android.
Vous devez également avoir un environnement de développement opérationnel. Vous pouvez utiliser soit l'éditeur Eclipse avec un SDK Android installé (procédure d'installationprocédure d'installation du SDK Android sous eclipse) ou la solution ADT all in one (ADT Bundle) qui intègre déjà tous les outils nécessaires (disponible iciinstallation ADT Bundle all in one).
II. Problématique▲
De nos jours, de plus en plus d'applications pour smartphones utilisent le système de géolocalisation à travers Google Maps, technologie développée par Google permettant entre autres d'embarquer des cartes dans des applications pour mobile. Sa prise en main peut poser quelques difficultés.
- La carte du monde est affichée par votre application au lieu d'un point dont vous aviez spécifié les coordonnées.
- En cours de développement la carte s'affiche, mais en production elle ne s'affiche plus.
Si vous avez déjà été confronté à une de ces difficultés ou vous êtes en train de développer une application Android ou vous avez besoin d'utiliser Android Google Maps et que vous ne savez pas par où commencer, j'espère que vous trouverez des réponses dans ce tutoriel.
III. Objectif▲
Dans le cadre de ce tutoriel, nous allons développer une application Android qui va permettre d'afficher une position sur une carte. Nous allons par la suite la déployer en production.
IV. Présentation de Google Maps API V2▲
Google Map API v2 est une bibliothèque fournie par Google pour permettre aux développeurs Android d'embarquer les cartes Google Maps dans leurs applications. Elle fournit les outils permettant de manipuler les cartes. Cette version de l'API est sortie officiellement en fin d'année 2012 notamment en décembre.
L'unique version existante avant l'apparition de Map API v2 était Map API v1 qui était distribuée via l'extension « Google API » et utilisait la Mapview pour afficher les cartes.
- les clés utilisées sur l'API v1 ne sont pas compatibles avec cette nouvelle version. De plus, Google ne fournit plus la possibilité de créer des clés pour l'API v1 ;
- le mode de distribution a changé et passe maintenant par le SDK Google Play services ;
- l'apparition des MapFragment qui permettent de faire des interfaces différenciées en fonction des terminaux mobiles utilisés (smartphones, tablettes, etc.) ;
- facilité d'intégration des marqueurs.
V. Création de l'application▲
V-A. Rappel▲
Depuis le début du tutoriel, je parle des modes développement et production. C'est quoi ces deux modes ?
Le mode développement (debogage) représente l'état d'une application en cours de développement. En effet, c'est un mode de test dans lequel les erreurs survenues pendant l'exécution sont affichées de façon détaillée et dans lequel l'EDI (environnement de développement intégré) permet de faire une exécution pas à pas du code source.
Par contre, le mode production (release) représente la version exécutable d'une application (.apk dans le cas d'une application Android). C'est une version dépourvue de tous les éléments de test par conséquent moins volumineuse.
V-B. Créer un projet Android▲
Démarrez votre EDI Eclipse, allez au menu « File > New > Android Application Project ». L'interface de création de nouveaux projets Android s'affiche. Renseignez le nom de l'application, le nom du projet et le nom du package. Pour les autres champs, laissez les valeurs par défaut.
Ensuite, cliquez sur « Next » et pour tous les autres écrans laissez les valeurs par défaut puis validez avec « Finish ». Eclipse vous génère un MainActivity et le layout correspondant.
V-C. Installer la librairie Google Play services▲
Pour afficher une carte avec Maps API V2, il est nécessaire d'inclure dans le projet la librairie Google Play services. Pour l'installer, lancez votre SDK Manager depuis la barre d'outils Eclipse.
Dans la boite de dialogue qui apparaît, déroulez « Extras » et installez « Google Play services ».
Après l'installation, il faut importer la bibliothèque comme projet dans Eclipse. Allez au menu « File > New > Project », déroulez l'entrée « Android » et choisissez « Android Project from Existing Code » puis « Next ».
Cliquez sur « Browse » pour rechercher la bibliothèque Google Play services (vous la trouverez à l'emplacement : chemin de votre sdk/extras/google/google_play_services/libproject.
Une fois la bibliothèque importée, il faut l'ajouter comme dépendance dans votre projet. Pour cela, sélectionnez le projet mapv2 ensuite allez dans le menu « Prroject > Properties », dans le panneau de gauche choisissez « Android ». À droite apparaît un panneau avec un bloc Library, cliquez sur le bouton « Add » et choisissez comme bibliothèque à importer googleplay services puis validez.
En principe si vous avez bien suivi les instructions, la structure de votre projet dans l'explorateur de paquets d'Eclipse devra ressembler à ceci:
À ce stade vous pouvez déjà utiliser les outils Maps API V2. Cependant vous ne pouvez pas encore afficher votre carte, car pour que ce soit possible il vous faut obtenir une API key de votre projet auprès de Google et donner les autorisations nécessaires dans votre fichier Manifest.
V-D. Création de la clé Map API V2▲
Pour obtenir cette clé, allez dans votre console Google Développeur Console Google.Console Google
Pour utiliser cette console, vous devez posséder un compte Gmail.
Créez un projet au niveau de la console, une fois votre projet créé, allez dans le panneau de gauche de votre console sous le Menu « APIs & auth », choisissez « APIs ».
Dans la liste de services qui se chargent, recherchez « Google Maps Android API V2 », vous trouverez une ligne semblable à celle-ci :
Cliquez sur le bouton « Off » pour l'activer, une fois activé il apparaît tout en haut de la liste comme ci-dessous.
Revenez dans le panneau de gauche et cliquez sur « Credentials ».
C'est ici que vous allez générer une clé pour votre application. Choisissez « Create new Key », ensuite dans la Popup qui s'affiche choisissez « Android Key ». Vous remarquerez que Google demande de donner l'empreinte SHA1 de votre clé. Pour la retrouver, revenez dans l'EDI Eclipse dans le menu « Window > preferences ». Dans le panneau de gauche, déroulez « Android » puis cliquez sur « Build ». Dans le panneau de droite, vous voyez apparaître un contenu, le bloc qui vous intéresse est celui de la capture suivante.
Copiez la valeur dont la clé est SHA1 fingerprint et collez-la dans l'espace indiqué dans votre console suivi du nom de package de votre application séparé par un point-virgule. Vous obtenez quelque chose comme sur la figure ci-contre:
Validez pour générer votre clé.
La clé étant générée, il vous faut définir les autorisations dans le fichier de configuration Manifest de votre projet.
V-E. Définir les autorisations du projet▲
Pour afficher votre Map, l'application a besoin de certaines autorisations en plus de l'API key. Ces permissions sont à mettre avant la balise application du fichier Manifest.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
<!-- on crée une permission pour notre application -->
<permission
android
:
name
=
"com.abyster.tuto.mapv2.permission.MAPS_RECEIVE"
android
:
protectionLevel
=
"signature"
/>
<!-- on ajoute notre permission à la liste de permissions requises par l'API -->
<uses-permission
android
:
name
=
"com.abyster.tuto.mapv2.permission.MAPS_RECEIVE"
android
:
protectionLevel
=
"signature"
/>
<uses-permission
android
:
name
=
"android.permission.INTERNET"
/>
<uses-permission
android
:
name
=
"android.permission.ACCESS_NETWORK_STATE"
/>
<uses-permission
android
:
name
=
"com.google.android.providers.gsf.permission.READ_GSERVICES"
/>
<uses-permission
android
:
name
=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android
:
name
=
"android.permission.ACCESS_COARSE_LOCATION"
/>
<uses-permission
android
:
name
=
"android.permission.ACCESS_FINE_LOCATION"
/>
<!-- la librairie Maps V2 nécessite openGL pour son bon fonctionnement -->
<uses-feature
android
:
glEsVersion
=
"0x00020000"
android
:
required
=
"true"
/>
Dans la balise application du même fichier Manifest, insérez les deux instructions du code ci-dessous. La première définit la clé de l'API générée précédemment (vous remarquerez que j'ai mis ma clé dans le fichier de déclaration de chaîne de caractères strings.xml avec pour nom api_debug_key et je l'appelle juste dans le Manifest) et la seconde définit la version de l'API Google Play services utilisée.
2.
3.
4.
<meta-data
android
:
name
=
"com.google.android.maps.v2.API_KEY"
android
:
value
=
"@string/api_debug_key"
/>
<meta-data
android
:
name
=
"com.google.android.gms.version"
android
:
value
=
"@integer/google_play_services_version"
/>
Le fichier manifest final devrait ressembler à ceci:
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.abyster.tuto.mapv2"
android
:
versionCode
=
"1"
android
:
versionName
=
"1.0"
>
<uses-sdk
android
:
minSdkVersion
=
"8"
android
:
targetSdkVersion
=
"19"
/>
<!-- on crée une permission pour notre application -->
<permission
android
:
name
=
"com.abyster.tuto.mapv2.permission.MAPS_RECEIVE"
android
:
protectionLevel
=
"signature"
/>
<!-- on ajoute notre permission à la liste de permissions requises par l'API -->
<uses-permission
android
:
name
=
"com.abyster.tuto.mapv2.permission.MAPS_RECEIVE"
android
:
protectionLevel
=
"signature"
/>
<uses-permission
android
:
name
=
"android.permission.INTERNET"
/>
<uses-permission
android
:
name
=
"android.permission.ACCESS_NETWORK_STATE"
/>
<uses-permission
android
:
name
=
"com.google.android.providers.gsf.permission.READ_GSERVICES"
/>
<uses-permission
android
:
name
=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android
:
name
=
"android.permission.ACCESS_COARSE_LOCATION"
/>
<uses-permission
android
:
name
=
"android.permission.ACCESS_FINE_LOCATION"
/>
<!-- la librairie Maps V2 nécessite openGL pour son bon fonctionnement -->
<uses-feature
android
:
glEsVersion
=
"0x00020000"
android
:
required
=
"true"
/>
<application
android
:
allowBackup
=
"true"
android
:
icon
=
"@drawable/ic_launcher"
android
:
label
=
"@string/app_name"
android
:
theme
=
"@style/AppTheme"
>
<meta-data
android
:
name
=
"com.google.android.maps.v2.API_KEY"
android
:
value
=
"@string/api_debug_key"
/>
<meta-data
android
:
name
=
"com.google.android.gms.version"
android
:
value
=
"@integer/google_play_services_version"
/>
<activity
android
:
name
=
"com.abyster.tuto.mapv2.MainActivity"
android
:
label
=
"@string/app_name"
>
<intent-filter>
<action
android
:
name
=
"android.intent.action.MAIN"
/>
<category
android
:
name
=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
</manifest>
V-F. Code d'affichage de la Map▲
Remplacez le code de votre activity_main.xml par celui-ci :
2.
3.
4.
5.
6.
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
id
=
"@+id/map"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"match_parent"
android
:
name
=
"com.google.android.gms.maps.SupportMapFragment"
/>
Au niveau de la ligne android:name, nous avons utilisé SupportMapFragment pour que notre carte puisse s'afficher sur tous les téléphones quelle que soit la version d'Android utilisée par ceux-ci. On aurait pu utiliser MapFragment, alors la carte ne se serait pas affichée sur des téléphones possédant des versions d'Android inférieures à Android 3.0.
MainActivity doit étendre FragmentActivity au lieu d'Activity.
Définissons le code de l'activité pour afficher un point sur la carte. Les explications sont en commentaire dans le code.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
package
com.abyster.tuto.mapv2;
import
com.google.android.gms.maps.CameraUpdateFactory;
import
com.google.android.gms.maps.GoogleMap;
import
com.google.android.gms.maps.SupportMapFragment;
import
com.google.android.gms.maps.model.BitmapDescriptorFactory;
import
com.google.android.gms.maps.model.LatLng;
import
com.google.android.gms.maps.model.MarkerOptions;
import
android.os.Bundle;
import
android.support.v4.app.FragmentActivity;
import
android.view.Menu;
public
class
MainActivity extends
FragmentActivity {
private
GoogleMap GMap;
private
LatLng yaounde=
new
LatLng
(
3.881501
,11.50818
);
@Override
protected
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.activity_main);
//on récupère le fragment définit dans le layout qui va contenir la carte
GMap=
((
SupportMapFragment)getSupportFragmentManager
(
).findFragmentById
(
R.id.map)).getMap
(
);
//on s'assure que l'objet map n'est pas vide
if
(
GMap!=
null
){
//mode d'affichage de la carte
GMap.setTrafficEnabled
(
true
);
//on autorise l'api à afficher le bouton pour accéder à notre position courante
GMap.setMyLocationEnabled
(
true
);
//définition du marqueur qui va se positionner sur le point qu'on désire afficher
MarkerOptions markerOptions =
new
MarkerOptions
(
);
markerOptions.title
(
"YAOUNDE"
);
markerOptions.visible
(
true
);
markerOptions.position
(
yaounde);
markerOptions.icon
(
BitmapDescriptorFactory.defaultMarker
(
BitmapDescriptorFactory.HUE_YELLOW));
//ajout du marqueur sur la carte
GMap.addMarker
(
markerOptions);
//zoom de la caméra sur la position qu'on désire afficher
GMap.moveCamera
(
CameraUpdateFactory.newLatLngZoom
(
yaounde, 16
));
//animation le zoom toute les 2000ms
GMap.animateCamera
(
CameraUpdateFactory.zoomTo
(
15
), 2000
, null
);
}
}
}
Le niveau de zoom est très important, si vous définissez une mauvaise valeur votre Map n'affichera que la carte du monde. Les deux dernières lignes de code (ligne 40 et 42) vont de paires. La carte ne s'afficherait pas bien sans ces deux instructions. Vous pouvez faire varier la valeur du zoom pour voir les différents effets que cela produit.
V-G. Test de l'application▲
Faites un clic droit sur le projet puis « Run As > Android Application », vous devriez obtenir ceci :
Pour afficher votre position, cliquez sur le bouton représenté par une boussole et la carte se déplace et signale votre position avec un point bleu.
Ce test est fait sur un vrai téléphone et non sur un émulateur, car l'application installée directement sur l'émulateur n'affiche pas la carte.
Cependant, après quelques recherches sur la toile, il se pourrait que cela soit possible moyennant certaines configurations préalables sur l'émulateur.
Si quelqu'un a déjà eu à le faire autrement, ce serait généreux de sa part de le partager avec nous.
VI. Générer l'exécutable (.apk) de l'application▲
Pour mettre l'application en production, il faut créer l'exécutable. Faites un clic droit sur le projet > Android Tools >Exported Signed Application package, vous avez la boîte de dialogue ci-contre :
Sur l'écran suivant, nous allons créer la clé avec laquelle on va signer notre application en production. Cochez le bouton radio « Create new keystore » et remplissez les champs. Utilisez un mot de passe que vous n'allez pas oublier.
Pour l'écran suivant, entrez les informations de signature. Les quatre premiers champs sont obligatoires. Pour le Password, utilisez le même que celui de l'écran précédent.
Maintenant vous pouvez générer votre exécutable.
Installez cet exécutable dans votre mobile et lancez l'application : elle affiche résolument un écran vide juste avec le marqueur. La carte de tout à l'heure ne s'affiche plus.
Pourquoi ?
C'est simple, la clé que nous venons d'utiliser pour signer notre APK est une clé de production que nous avons créée nous-mêmes donc celle-ci est liée au certificat que nous avons créé. Or la clé que nous avons générée au niveau de la console API Google n'est pas liée à ce certificat, mais plutôt à l'empreinte SHA-1 de notre certificat de debogage (l'android.debug que nous avons copié depuis Eclipse).
VI-A. Création de la clé release▲
Pour résoudre ce problème, il faut donc générer une autre clé depuis la console API Google, mais cette fois-ci avec l'empreinte SHA-1 du certificat que nous avons créé pour signer notre APK. Pour le faire, lancez l'invite de commande et positionnez-vous dans le répertoire d'installation de votre JDK.
Saisissez la commande : keytool -list -kystore « chemin vers votre keystore ».
Ensuite il vous est demandé de donner le mot de passe de votre certificat (c'est celui utilisé pour créer votre keystore).
Copiez l'empreinte SHA-1 et générez une nouvelle API Key dans la console Google.
Une fois cette tâche accomplie, copiez cette nouvelle clé dans le Manifest pour remplacer la clé de debogage ci-dessous.
<meta-data
android
:
name
=
"com.google.android.maps.v2.API_KEY"
android
:
value
=
"@string/api_debug_key"
/>
VI-B. Test de l'application avec la clé release▲
VII. Pour aller plus loin▲
Dans ce qui précède, nous avons utilisé les fonctionnalités de base pour l'intégration des Google maps : ultilisation des fragments, ajout des marqueurs, etc.
Mais ces éléments ne sont pas les seuls fournis par l'API v2. Nous allons présenter quelques autres fonctionnalités principales.
VII-A. Shapes▲
Ce sont des formes ou schémas fournis par l'API qu'on peut ajouter à une carte en vue de la personnaliser. On distingue :
- Polyline : c'est une classe fournissant des segments d'interconnexions de coordonnées(LatLng) successives sur une carte, elle peut par exemple permettre de représenter un chemin ;
- Polygon : elle fournit à la base la même fonctionnalité que Polyline sauf qu'ici elle interconnecte des coordonnées successives dans un espace fermé, c'est-à-dire que le point d'arrivée rejoint le point de départ ;
- Circle : permet d'ajouter un cercle sur la carte, cercle centré autour d'une coordonnée spécifique et d'un rayon défini.
VII-B. Location Data▲
Les données de localisation fournissent les informations de localisation d'un appareil Android, elles le font via des fournisseurs de position tels que le GPS et Internet. Cela va de la localisation de l'emplacement actuel de l'appareil à la direction et à la méthode de mouvement. Selon les besoins d'une application, vous pouvez choisir entre plusieurs façons de travailler avec des données de localisation.
- La couche MyLocation : fournit les outils pour afficher la position d'un appareil sur la carte.
- Google Play Services Location API : est utilisé dans la programmation pour toutes les requêtes sur les données de localisation.
- LocationSource : interface permettant à l'utilisateur de définir son propre fournisseur de position.
VII-C. Interaction avec la carte▲
Maps API V2 permet de personnaliser les actions qu'un utilisateur peut réaliser. Cela va de l'ajout de composants d'interface graphique sur la carte à l'ajout des événements autorisés à l'utilisateur et quels comportements adoptés quand ces derniers surviennent.
VIII. Conclusion▲
C'est ici que s'achève ce tutoriel sur l'utilisation de Google Maps Android API V2. J'espère avoir pu aider ceux qui avaient quelques difficultés pour la prise en main de cette API.
IX. Code source du projet▲
Téléchargez le code source de l'exemple ici.
X. Remerciements▲
Je tiens à remercier:
- la société AByster qui m'a permis de travailler sur le projet qui a donné l'idée de ce tutoriel ;
- Feanorin et Mickael Baron pour la relecture de ce tutoriel, également leurs remarques et conseils apportés lors de sa rédaction ;
- Milkoseck pour sa relecture orthographique.