1. Avant de commencer
Android 10 et 11 permettent aux utilisateurs de mieux contrôler l'accès de leurs applications à la position de leur appareil.
Lorsqu'une application exécutée sur Android 11 demande l'accès à la position, les utilisateurs ont quatre options :
- Toujours autoriser
- Autoriser seulement si l'appli est en cours d'utilisation (Android 10)
- Une seule fois (dans Android 11)
- Refuser
Android 10

Android 11

Dans cet atelier de programmation, vous allez apprendre à recevoir des mises à jour de localisation et à prendre en charge la localisation sur n'importe quelle version d'Android, en particulier Android 10 et 11. À la fin de l'atelier de programmation, vous devriez disposer d'une application qui suit les bonnes pratiques actuelles pour récupérer les mises à jour de localisation.
Prérequis
- Connaissances en développement Android
- Bonne connaissance des activités, des services et des autorisations
Objectifs de l'atelier
- Suivez les bonnes pratiques concernant la localisation sur Android.
- Gérez les autorisations d'accéder à la position au premier plan (lorsque l'utilisateur demande à votre application d'accéder à la position de l'appareil pendant qu'elle est en cours d'utilisation).
- Modifiez une application existante pour ajouter la prise en charge de la demande d'accès à la position en ajoutant du code pour s'abonner et se désabonner à la position.
- Ajoutez la prise en charge d'Android 10 et 11 à l'application en ajoutant une logique pour accéder à la position au premier plan ou en cours d'utilisation.
Prérequis
- Android Studio 3.4 ou version ultérieure pour exécuter le code
- Un appareil ou un émulateur exécutant une version Preview développeur d'Android 10 et 11
2. Premiers pas
Cloner les éléments du projet de démarrage
Pour vous aider à démarrer le plus rapidement possible, vous pouvez vous appuyer sur ce projet de démarrage. Si Git est installé, vous pouvez simplement exécuter la commande suivante :
git clone https://github.com/android/codelab-while-in-use-location
N'hésitez pas à consulter directement la page GitHub.
Si vous n'avez pas Git, vous pouvez obtenir le projet sous forme de fichier ZIP :
Importer le projet
Ouvrez Android Studio, sélectionnez Open an existing Android Studio project (Ouvrir un projet Android Studio existant) sur l'écran d'accueil, puis ouvrez le répertoire du projet.
Une fois le projet chargé, une alerte peut s'afficher, indiquant que Git ne suit pas toutes les modifications locales. Vous pouvez cliquer sur Ignorer. (Vous ne transmettrez pas vos modifications au dépôt Git.)
En haut à gauche de la fenêtre du projet, vous devriez obtenir une image semblable à celle ci-dessous si vous êtes dans la vue Android. (Si vous êtes dans la vue Project (Projet), vous devez développer le projet pour voir la même chose.)

Deux dossiers s'affichent (base et complete). Chacun est considéré comme un "module".
Notez que, la première fois, Android Studio peut mettre plusieurs secondes pour compiler le projet en arrière-plan. Pendant ce temps, le message suivant s'affiche dans la barre d'état en bas d'Android Studio :

