Créer votre propre sélecteur du lieu actuel pour Android (Java)

1. Avant de commencer

Découvrez comment utiliser Google Maps Platform et le SDK Places pour Android afin de présenter à vos utilisateurs une liste de lieux permettant d'identifier leur position actuelle.

bd07a9ad2cb27a06.png

Conditions préalables

  • Compétences de base en Java

Objectifs de l'atelier

  • Ajouter une carte à une application Android
  • Utiliser les autorisations d'accéder à la position afin de géolocaliser l'utilisateur
  • Extraire les lieux situés près de la position actuelle de l'utilisateur
  • Présenter à l'utilisateur des lieux susceptibles d'identifier sa position actuelle

Objectifs de l'atelier

Vous compilez votre application Android de A à Z, mais vous pouvez télécharger l'exemple de code à des fins de comparaison lors du débogage. Téléchargez l'exemple de code depuis GitHub ou, si Git est configuré pour une utilisation avec la ligne de commande, saisissez ce qui suit :

git clone https://github.com/googlecodelabs/current-place-picker-android.git

Si vous rencontrez des problèmes (bugs de code, erreurs grammaticales, formulations imprécises, etc.) au cours de cet atelier de programmation, veuillez nous en informer via le lien Signaler une erreur en bas à gauche de l'atelier de programmation.

2. Commencer

Avant de démarrer cet atelier de programmation, configurez les éléments suivants :

Android Studio

Téléchargez Android Studio à l'adresse https://developer.android.com/studio.

Si vous utilisez déjà Android Studio, vérifiez que vous disposez de la dernière version en cliquant sur Android Studio > Check for Updates… (Android Studio > Rechercher les mises à jour…).

1f36bae83b64e33.png

Cet atelier a été rédigé en utilisant Android Studio 3.4.

SDK Android

Dans Android Studio, vous pouvez configurer les SDK souhaités à l'aide de SDK Manager. Cet atelier utilise le SDK Android Q.

  1. Dans l'écran d'accueil Android Studio, cliquez sur Configure > SDK Manager (Configurer > SDK Manager).

d3fa03c269ec231c.png

  1. Cochez la case correspondant au SDK de votre choix, puis cliquez sur Apply (Appliquer).

Si le SDK n'est pas présent sur votre ordinateur, cette action lance son téléchargement.

884e0aa1314f70d.png

Services Google Play

À partir de SDK Manager, vous devez également installer les services Google Play.

  1. Cliquez sur l'onglet SDK Tools, puis cochez la case Google Play services (Services Google Play).

Si ces services présentent l'état Update available (Mise à jour disponible), mettez-les à jour.

ad6211fd78f3b629.png

3. Préparer l'émulateur

Pour exécuter l'application, vous pouvez connecter votre propre appareil ou utiliser Android Emulator.

Si vous utilisez votre propre appareil, passez à la section Instructions pour les appareils physiques : mettre à jour les services Google Play à la fin de cette page.

Ajouter un émulateur

  1. Dans l'écran d'accueil d'Android Studio, cliquez sur Configure > AVD Manager (Configurer > AVD Manager).

5dd2d14c9c56d3f9.png

La boîte de dialogue Android Virtual Device Manager (Gestionnaire des appareils virtuels Android) s'ouvre.

  1. Cliquez sur Create Virtual Device… (Créer un appareil virtuel) pour ouvrir la liste des appareils disponibles.

2d44eada384f8b35.png

  1. Sélectionnez un appareil accompagné de l'icône Play d5722488d80cd6be.png dans la colonne Play Store, puis cliquez sur Next (Suivant).

e0248f1c6e85ab7c.png

Un ensemble d'images système que vous pouvez installer s'affiche. Si le nom Q ciblant Android 9.+ (Google Play) est accompagnée du mot Download (Télécharger), cliquez sur Download.

316d0d1efabd9f24.png

  1. Cliquez sur Next (Suivant) pour donner un nom à votre appareil virtuel, puis cliquez sur Finish (Terminer).

Vous revenez à la liste Your Virtual Devices (Vos appareils virtuels).

  1. Cliquez sur Start ba8adffe56d3b678.png (Démarrer) à côté de votre nouvel appareil :

7605864ed27f77ea.png

Après quelques instants, l'émulateur s'ouvre.

Instructions concernant l'émulateur : mettre à jour les services Google Play

  1. Une fois l'émulateur lancé, cliquez sur dans la barre de navigation qui s'affiche.

2e1156e02643d018.png

La boîte de dialogue Extended controls (Commandes étendues) s'ouvre.

  1. Dans le menu, cliquez sur Google Play.

Si une mise à jour est disponible, cliquez sur Update (Mettre à jour).

5afd2686c5cad0e5.png

  1. Connectez-vous à l'émulateur avec un compte Google.

