Ludovic ROLAND

Blog technique sur mes expériences de développeur.

Intégrer et utiliser une carte Google dans une application Android (4/7) : Intégration de la carte

15 juillet 2016

Dans les étapes précédentes, nous avons déclaré notre application auprès de Google et généré une clef afin d’être en mesure de pouvoir utiliser le service de cartographie de Google dans lapplication Android que nous avons créé il y a seulement quelques minutes.

La partie intéressante de ce tutoriel va enfin pouvoir commencer ! Au cours de ce chapitre, nous allons voir étape par étape comment intégrer une carte Google dans une application Android

L’intégralité de ce chapitre se passe sur internet et plus précisément dans la console développeur de Google.

Plan

Du côté de Gradle

Comme je vous le disais dans le tout premier chapitre de ce tutoriel qui concernait l’installation et la configuration des outils nécessaires à ce tutoriel, nous allons devoir utiliser les Google Play Services. Pour rappel, il s’agit d’un ensemble de classes et fonctions qui vont nous permettre de manipuler les technologies Google comme par exemple :

  • Google Maps
  • Google+
  • Google Wallet
  • Google Fit
  • etc.

Nous allons donc devoir importer ces fameux services dans notre projet d’application afin de pouvoir les utiliser puisqu’ils sont nécessaires à l’affichage d’une carte Google.

Il n’y a pas si longtemps de ça, lorsque nous avions besoin d’intégrer une carte Google dans une application Android, nous étions obligés d’importer dans notre projet tous les Google Play Services. Cette contrainte a longtemps été présentie comme un gros désavantage et a fait râler plus d’un développeur : les Google Play Services c’étaient plus de 14 000 méthodes. Pour bien comprendre ce désavantage, il est important de savoir qu’une application Android basique, ne peut pas contenir plus de 65 536 méthodes. Le nombre de méthodes embarquées dans une application c’est la somme des méthodes que vous avez écrits dans votre projet et l’ensemble des méthodes contenues dans les différentes bibliothèques (jar et aar) et des autres modules dont votre projet dépend. Si vous faites un rapide calcul, vous vous rendez compte que lorsque vous utilisiez les Google Play Services, vous utilisiez 20% des méthodes dont vous aviez le droit dans votre application, ce qui est énorme.

Parmi les solutions les plus répendues à l’époque pour contourner le problème, on peut par exemple citer des scripts qui permettaient de faire “mincir” les Google Play Services ou encore la mise en place de ce qu’on appelle le multi-dex. Cette seconde solution permet d’embarquer plus de 65 536 méthodes dans une application mobile, mais si aujourd’hui Google proposent des outils pour facilement le mettre en place, ce n’était pas le cas à l’époque.

Rassurez-vous, aujourd’hui Google a pris les choses en main et propose ses Google Play Services sous la forme de modules. Grâce à ces modules, vous pouvez importer dans votre projet uniquement ce dont vous avez vraiment besoin. Ainsi, on retrouve par exemple :

  • Un module pour la Google Chromecast
  • Un module pour la régie publicitaire Google Ad Mob
  • Un module pour Google Maps
  • Un module pour Google+
  • etc.

Dans le cadre de ce tutoriel, nous allons bien évidemment utiliser toute la puissance de ces modules pour n’importer que ce dont nous avons besoin à savoir le module pour Google Maps.

Nous allons donc ajouter dans le fichier build.gradle de notre module, une dépendance au module Google Maps des Google Play Services grâce à la ligne suivante :

compile 'com.google.android.gms:play-services-maps:8.4.0'
apply plugin: 'com.android.application'