Attendez qu'Android Studio ait terminé d'indexer et de compiler le projet avant de modifier le code. Android Studio pourra ainsi récupérer tous les composants nécessaires.
Si une invite Reload for language changes to take effect? (Charger à nouveau pour appliquer les modifications de langue) ou similaire apparaît, sélectionnez Yes (Oui).
Comprendre le projet de démarrage
Vous êtes prêt à demander la position dans l'application. Utilisez le module base comme point de départ. À chaque étape, ajoutez du code au module base. À la fin de cet atelier de programmation, le code du module base doit correspondre au contenu du module complete. Vous pouvez utiliser le module complete pour vérifier votre travail ou comme référence si vous rencontrez des problèmes.
Voici les principaux composants :
MainActivity: interface utilisateur permettant à l'utilisateur d'autoriser l'application à accéder à la position de l'appareilLocationService: service qui s'abonne aux changements de position et se désabonne, et qui se promeut en service de premier plan (avec une notification) si l'utilisateur quitte l'activité de l'application. Ajoutez le code du lieu ici.Util: ajoute des fonctions d'extension pour la classeLocationet enregistre la position dansSharedPreferences(couche de données simplifiée).
Configuration de l'émulateur
Pour savoir comment configurer un émulateur Android, consultez Exécuter sur un émulateur.
Exécuter le projet de démarrage
Exécutez votre application.
- Connectez votre appareil Android à votre ordinateur ou démarrez un émulateur. (Assurez-vous que l'appareil est équipé d'Android 10 ou version ultérieure.)
- Dans la barre d'outils, sélectionnez la configuration
basedans le menu déroulant, puis cliquez sur Exécuter :

- L'application suivante s'affiche sur votre appareil :