Vous pouvez utiliser votre propre compte ou en créer un gratuitement pour dissocier vos informations personnelles de vos tests.

Google Play s'ouvre alors sur les services Google Play.

  1. Cliquez sur Mettre à jour pour obtenir la dernière version des services Google Play.

f4bc067e80630b9c.png

Si vous êtes invité à finaliser la configuration de votre compte et à ajouter une option de paiement, cliquez sur Ignorer.

Définir la position dans l'émulateur

  1. Une fois l'émulateur lancé, saisissez "maps" dans la barre de recherche de l'écran d'accueil pour afficher l'icône de l'application Google Maps.

2d996aadd53685a6.png

  1. Cliquez sur l'icône pour lancer l'application.

Une carte par défaut s'affiche.

  1. En bas à droite de la carte, cliquez sur Votre position c5b4e2fda57a7e71.png.

Vous êtes invité à autoriser le téléphone à utiliser votre position.

f2b68044eabca151.png

  1. Cliquez sur pour ouvrir le menu Extended Controls (Commandes étendues).
  2. Cliquez sur l'onglet Location (Position).
  3. Saisissez une latitude et une longitude.

Spécifiez la position de votre souhait, mais assurez-vous qu'elle est à proximité de nombreuses adresses.

(Pour reproduire les résultats de cet atelier, utilisez la latitude 20.7818 et la longitude -156.4624, qui correspondent à la ville de Kihei, sur l'île hawaïenne Maui.)

  1. Cliquez sur Send (Envoyer). La carte est alors mise à jour avec cette position.

f9576b35218f4187.png

Vous êtes prêt à exécuter votre application et à la tester avec la position.

Instructions pour les appareils physiques : mettre à jour les services Google Play

Si vous utilisez un appareil Android physique, procédez comme suit :

  1. Dans la barre de recherche de l'écran d'accueil, recherchez les services Google Play, puis ouvrez-les.
  2. Cliquez sur Plus d'infos.

Si l'option est disponible, cliquez sur Mettre à jour.

ad16cdb975b5c3f7.png baf0379ef8a9c88c.png

4. Créer le shell d'application avec une activité Google Maps

  1. Sur l'écran d'accueil Android Studio, sélectionnez Start a new Android Studio project (Démarrer un nouveau projet Android Studio).
  2. Dans l'onglet Phone and Tablet (Téléphone et tablette), sélectionnez Google Maps Activity (Activité Google Maps).

c9c80aa8211a8761.png

La boîte de dialogue Configure your project (Configurer votre projet) s'ouvre. C'est ici que vous allez nommer votre application et créer le package basé sur votre domaine.

Voici les paramètres d'une application appelée Current Place, qui correspond au package com.google.codelab.currentplace.

37f5b93b94ee118c.png

  1. Choisissez le langage de programmation Java, puis sélectionnez Use androidx. artifacts* (Utiliser les artefacts androidx.).

Conservez les valeurs par défaut des autres paramètres.

  1. Cliquez sur Finish (Terminer).

5. Ajouter des dépendances de services Google au fichier de compilation Gradle

Pour accéder aux autorisations d'accéder à la position sur Android, vous devez disposer de l'API Google Location and Activity Recognition depuis les services Google Play. Pour en savoir plus sur l'ajout de cette API et d'autres API des services Google Play, consultez l'article Configurer les services Google Play.

Les projets Android Studio comportent généralement deux fichiers build.gradle : un pour le projet global et un pour l'application. Si l'explorateur de projets Android Studio est dans la vue Android, les deux éléments s'affichent dans le dossier Gradle Scripts. Vous devez modifier le fichier build.gradle (Module: app) pour ajouter des services Google.

f3043429cf719c47.png

  1. Ajoutez deux lignes à la section dependencies pour ajouter les services Google de position et l'API Places (exemple de code en contexte).

build.gradle (Module: app)

plugins {
  id 'com.android.application'
}

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.google.codelab.currentplace"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'com.google.android.gms:play-services-maps:16.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

    implementation 'com.google.android.gms:play-services-location:16.0.0'
    implementation 'com.google.android.libraries.places:places:1.1.0'
}

6. Activer les API Google Maps Platform et obtenir une clé API

Pour l'étape suivante, vous devez activer le SDK Maps pour Android et l'API Places.

Configurer Google Maps Platform

Si vous ne disposez pas encore d'un compte Google Cloud Platform ni d'un projet pour lequel la facturation est activée, consultez le guide Premiers pas avec Google Maps Platform pour savoir comment créer un compte de facturation et un projet.

  1. Dans Cloud Console, cliquez sur le menu déroulant des projets, puis sélectionnez celui que vous souhaitez utiliser pour cet atelier de programmation.

  1. Activez les API et les SDK Google Maps Platform requis pour cet atelier de programmation dans Google Cloud Marketplace. Pour ce faire, suivez les étapes indiquées dans cette vidéo ou dans cette documentation.
  2. Générez une clé API sur la page Identifiants de Cloud Console. Vous pouvez suivre la procédure décrite dans cette vidéo ou dans cette documentation. Toutes les requêtes envoyées à Google Maps Platform nécessitent une clé API.