android
{
  compileSdkVersion 23
  buildToolsVersion "23.0.2"

  defaultConfig
  {
    applicationId "fr.openclassrooms.geolocalisation"

    minSdkVersion 9
    targetSdkVersion 23

    versionCode 1
    versionName "1.0"
  }

  buildTypes
  {
    release
    {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies
{
  compile 'com.android.support:appcompat-v7:23.1.1'
  compile 'com.google.android.gms:play-services-maps:8.4.0'
}

Le manifest

Maintenant que le module Google Maps des Google Play Services est utilisable dans notre application, nous allons nous attaquer à la mise à jour du manifest de notre application à travers la modification du fichier AndroidManifest.xml et plus précisément à travers l’ajout de méta-data, de permissions et la déclarations de features.

Cette partie relativement simple ne devrait pas vous prendre énormément de temps.

Les méta-data

Nous allons donc débuter par l’ajout de quelques meta-data dans le fichier AndroidManifest.xml de notre application Android. Actuellement, ce fameux fichier doit ressembler à ça :

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="fr.openclassrooms.geolocalisation"
>
  <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
  >
    <activity
      android:name=".MainActivity"
      android:label="@string/app_name"
      android:theme="@style/AppTheme.NoActionBar"
    >
      <intent-filter>
        <action android:name="android.intent.action.MAIN"></action>
        <category android:name="android.intent.category.LAUNCHER"></category>
      </intent-filter>
    </activity>
  </application>
</manifest>

La première méta-data à déclarer au sein du manifest de notre application est la clef de service Google Maps Android API v2 que nous avons créé dans un précédent chapitre. Cette méta-data sera exploitée par le système de Google pour vérifier que notre application est bien autorisée à afficher une carte Google sans quoi, aucune carte ne sera affichée dans notre application. La carte sera alors remplacée par un fond gris que trop de développeurs connaissent.

Pour déclarer la clef de service Google Maps Android API v2 en tant que méta-data, il convient d’ajouter l’élément suivant dans le manifest :

<meta-data
  android:name="com.google.android.maps.v2.API_KEY"
  android:value="AIzaSyCmLsrHx6T_nqA5B4xkWGZbe47wnfr7ApU"
/>

La seconde méta-data que nous allons ajouter au manifest de notre application est directement liée aux Google Play Services puisqu’elle consiste à déclarer la version utilisée au sein de notre application. Rassurez-vous, cette donnée nous est fournie par Google. Aussi, il convient de simplement rajouter l’élément suivant dans le manifest :

<meta-data
  android:name="com.google.android.gms.version"
  android:value="@integer/google_play_services_version"
/>

A l’issue de cette première série de modification, votre fichier AndroidManifest.xml doit alors ressembler à ça :

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="fr.openclassrooms.geolocalisation"
>
  <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
  >
    <meta-data
      android:name="com.google.android.maps.v2.API_KEY"
      android:value="AIzaSyCmLsrHx6T_nqA5B4xkWGZbe47wnfr7ApU"
    />

    <meta-data
      android:name="com.google.android.gms.version"
      android:value="@integer/google_play_services_version"
    />

    <activity
      android:name=".MainActivity"
      android:label="@string/app_name"
      android:theme="@style/AppTheme.NoActionBar"
    >
      <intent-filter>
        <action android:name="android.intent.action.MAIN"></action>
        <category android:name="android.intent.category.LAUNCHER"></category>
      </intent-filter>
    </activity>
  </application>
</manifest>

Les permissions

Maintenant que nous en avons terminé avec les méta-data, nous allons nous attaquer à la déclaration des permissions nécessaires à notre application pour afficher une carte à travers le service Google Maps Android API v2.

Bonne nouvelle pour les développeurs que vous êtes, il n’y a que trois permissions des plus classiques à déclarer ce qui ne devrait pas faire fuir vos utilisateurs. Les permissions à ajouter au manifest de l’application sont les suivantes :

  • INTERNET : cette permission est nécessaire afin que les tuiles de la carte puissent être téléchargées.
  • ACCESS_NETWORK_STATE : cette permission est nécessaire afin d’adapter le comportement de la carte et notamment afin qu’elle ne tente pas de télécharger des tuiles si le terminal n’a pas accès à internet.
  • WRITE_EXTERNAL_STORAGE : cette permission est nécessaire afin que les tuiles de la carte puissent être mises en cache afin de permettre un affichage hors-ligne ou tout simplement un affichage plus rapide de la carte lors des prochains lancements de l’application.

Au niveau du manifest, l’ajout des permissions se traduit par l’ajout des éléments suivants :

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

A l’issue de cette étape, votre fichier AndroidManifest.xml doit alors ressembler à ça :

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="fr.openclassrooms.geolocalisation"
>
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  
  <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
  >
    <meta-data
      android:name="com.google.android.maps.v2.API_KEY"
      android:value="AIzaSyCmLsrHx6T_nqA5B4xkWGZbe47wnfr7ApU"
    />

    <meta-data
      android:name="com.google.android.gms.version"
      android:value="@integer/google_play_services_version"
    />

    <activity
      android:name=".MainActivity"
      android:label="@string/app_name"
      android:theme="@style/AppTheme.NoActionBar"
    >
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
    </activity>
  </application>
</manifest>

Les features

Nous venons donc de mettre à jour le manifest de notre application en y ajoutant les permissions nécessaires au bon fonctionnement de la carte de Google. Il nous reste encore une petite modification à faire. Il convient en effet de dire, toujours au niveau de notre manifest, que notre application utilise la version 2 de la technologie OpenGL ES.

Cette étape n’est nullement obligatoire, mais déclarer l’utilisation de cette technologie indispensable au bon fonctionnement du service Google Maps Android API v2, va nous permettre, au niveau du Google Play Store, de ne proposer notre application qu’aux terminaux réellement capables de la faire tourner.

La déclaration de l’utilisation de cette technologie se fait via la balise <uses-features /> qu’il convient de placer dans la balise <manifest />. L’élément complet à ajouter au manifest est le suivant :

<uses-feature
  android:glEsVersion="0x00020000"
  android:required="true"
/>

A l’issue de cette utime étape, votre fichier AndroidManifest.xml doit alors ressembler à ça :

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="fr.openclassrooms.geolocalisation"
>
  <uses-feature
    android:glEsVersion="0x00020000"
    android:required="true"
  />

  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
  >
    <meta-data
      android:name="com.google.android.maps.v2.API_KEY"
      android:value="AIzaSyCmLsrHx6T_nqA5B4xkWGZbe47wnfr7ApU"
    />

    <meta-data
      android:name="com.google.android.gms.version"
      android:value="@integer/google_play_services_version"
    />

    <activity
      android:name=".MainActivity"
      android:label="@string/app_name"
      android:theme="@style/AppTheme.NoActionBar"
    >
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
    </activity>
  </application>
</manifest>

Layout

Nous y sommes presque ! D’ici quelques minutes seulement, nous seront en mesure d’afficher une carte Google dans notre application ! Pour cela, nous allons déclarer une carte Google directement dans le layout de notre fragment principal. Il convient alors de modifier le contenu du fichier fragment_main.xml.

En réalité, une carte Google est un fragment. Nous allons donc être obligé d’utilisé la balise <fragment /> directement dans le layout.

La version “support”

Dans le cas où l’API minimale supportée par votre application est inférieure à 12, vous allez être dans l’obligation d’utiliser la version support du composant de Google à travers l’utilisation de la classe SupportMapFragment.

Modifiez alors le fichier fragment_main.xml pour qu’il affiche une instance de cette classe :

<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"
/>

Comme vous pouvez le constater, il s’agit d’une utilisation relativement classique d’un fragment. Bien que nous nous en servions pas tout de suite, je me suis permis de déclarer un identifiant au composant graphique. Notez bien le nom complet du package de la classe que l’on souhaite instancier au niveau de l’attribut android:name.

Vous pouvez dès maintenant compiler et exécuter votre application. Si vous avez respecter toutes les étapes décrites jusqu’à maintenant dans ce tutoriel, vous devriez voir s’afficher une carte sur l’écran de votre téléphone, comme en témoigne la capture d’écran suivante :

La version “non support”

Dans le cas où l’API minimale supportée par votre application est supérieure ou égale à 12, vous allez pouvoir, mais ce n’est nullement une obligation, utiliser la version non support du composant de Google à travers l’utilisation de la classe MapFragment.

Modifiez alors le fichier fragment_main.xml pour qu’il affiche une instance de cette classe :

<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.MapFragment"
/>

Une nouvelle fois, il s’agit d’une utilisation relativement classique d’un fragment. Bien que nous nous en servions pas tout de suite, je me suis permis de déclarer un identifiant au composant graphique. Notez bien le nom complet du package de la classe que l’on souhaite instancier au niveau de l’attribut android:name.

Vous pouvez dès maintenant compiler et exécuter votre application. Si vous avez respecter toutes les étapes décrites jusqu’à maintenant dans ce tutoriel, vous devriez voir s’afficher une carte sur l’écran de votre téléphone, comme en témoigne la capture d’écran suivante :

En résumé

Pour afficher une carte Google au sein d’une application il convient :

  • d’ajouter un certain nombre d’élément au niveau du manifest et plus précisément des meta-data, des permissions et des features.
  • d’utiliser la classe MapFragment ou SupportMapFragment en fonction de l’API minimale supportée par l’application.

Commentaires