Vous remarquerez peut-être qu'aucune information sur la position ne s'affiche sur l'écran de sortie. En effet, vous n'avez pas encore ajouté le code du lieu.
3. Ajouter un lieu
Concepts
L'objectif de cet atelier de programmation est de vous montrer comment recevoir des notifications de position et, à terme, comment prendre en charge Android 10 et Android 11.
Toutefois, avant de commencer à coder, il est judicieux de revoir les bases.
Types d'accès à la position
Vous vous souvenez peut-être des quatre options d'accès à la position que nous avons vues au début de l'atelier de programmation. Voici ce que cela signifie :
- Autoriser seulement si l'appli est en cours d'utilisation
- Cette option est recommandée pour la plupart des applications. Également appelée accès "si l'application est ouverte" ou "au premier plan uniquement", cette option a été ajoutée dans Android 10 et permet aux développeurs de récupérer la position uniquement lorsque l'application est activement utilisée. Une application est considérée comme active si l'une des conditions suivantes est remplie :
- Une activité est visible.
- Un service de premier plan est en cours d'exécution avec une notification d'activité en cours.
- Une seule fois
- Ajoutée dans Android 11, cette option est identique à Autoriser seulement si l'appli est en cours d'utilisation, mais pour une durée limitée. Pour en savoir plus, consultez Autorisations ponctuelles.
- Refuser
- Cette option empêche l'accès aux informations de localisation.
- Toujours autoriser
- Cette option permet d'accéder à la position en permanence, mais nécessite une autorisation supplémentaire pour Android 10 et versions ultérieures. Vous devez également vous assurer d'avoir un cas d'utilisation valide et de respecter les Règles relatives à la localisation. Nous n'aborderons pas cette option dans cet atelier de programmation, car il s'agit d'un cas d'utilisation plus rare. Toutefois, si vous avez un cas d'utilisation valide et que vous souhaitez comprendre comment gérer correctement la localisation en continu, y compris l'accès à la localisation en arrière-plan, consultez l'exemple LocationUpdatesBackgroundKotlin.
Services, services de premier plan et liaison
Pour prendre entièrement en charge les mises à jour de la position avec l'option Autoriser seulement si l'appli est en cours d'utilisation, vous devez tenir compte du moment où l'utilisateur quitte votre application. Si vous souhaitez continuer à recevoir des mises à jour dans ce cas, vous devez créer un Service de premier plan et l'associer à un Notification.
De plus, si vous souhaitez utiliser le même Service pour demander des mises à jour de la position lorsque votre application est visible et lorsque l'utilisateur quitte votre application, vous devez lier/délier ce Service à l'élément d'interface utilisateur.
Comme cet atelier de programmation se concentre uniquement sur la réception des mises à jour de localisation, vous trouverez tout le code dont vous avez besoin dans la classe ForegroundOnlyLocationService.kt. Vous pouvez parcourir cette classe et le MainActivity.kt pour voir comment ils fonctionnent ensemble.
Pour en savoir plus, consultez Présentation des services et Présentation des services liés.
Autorisations
Pour recevoir des mises à jour de la position à partir d'un NETWORK_PROVIDER ou d'un GPS_PROVIDER, vous devez demander l'autorisation de l'utilisateur en déclarant l'autorisation ACCESS_COARSE_LOCATION ou ACCESS_FINE_LOCATION, respectivement, dans votre fichier manifeste Android. Sans ces autorisations, votre application ne pourra pas demander l'accès à la position lors de l'exécution.
Ces autorisations couvrent les cas Une seule fois et Autoriser seulement si l'appli est en cours d'utilisation lorsque votre application est utilisée sur un appareil exécutant Android 10 ou version ultérieure.
Emplacement
Votre application peut accéder à l'ensemble des services de localisation compatibles via les classes du package com.google.android.gms.location.
Examinons les classes principales :
FusedLocationProviderClient- Il s'agit du composant central du framework de localisation. Une fois créé, vous l'utilisez pour demander des mises à jour de la position et obtenir la dernière position connue.
LocationRequest- Il s'agit d'un objet de données contenant des paramètres de qualité de service pour les requêtes (intervalles de mise à jour, priorités et précision). Cette valeur est transmise à
FusedLocationProviderClientlorsque vous demandez des mises à jour de la position. LocationCallback- Il est utilisé pour recevoir des notifications lorsque la position de l'appareil a changé ou ne peut plus être déterminée. Un
LocationResultest transmis, à partir duquel vous pouvez obtenir leLocationà enregistrer dans votre base de données.
Maintenant que vous avez une idée de base de ce que vous faites, lancez-vous dans le code !
4. Ajouter des fonctionnalités de localisation
Cet atelier de programmation se concentre sur l'option de localisation la plus courante : Autoriser seulement si l'appli est en cours d'utilisation.
Pour recevoir des mises à jour de la position, votre application doit avoir une activité visible ou un service s'exécutant au premier plan (avec une notification).
Autorisations
L'objectif de cet atelier de programmation est de vous montrer comment recevoir des notifications de position, et non comment demander des autorisations d'accès à la position. Le code basé sur les autorisations est donc déjà écrit pour vous. N'hésitez pas à l'ignorer si vous le comprenez déjà.
Voici les points clés concernant les autorisations (aucune action n'est requise pour cette partie) :
- Déclarez l'autorisation que vous utilisez dans le fichier
AndroidManifest.xml. - Avant de tenter d'accéder aux informations de localisation, vérifiez si l'utilisateur a accordé l'autorisation à votre application. Si votre application n'a pas encore reçu l'autorisation, demandez-la.
- Gérez le choix de l'utilisateur concernant les autorisations. (Vous pouvez voir ce code dans le fichier
MainActivity.kt.)
Si vous recherchez TODO: Step 1.0, Review Permissions dans AndroidManifest.xml ou MainActivity.kt, vous verrez tout le code écrit pour les autorisations.
Pour en savoir plus, consultez Présentation des autorisations.
Maintenant, commencez à écrire du code de localisation.
Examiner les principales variables nécessaires pour les mises à jour de localisation
Dans le module base, recherchez TODO: Step 1.1, Review variables dans
Fichier ForegroundOnlyLocationService.kt.
Aucune action n'est requise à cette étape. Il vous suffit d'examiner le bloc de code suivant, ainsi que les commentaires, pour comprendre les classes et variables clés que vous utilisez pour recevoir les mises à jour de localisation.
// TODO: Step 1.1, Review variables (no changes).
// FusedLocationProviderClient - Main class for receiving location updates.
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
// LocationRequest - Requirements for the location updates, i.e., how often you
// should receive updates, the priority, etc.
private lateinit var locationRequest: LocationRequest
// LocationCallback - Called when FusedLocationProviderClient has a new Location.
private lateinit var locationCallback: LocationCallback
// Used only for local storage of the last known location. Usually, this would be saved to your
// database, but because this is a simplified sample without a full database, we only need the
// last location to create a Notification if the user navigates away from the app.
private var currentLocation: Location? = null
Examiner l'initialisation de FusedLocationProviderClient
Dans le module base, recherchez TODO: Step 1.2, Review the FusedLocationProviderClient dans le fichier ForegroundOnlyLocationService.kt. Votre code doit se présenter comme suit :
// TODO: Step 1.2, Review the FusedLocationProviderClient.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
Comme indiqué dans les commentaires précédents, il s'agit de la classe principale pour obtenir des informations sur la position. La variable est déjà initialisée pour vous, mais il est important d'examiner le code pour comprendre comment elle est initialisée. Vous ajouterez du code ici plus tard pour demander des mises à jour de la position.
Initialiser LocationRequest
- Dans le module
base, recherchezTODO: Step 1.3, Create a LocationRequestdans le fichierForegroundOnlyLocationService.kt. - Ajoutez le code suivant après le commentaire.
Le code d'initialisation LocationRequest ajoute les paramètres de qualité de service supplémentaires dont vous avez besoin pour votre requête (intervalles, temps d'attente maximal et priorité).
// TODO: Step 1.3, Create a LocationRequest.
locationRequest = LocationRequest.create().apply {
// Sets the desired interval for active location updates. This interval is inexact. You
// may not receive updates at all if no location sources are available, or you may
// receive them less frequently than requested. You may also receive updates more
// frequently than requested if other applications are requesting location at a more
// frequent interval.
//
// IMPORTANT NOTE: Apps running on Android 8.0 and higher devices (regardless of
// targetSdkVersion) may receive updates less frequently than this interval when the app
// is no longer in the foreground.
interval = TimeUnit.SECONDS.toMillis(60)
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates more frequently than this value.
fastestInterval = TimeUnit.SECONDS.toMillis(30)
// Sets the maximum time when batched location updates are delivered. Updates may be
// delivered sooner than this interval.
maxWaitTime = TimeUnit.MINUTES.toMillis(2)
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
- Lisez les commentaires pour comprendre le fonctionnement de chacun d'eux.
Initialiser LocationCallback
- Dans le module
base, recherchezTODO: Step 1.4, Initialize the LocationCallbackdans le fichierForegroundOnlyLocationService.kt. - Ajoutez le code suivant après le commentaire.
// TODO: Step 1.4, Initialize the LocationCallback.
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
// Normally, you want to save a new location to a database. We are simplifying
// things a bit and just saving it as a local variable, as we only need it again
// if a Notification is created (when the user navigates away from app).
currentLocation = locationResult.lastLocation
// Notify our Activity that a new location was added. Again, if this was a
// production app, the Activity would be listening for changes to a database
// with new locations, but we are simplifying things a bit to focus on just
// learning the location side of things.
val intent = Intent(ACTION_FOREGROUND_ONLY_LOCATION_BROADCAST)
intent.putExtra(EXTRA_LOCATION, currentLocation)
LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent)
// Updates notification content if this service is running as a foreground
// service.
if (serviceRunningInForeground) {
notificationManager.notify(
NOTIFICATION_ID,
generateNotification(currentLocation))
}
}
}
Le LocationCallback que vous créez ici est le rappel que le FusedLocationProviderClient appellera lorsqu'une nouvelle mise à jour de la position sera disponible.
Dans votre rappel, vous obtenez d'abord la dernière position à l'aide d'un objet LocationResult. Ensuite, vous informez votre Activity de la nouvelle position à l'aide d'une diffusion locale (si elle est active) ou vous mettez à jour le Notification si ce service s'exécute en tant que Service de premier plan.
- Lisez les commentaires pour comprendre ce que fait chaque partie.
S'abonner aux modifications de localisation
Maintenant que vous avez tout initialisé, vous devez indiquer à FusedLocationProviderClient que vous souhaitez recevoir des mises à jour.
- Dans le module
base, recherchezStep 1.5, Subscribe to location changesdans le fichierForegroundOnlyLocationService.kt. - Ajoutez le code suivant après le commentaire.
// TODO: Step 1.5, Subscribe to location changes.
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
L'appel requestLocationUpdates() indique à FusedLocationProviderClient que vous souhaitez recevoir des mises à jour de localisation.
Vous reconnaîtrez probablement les valeurs LocationRequest et LocationCallback que vous avez définies précédemment. Ils permettent à FusedLocationProviderClient de connaître les paramètres de qualité de service de votre requête et ce qu'il doit appeler lorsqu'il y a une mise à jour. Enfin, l'objet Looper spécifie le thread pour le rappel.
Vous remarquerez peut-être également que ce code se trouve dans une instruction try/catch. Cette méthode nécessite un tel bloc, car un SecurityException se produit lorsque votre application n'est pas autorisée à accéder aux informations de localisation.
Se désabonner des notifications de modification de l'emplacement
Lorsque l'application n'a plus besoin d'accéder aux informations de localisation, il est important de se désabonner des mises à jour de localisation.
- Dans le module
base, recherchezTODO: Step 1.6, Unsubscribe to location changesdans le fichierForegroundOnlyLocationService.kt. - Ajoutez le code suivant après le commentaire.
// TODO: Step 1.6, Unsubscribe to location changes.
val removeTask = fusedLocationProviderClient.removeLocationUpdates(locationCallback)
removeTask.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d(TAG, "Location Callback removed.")
stopSelf()
} else {
Log.d(TAG, "Failed to remove Location Callback.")
}
}
La méthode removeLocationUpdates() configure une tâche pour indiquer au FusedLocationProviderClient que vous ne souhaitez plus recevoir de mises à jour de la position de votre LocationCallback. addOnCompleteListener() fournit le rappel pour l'achèvement et exécute Task.
Comme pour l'étape précédente, vous avez peut-être remarqué que ce code se trouve dans une instruction try/catch. Cette méthode nécessite un tel bloc, car une SecurityException se produit lorsque votre application n'est pas autorisée à accéder aux informations de localisation.
Vous vous demandez peut-être quand les méthodes contenant le code d'abonnement/désabonnement sont appelées. Ils sont déclenchés dans la classe principale lorsque l'utilisateur appuie sur le bouton. Si vous souhaitez la consulter, regardez la classe MainActivity.kt.
Exécuter l'application
Exécutez votre application depuis Android Studio et essayez le bouton de localisation.
Des informations sur la position devraient s'afficher sur l'écran de sortie. Il s'agit d'une application entièrement fonctionnelle pour Android 9.