Copiez la clé API que vous venez de créer. Revenez dans Android Studio et recherchez le fichier google_maps_api.xml sous Android > app > res > values.

Remplacez YOUR_KEY_HERE par la clé API que vous avez copiée.

aa576e551a7a1009.png

Votre application est maintenant configurée.

7. Modifier le fichier de mise en page

  1. Dans l'explorateur de projets, ouvrez le fichier activity_maps.xml dans Android > app > res > layout.

4e0d986480c57efa.png

  1. L'interface utilisateur de base s'ouvre à droite de l'écran. Des onglets situés en bas vous permettent de sélectionner l'éditeur de conception ou de texte pour votre mise en page. Sélectionnez Text (Texte), puis remplacez l'intégralité du contenu du fichier de mise en page par le code suivant :

activity_maps.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:minHeight="?attr/actionBarSize"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:titleTextColor="@android:color/white"
        android:background="@color/colorPrimary" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <fragment
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="349dp"
            tools:context=".MapsActivity" />

        <ListView
            android:id="@+id/listPlaces"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

L'interface utilisateur qui s'affiche se présente comme suit :

1bf786808a4697ce.png

8. Configurer la barre d'application

Pour que l'utilisateur puisse cliquer sur un bouton lorsqu'il souhaite sélectionner son lieu actuel, ajoutez une barre d'application avec une icône permettant de trouver le lieu actuel de l'utilisateur et d'afficher ceux à proximité. La barre se présente comme suit :

3a17c92b613a26c5.png

Sur un téléphone, seule l'icône s'affiche. Sur une tablette plus grande, le texte est également affiché.

Créer l'icône

  1. Dans l'explorateur de projets, cliquez sur Android > app, puis faites un clic droit sur le dossier res. Ensuite, sélectionnez New > Image Asset (Nouveau > Élément d'image).

Asset Studio s'ouvre.

  1. Dans le menu Icon Type (Type d'icône), cliquez sur Action Bar and Tab Icons (Barre d'action et icônes d'onglet).
  2. Nommez votre élément ic_geolocate.
  3. Sélectionnez le type d'élément Clip Art (Image clipart).
  4. Cliquez sur l'image située à côté de Clip Art.

La fenêtre Select Icon (Sélectionner une icône) s'ouvre.

  1. Sélectionnez une icône.

Vous pouvez utiliser la barre de recherche pour trouver des icônes adaptées à vos besoins.

  1. Recherchez location et choisissez une icône liée à la notion de lieu.

L'icône My location (Ma position) est identique à celle utilisée dans l'application Google Maps lorsqu'un utilisateur souhaite ancrer l'appareil photo sur sa position actuelle.

  1. Cliquez sur OK > Next > Finish (OK > Suivant > Terminer) et vérifiez la présence d'un nouveau dossier nommé drawable contenant vos nouveaux fichiers d'icônes.

b9e0196137ed18ae.png

Ajouter des ressources de chaîne

  1. Dans l'explorateur de projets, cliquez sur Android > app > res > values, puis ouvrez le fichier strings.xml.
  2. Après <string name="title_activity_maps">Map</string>, ajoutez les lignes suivantes :

strings.xml

    <string name="action_geolocate">Pick Place</string>
    <string name="default_info_title">Default Location</string>
    <string name="default_info_snippet">No places found, because location permission is disabled.</string>

La première ligne est utilisée dans la barre d'application lorsqu'il y a assez d'espace pour inclure un libellé à côté de l'icône. Les autres éléments sont utilisés pour les repères que vous ajoutez à la carte.

Le code du fichier se présente maintenant comme suit :

<resources>
    <string name="app_name">Current Place</string>
    <string name="title_activity_maps">Map</string>
    <string name="action_geolocate">Pick Place</string>
    <string name="default_info_title">Default Location</string>
    <string name="default_info_snippet">No places found, because location permission is disabled.</string>
</resources>

Ajouter la barre d'application

  1. Dans l'explorateur de projets, cliquez sur Android > app, puis faites un clic droit sur le dossier res. Ensuite, sélectionnez New > Directory (Nouveau > Répertoire) pour créer un sous-répertoire sous app/src/main/res.
  2. Nommez le répertoire menu.
  3. Faites un clic droit sur le dossier menu, puis sélectionnez New > File (Nouveau > Fichier).
  4. Nommez le fichier menu.xml.
  5. Collez le code suivant :
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- "Locate me", should appear as action button if possible -->
    <item
        android:id="@+id/action_geolocate"
        android:icon="@drawable/ic_geolocate"
        android:title="@string/action_geolocate"
        app:showAsAction="always|withText" />

</menu>

Modifier le style de la barre d'application

  1. Dans l'explorateur de projets, développez Android > app > res > values, puis ouvrez le fichier styles.xml.
  2. Dans le tag <style>, modifiez la propriété parent et attribuez-lui la valeur "Theme.AppCompat.NoActionBar".
  3. Notez la propriété name, que vous utiliserez à l'étape suivante.

styles.xml

<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">

Mettre à jour le thème de l'application dans le fichier AndroidManifest.xml

  1. Cliquez sur Android > app > manifests, puis ouvrez le fichier AndroidManifest.xml.
  2. Recherchez la ligne android:theme, puis modifiez-la ou confirmez sa valeur, qui doit être @style/AppTheme.

AndroidManifest.xml

   <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

Vous pouvez à présent commencer à coder.

9. Initialiser l'application

  1. Dans l'explorateur de projets, recherchez le fichier MapsActivity.java.

Il se trouve dans le dossier correspondant au package que vous avez créé pour votre application à l'étape 1.

8b0fa27d417f5f55.png

  1. Ouvrez le fichier. Vous accédez alors à l'éditeur de code Java.

Importer le SDK Places et d'autres dépendances

Ajoutez ces lignes en haut de MapsActivity.java pour remplacer les instructions d'importation existantes.

Elles comprennent les importations existantes et permettent d'en ajouter bien d'autres qui sont utilisées dans le code de cet atelier de programmation.

MapsActivity.java

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.model.PlaceLikelihood;
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest;
import com.google.android.libraries.places.api.net.FindCurrentPlaceResponse;
import com.google.android.libraries.places.api.net.PlacesClient;

import java.util.Arrays;
import java.util.List;

Mettre à jour la signature de classe

L'API Places utilise des composants AndroidX pour offrir des capacités de rétrocompatibilité. Vous devez donc la définir pour étendre l'AppCompatActivity. Elle remplace l'extension FragmentActivity définie par défaut pour une activité Google Maps.

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {

Ajouter des variables de classe

Ensuite, déclarez les différentes variables de classe utilisées dans diverses méthodes de classe. (y compris les éléments de l'interface utilisateur et les codes d'état). Celles-ci doivent se trouver juste en dessous de la déclaration de variables pour GoogleMap mMap.

    // New variables for Current Place picker
    private static final String TAG = "MapsActivity";
    ListView lstPlaces;
    private PlacesClient mPlacesClient;
    private FusedLocationProviderClient mFusedLocationProviderClient;

    // The geographical location where the device is currently located. That is, the last-known
    // location retrieved by the Fused Location Provider.
    private Location mLastKnownLocation;

    // A default location (Sydney, Australia) and default zoom to use when location permission is
    // not granted.
    private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085);
    private static final int DEFAULT_ZOOM = 15;
    private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
    private boolean mLocationPermissionGranted;

    // Used for selecting the Current Place.
    private static final int M_MAX_ENTRIES = 5;
    private String[] mLikelyPlaceNames;
    private String[] mLikelyPlaceAddresses;
    private String[] mLikelyPlaceAttributions;
    private LatLng[] mLikelyPlaceLatLngs;

Mettre à jour la méthode onCreate

Vous devez mettre à jour la méthode onCreate afin de gérer les autorisations d'exécution de l'utilisateur pour utiliser les services de localisation, configurer les éléments de l'interface utilisateur et créer le client de l'API Places.

Ajoutez les lignes de code suivantes concernant la barre d'outils d'action, la configuration des vues et le client Places à la fin de la méthode onCreate() existante.

MapsActivity.java onCreate()

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        //
        // PASTE THE LINES BELOW THIS COMMENT
        //

        // Set up the action toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Set up the views
        lstPlaces = (ListView) findViewById(R.id.listPlaces);

        // Initialize the Places client
        String apiKey = getString(R.string.google_maps_key);
        Places.initialize(getApplicationContext(), apiKey);
        mPlacesClient = Places.createClient(this);
        mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
    }

Ajouter le code du menu de votre barre d'application

Ces deux méthodes permettent d'ajouter le menu de la barre d'application (avec un seul élément, l'icône Choisir le lieu) et de gérer le clic de l'utilisateur sur l'icône.

Copiez ces deux méthodes dans votre fichier après la méthode onCreate.

MapsActivity.java onCreateOptionsMenu() et onOptionsItemSelected()

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
           case R.id.action_geolocate:

                // COMMENTED OUT UNTIL WE DEFINE THE METHOD
                // Present the current place picker
                // pickCurrentPlace();
                return true;

            default:
                // If we got here, the user's action was not recognized.
                // Invoke the superclass to handle it.
                return super.onOptionsItemSelected(item);

        }
    }