5. Compatibilité avec Android 10
Dans cette section, vous allez ajouter la compatibilité avec Android 10.
Votre application s'abonne déjà aux changements de localisation. Il n'y a donc pas grand-chose à faire.
En fait, il vous suffit de préciser que votre service de premier plan est utilisé à des fins de localisation.
SDK cible 29
- Dans le module
base, recherchezTODO: Step 2.1, Target Android 10 and then Android 11.dans le fichierbuild.gradle. - Apportez les modifications suivantes :
- Définissez
targetSdkVersionsur29.
Votre code doit se présenter comme suit :
android {
// TODO: Step 2.1, Target Android 10 and then Android 11.
compileSdkVersion 29
defaultConfig {
applicationId "com.example.android.whileinuselocation"
minSdkVersion 26
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
...
}
Vous serez ensuite invité à synchroniser votre projet. Cliquez sur Synch Now (Synchroniser).

Votre application sera alors presque prête pour Android 10.
Ajouter un type de service de premier plan
Dans Android 10, vous devez inclure le type de votre service de premier plan si vous avez besoin d'accéder à la position en cours d'utilisation. Dans votre cas, il est utilisé pour obtenir des informations de localisation.
Dans le module base, recherchez TODO: 2.2, Add foreground service type dans AndroidManifest.xml et ajoutez le code suivant à l'élément <service> :
android:foregroundServiceType="location"
Votre code doit se présenter comme suit :
<application>
...
<!-- Foreground services in Android 10+ require type. -->
<!-- TODO: 2.2, Add foreground service type. -->
<service
android:name="com.example.android.whileinuselocation.ForegroundOnlyLocationService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="location" />
</application>
Et voilà ! Votre application est compatible avec la localisation "en cours d'utilisation" d'Android 10 en suivant les bonnes pratiques de localisation dans Android.
Exécuter l'application
Exécutez votre application depuis Android Studio et essayez le bouton de localisation.
Tout devrait fonctionner comme avant, mais désormais sur Android 10. Si vous n'avez pas accepté les autorisations d'accès à la position auparavant, l'écran d'autorisation devrait maintenant s'afficher.



6. Compatibilité avec Android 11
Dans cette section, vous ciblez Android 11.
Bonne nouvelle : vous n'avez pas besoin de modifier d'autres fichiers que le fichier build.gradle.
SDK cible 11
- Dans le module
base, recherchezTODO: Step 2.1, Target SDKdans le fichierbuild.gradle. - Apportez les modifications suivantes :
- De
compileSdkVersionà30 - De
targetSdkVersionà30
Votre code doit se présenter comme suit :
android {
TODO: Step 2.1, Target Android 10 and then Android 11.
compileSdkVersion 30
defaultConfig {
applicationId "com.example.android.whileinuselocation"
minSdkVersion 26
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
...
}
Vous serez ensuite invité à synchroniser votre projet. Cliquez sur Synch Now (Synchroniser).

Votre application est alors prête pour Android 11.
Exécuter l'application
Exécutez votre application depuis Android Studio et essayez de cliquer sur le bouton.
Tout devrait fonctionner comme avant, mais désormais sur Android 11. Si vous n'avez pas accepté les autorisations d'accès à la position auparavant, l'écran d'autorisation devrait maintenant s'afficher.


7. Stratégies de localisation pour Android
En vérifiant et en demandant les autorisations d'accès à la position de la manière indiquée dans cet atelier de programmation, votre application peut suivre son niveau d'accès à la position de l'appareil.
Cette page présente quelques bonnes pratiques clés concernant les autorisations d'accéder à la position. Pour savoir comment protéger les données de vos utilisateurs, consultez Bonnes pratiques concernant les autorisations des applications.
Ne demandez que les autorisations dont vous avez besoin.
Ne demandez des autorisations que lorsque cela est nécessaire. Exemple :
- Ne demandez pas d'autorisation d'accéder à la position au démarrage de l'application, sauf si cela est absolument nécessaire.
- Si votre application cible Android 10 ou version ultérieure et que vous disposez d'un service de premier plan, déclarez un
foregroundServiceTypede"location"dans le fichier manifeste. - Ne demandez pas d'autorisations d'accès à la localisation en arrière-plan, sauf si vous avez un cas d'utilisation valide, comme décrit dans Accès plus sûr et plus transparent à la position de l'utilisateur.
Prendre en charge la dégradation progressive si l'autorisation n'est pas accordée
Pour offrir une bonne expérience utilisateur, concevez votre application de manière à ce qu'elle puisse gérer correctement les situations suivantes :
- Votre application n'a pas accès aux informations de localisation.
- Votre application n'a pas accès aux informations de localisation lorsqu'elle s'exécute en arrière-plan.
8. Félicitations
Vous avez appris à recevoir des notifications de position dans Android, en gardant à l'esprit les bonnes pratiques.
En savoir plus
- Exemple complet d'utilisation de la localisation en arrière-plan si vous avez un cas d'utilisation valide
- Demander des notifications de position