Tester le code

  1. Dans Android Studio, cliquez sur Run (Exécuter) ou Run menu > Run 'app' (Exécuter le menu > Exécuter l'application).

28bea91c68c36fb2.png

  1. Vous êtes invité à sélectionner la cible de votre déploiement. L'émulateur en cours d'exécution doit apparaître dans cette liste. Sélectionnez-la, puis Android Studio déploie l'application dans l'émulateur.

f44658ca91f6f41a.png

L'application démarre après quelques instants. Une carte centrée sur Sydney, en Australie, s'affiche. Elle présente un seul bouton et une liste de lieux non renseignés.

68eb8c70f4748350.png

Le point sur lequel est centré la carte n'est pas déplacé vers la position de l'utilisateur, sauf si vous demandez l'autorisation d'accéder à la position de l'appareil.

10. Demander et gérer les autorisations d'accéder à la position

Demander les autorisations d'accéder à la position une fois la carte prête

  1. Définissez une méthode appelée getLocationPermission qui demande des autorisations de l'utilisateur.

Collez ce code sous la méthode onOptionsSelected que vous venez de créer.

MapsActivity.java getLocationPermission()

    private void getLocationPermission() {
        /*
         * Request location permission, so that we can get the location of the
         * device. The result of the permission request is handled by a callback,
         * onRequestPermissionsResult.
         */
        mLocationPermissionGranted = false;
        if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
                android.Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            mLocationPermissionGranted = true;
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
        }
    }
  1. Ajoutez deux lignes à la fin de la méthode onMapReady existante pour activer les commandes de zoom et demander à l'utilisateur l'autorisation d'accéder à la position.

MapsActivity.java onMapReady()

   @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));

        //
        // PASTE THE LINES BELOW THIS COMMENT
        //

        // Enable the zoom controls for the map
        mMap.getUiSettings().setZoomControlsEnabled(true);

        // Prompt the user for permission.
        getLocationPermission();

    }

Gérer le résultat des autorisations demandées

Lorsque l'utilisateur répond à la boîte de dialogue d'autorisation de la requête, ce rappel est appelé par Android.

Après la méthode getLocationPermission(), collez le code suivant :

MapsActivity.java onRequestPermissionsResult()

   /**
     * Handles the result of the request for location permissions
     */
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        mLocationPermissionGranted = false;
        switch (requestCode) {
            case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    mLocationPermissionGranted = true;
                }
            }
        }
    }

11. Obtenir la position actuelle et extraire les lieux probables

Lorsque l'utilisateur clique sur Pick Place (Choisir le lieu) dans la barre d'application, l'application appelle la méthode pickCurrentPlace(), qui appelle à son tour la méthode getDeviceLocation() définie précédemment. La méthode getDeviceLocation appelle une autre méthode, getCurrentPlaceLikelihoods,, une fois que la dernière position de l'appareil a été récupérée.

Appeler l'API findCurrentPlace et gérer la réponse

getCurrentPlaceLikelihoods construit une findCurrentPlaceRequest et appelle la tâche findCurrentPlace de l'API Places. Si la tâche aboutit, elle affiche une findCurrentPlaceResponse qui contient une liste d'objets placeLikelihood. Chacun de ces objets comporte un certain nombre de propriétés, y compris le nom et l'adresse du lieu, ainsi que la probabilité que l'utilisateur s'y trouve (valeur double comprise entre 0 et 1). Cette méthode gère la réponse en construisant des listes d'informations sur le lieu à partir de placeLikelihoods.

Ce code parcourt les cinq lieux les plus probables, puis ajoute ceux qui présentent une probabilité supérieure à 0 à une liste qu'il affiche ensuite. Si vous souhaitez afficher plus ou moins de cinq lieux, modifiez la constante M_MAX_ENTRIES.

Collez ce code après la méthode onMapReady.

MapsActivity.java getCurrentPlaceLikelihoods()

   private void getCurrentPlaceLikelihoods() {
        // Use fields to define the data types to return.
        List<Place.Field> placeFields = Arrays.asList(Place.Field.NAME, Place.Field.ADDRESS,
                Place.Field.LAT_LNG);

        // Get the likely places - that is, the businesses and other points of interest that
        // are the best match for the device's current location.
        @SuppressWarnings("MissingPermission") final FindCurrentPlaceRequest request =
                FindCurrentPlaceRequest.builder(placeFields).build();
        Task<FindCurrentPlaceResponse> placeResponse = mPlacesClient.findCurrentPlace(request);
        placeResponse.addOnCompleteListener(this,
                new OnCompleteListener<FindCurrentPlaceResponse>() {
                    @Override
                    public void onComplete(@NonNull Task<FindCurrentPlaceResponse> task) {
                        if (task.isSuccessful()) {
                            FindCurrentPlaceResponse response = task.getResult();
                            // Set the count, handling cases where less than 5 entries are returned.
                            int count;
                            if (response.getPlaceLikelihoods().size() < M_MAX_ENTRIES) {
                                count = response.getPlaceLikelihoods().size();
                            } else {
                                count = M_MAX_ENTRIES;
                            }

                            int i = 0;
                            mLikelyPlaceNames = new String[count];
                            mLikelyPlaceAddresses = new String[count];
                            mLikelyPlaceAttributions = new String[count];
                            mLikelyPlaceLatLngs = new LatLng[count];

                            for (PlaceLikelihood placeLikelihood : response.getPlaceLikelihoods()) {
                                Place currPlace = placeLikelihood.getPlace();
                                mLikelyPlaceNames[i] = currPlace.getName();
                                mLikelyPlaceAddresses[i] = currPlace.getAddress();
                                mLikelyPlaceAttributions[i] = (currPlace.getAttributions() == null) ?
                                        null : TextUtils.join(" ", currPlace.getAttributions());
                                mLikelyPlaceLatLngs[i] = currPlace.getLatLng();

                                String currLatLng = (mLikelyPlaceLatLngs[i] == null) ?
                                        "" : mLikelyPlaceLatLngs[i].toString();

                                Log.i(TAG, String.format("Place " + currPlace.getName()
                                        + " has likelihood: " + placeLikelihood.getLikelihood()
                                        + " at " + currLatLng));

                                i++;
                                if (i > (count - 1)) {
                                    break;
                                }
                            }

                            // COMMENTED OUT UNTIL WE DEFINE THE METHOD
                            // Populate the ListView
                            // fillPlacesList();
                        } else {
                            Exception exception = task.getException();
                            if (exception instanceof ApiException) {
                                ApiException apiException = (ApiException) exception;
                                Log.e(TAG, "Place not found: " + apiException.getStatusCode());
                            }
                        }
                    }
                });
    }

Déplacer l'appareil photo de la carte sur la position actuelle de l'appareil

Si l'utilisateur donne son autorisation, l'application extrait sa dernière position et centre l'appareil photo sur cette position.

Si l'utilisateur refuse l'autorisation, l'application déplace simplement l'appareil photo sur la position par défaut définie parmi les constantes au début de cette page (dans l'exemple de code, il s'agit de Sydney, en Australie).

Après la méthode getPlaceLikelihoods(), collez le code suivant :

MapsActivity.java getDeviceLocation()

    private void getDeviceLocation() {
        /*
         * Get the best and most recent location of the device, which may be null in rare
         * cases when a location is not available.
         */
        try {
            if (mLocationPermissionGranted) {
                Task<Location> locationResult = mFusedLocationProviderClient.getLastLocation();
                locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
                    @Override
                    public void onComplete(@NonNull Task<Location> task) {
                        if (task.isSuccessful()) {
                            // Set the map's camera position to the current location of the device.
                            mLastKnownLocation = task.getResult();
                            Log.d(TAG, "Latitude: " + mLastKnownLocation.getLatitude());
                            Log.d(TAG, "Longitude: " + mLastKnownLocation.getLongitude());
                            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                                    new LatLng(mLastKnownLocation.getLatitude(),
                                            mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
                        } else {
                            Log.d(TAG, "Current location is null. Using defaults.");
                            Log.e(TAG, "Exception: %s", task.getException());
                            mMap.moveCamera(CameraUpdateFactory
                                    .newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
                        }

                       getCurrentPlaceLikelihoods();
                    }
                });
            }
        } catch (SecurityException e)  {
            Log.e("Exception: %s", e.getMessage());
        }
    }

Vérifier si l'autorisation d'accéder à la position a été donnée lorsque l'utilisateur clique sur "Pick Place" (Choisir le lieu)

Lorsque l'utilisateur appuie sur Pick Place (Choisir le lieu), cette méthode vérifie si l'autorisation d'accéder à la position a été donnée. Si ce n'est pas le cas, elle invite l'utilisateur à le faire.

Si l'utilisateur a donné son autorisation, la méthode appelle getDeviceLocation pour lancer le processus d'obtention des lieux probables actuels.

  1. Après getDeviceLocation(), ajoutez la méthode suivante :

MapsActivity.java pickCurrentPlace()

   private void pickCurrentPlace() {
        if (mMap == null) {
            return;
        }

        if (mLocationPermissionGranted) {
            getDeviceLocation();
        } else {
            // The user has not granted permission.
            Log.i(TAG, "The user did not grant location permission.");

            // Add a default marker, because the user hasn't selected a place.
            mMap.addMarker(new MarkerOptions()
                    .title(getString(R.string.default_info_title))
                    .position(mDefaultLocation)
                    .snippet(getString(R.string.default_info_snippet)));

            // Prompt the user for permission.
            getLocationPermission();
        }
    }
  1. Maintenant que pickCurrentPlace est défini, recherchez la ligne onOptionsItemSelected() qui appelle pickCurrentPlace, puis annulez la mise en commentaire.

MapsActivity.java onOptionItemSelected()

           case R.id.action_geolocate:

                // COMMENTED OUT UNTIL WE DEFINE THE METHOD
                // Present the Current Place picker
                pickCurrentPlace();
                return true;

Tester le code

Si vous exécutez maintenant l'application et que vous appuyez sur Pick Place (Choisir le lieu), elle demande l'autorisation d'accéder à la position.

  • Si vous la donnez, cette préférence est enregistrée et l'application ne vous posera plus la question. Si vous refusez de donner l'autorisation, elle vous sera à nouveau demandée la prochaine fois que vous appuierez sur le bouton.
  • Même si getPlaceLikelihoods a extrait les lieux probables, la ListView ne les affiche pas encore. Dans Android Studio, vous pouvez cliquer sur ⌘6 pour examiner les journaux dans Logcat et rechercher les instructions portant le libellé MapsActivity afin de vérifier que vos nouvelles méthodes fonctionnent correctement.
  • Si vous avez donné l'autorisation d'accéder à la position, les journaux incluent une instruction pour Latitude: et une instruction pour Longitude: indiquant la position détectée de l'appareil. Si vous avez déjà utilisé Google Maps et le menu étendu de l'émulateur afin de spécifier une position pour l'émulateur, ces instructions affichent ce lieu.
  • Si l'appel de la fonction findCurrentPlace a abouti, les journaux incluent cinq instructions qui donnent le nom et la position des cinq lieux les plus probables :

d9896a245b81bf3.png

12. Remplir le sélecteur du lieu actuel

Configurer un gestionnaire pour les lieux choisis

Regardons comment procéder lorsque l'utilisateur clique sur un élément de la ListView. Pour confirmer le choix de l'utilisateur concernant le lieu où il se trouve actuellement, vous pouvez ajouter un repère à la carte, à cet endroit. Si l'utilisateur clique sur ce repère, une fenêtre d'informations s'affiche avec le nom et l'adresse du lieu.

Après la méthode pickCurrentPlace, collez le gestionnaire de clics suivant :

MapsActivity.java listClickedHandler

    private AdapterView.OnItemClickListener listClickedHandler = new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView parent, View v, int position, long id) {
            // position will give us the index of which place was selected in the array
            LatLng markerLatLng = mLikelyPlaceLatLngs[position];
            String markerSnippet = mLikelyPlaceAddresses[position];
            if (mLikelyPlaceAttributions[position] != null) {
                markerSnippet = markerSnippet + "\n" + mLikelyPlaceAttributions[position];
            }

            // Add a marker for the selected place, with an info window
            // showing information about that place.
            mMap.addMarker(new MarkerOptions()
                    .title(mLikelyPlaceNames[position])
                    .position(markerLatLng)
                    .snippet(markerSnippet));

           // Position the map's camera at the location of the marker.
            mMap.moveCamera(CameraUpdateFactory.newLatLng(markerLatLng));
        }
    };

Remplir la ListView

Maintenant que vous disposez de la liste des lieux dans lesquels l'utilisateur est le plus susceptible de se trouver actuellement, vous pouvez lui présenter ces options dans la ListView. Vous pouvez également configurer l'écouteur de clics ListView afin qu'il utilise le gestionnaire de clics que vous venez de définir.

Après le gestionnaire de clics, collez la méthode suivante :

MapsActivity.java fillPlacesList()

    private void fillPlacesList() {
        // Set up an ArrayAdapter to convert likely places into TextViews to populate the ListView
        ArrayAdapter<String> placesAdapter =
                new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mLikelyPlaceNames);
        lstPlaces.setAdapter(placesAdapter);
        lstPlaces.setOnItemClickListener(listClickedHandler);
    }

Maintenant que fillPlacesList est défini, recherchez la ligne située à la fin de findPlaceLikelihoods qui appelle fillPlacesList, puis annulez la mise en commentaire.

MapsActivity.java fillPlaceLikelihoods()

               // COMMENTED OUT UNTIL WE DEFINE THE METHOD
                // Populate the ListView
                fillPlacesList();

Vous avez terminé d'écrire le code nécessaire pour votre sélecteur du lieu actuel.

13. Exécuter l'application

Tester le sélecteur de lieu

  1. Exécutez à nouveau l'application.

Cette fois, lorsque vous appuyez sur Pick Place (Choisir le lieu), l'application remplit la liste avec les lieux nommés à proximité de la position. Près de cette position à Maui se trouvent des lieux comme Ululani's Hawaiian Shave Ice et Sugar Beach Bake Shop. Cette liste répertorie différents lieux très proches des coordonnées de la position. Ils sont donc susceptibles d'y figurer.

  1. Cliquez sur un nom de lieu dans la ListView.

Un repère doit s'afficher sur la carte.

  1. Appuyez sur ce repère.

Vous pouvez consulter les détails du lieu.

e52303cc0de6a513.png 864c74342fb52a01.png

Tester une autre position

Si vous souhaitez modifier votre position et que vous utilisez l'émulateur, la position de l'appareil n'est pas automatiquement actualisée lorsque vous mettez à jour les coordonnées dans le menu étendu de l'émulateur.

Pour résoudre ce problème, procédez comme suit afin d'utiliser l'application Google Maps native pour forcer la mise à jour de la position affichée dans l'émulateur :

  1. Ouvrez Google Maps.
  2. Appuyez sur  > Localisation pour remplacer la latitude et la longitude par de nouvelles coordonnées, puis appuyez sur Envoyer.
  3. Par exemple, vous pouvez utiliser la latitude 49.2768 et la longitude -123.1142 pour définir la position du centre-ville de Vancouver (Canada).
  4. Vérifiez que Google Maps a recentré la carte sur vos nouvelles coordonnées. Pour demander cette mise à jour, vous devrez peut-être appuyer sur le bouton Ma position dans l'application Google Maps.
  5. Revenez à l'application de sélection du lieu actuel, puis appuyez sur Pick Place (Choisir le lieu) pour afficher la carte avec les nouvelles coordonnées. Une nouvelle liste des lieux actuels probables s'affiche.

9adb99d1ce25c184.png

Voilà, c'est terminé ! Vous avez créé une application simple qui repère les lieux à la position actuelle de l'utilisateur et vous indique la probabilité qu'il se trouve à chacun d'entre eux. Profitez bien de cette application !

Pour suivre cette étape bonus, exécutez l'application avec les modifications que vous avez apportées.

14. Étapes suivantes

Afin d'empêcher tout vol de votre clé API, vous devez la sécuriser afin que seule votre application Android puisse l'utiliser. Sinon, tous les utilisateurs disposant de votre clé peuvent l'utiliser afin d'appeler les API Google Maps Platform, ce qui peut entraîner des frais à votre charge.

Obtenir votre certificat SHA-1

Vous en aurez besoin ultérieurement pour restreindre vos clés API. Vous trouverez ci-dessous un ensemble d'instructions à suivre pour obtenir votre certificat de débogage.

Pour Linux ou macOS, ouvrez une fenêtre sur le terminal et procédez comme suit :

keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

Sous Windows Vista et Windows 7, exécutez la commande suivante :

keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android

Le résultat doit ressembler à ce qui suit :

Alias name: androiddebugkey
Creation date: Jan 01, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 4aa9b300
Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033
Certificate fingerprints:
     MD5:  AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9
     SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75
     Signature algorithm name: SHA1withRSA
     Version: 3

La ligne commençant par SHA1 contient l'empreinte SHA-1 du certificat. L'empreinte correspond à la séquence de 20 nombres hexadécimaux à deux chiffres séparés par un deux-points.

Lorsque vous êtes prêt à publier une application, suivez les instructions de cette documentation pour récupérer votre certificat de version.

Restreindre votre clé API

  1. Dans Cloud Console, accédez à API et services > Identifiants.

La clé que vous avez utilisée pour cette application doit être répertoriée sous "Clés API".

  1. Cliquez sur 6454a04865d551e6.png pour modifier les paramètres de la clé.

316b052c621ee91c.png

  1. Sur la page "Clé API", sous Restrictions relatives aux clés, définissez les Restrictions relatives aux applications en procédant comme suit :
  2. Sélectionnez Applications Android, puis suivez les instructions.
  3. Cliquez sur Ajouter un élément.
  4. Saisissez le nom du package et l'empreinte du certificat SHA-1 (récupérés à la section précédente).

Exemple :

com.google.codelab.currentplace
BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75s
  1. Pour une protection supplémentaire, définissez les Restrictions relatives aux API en procédant comme suit.
  2. Après "Restrictions relatives aux API", sélectionnez Restreindre la clé.
  3. Sélectionnez le SDK Maps pour Android et l'API Places.
  4. Cliquez sur OK et sur Enregistrer.

15. Félicitations

Vous avez créé une application simple qui recherche les lieux les plus probables à la position actuelle de l'utilisateur et ajoute un repère sur la carte pour le lieu que l'utilisateur sélectionne.

En savoir plus