1. Avant de commencer
Android 10 et 11 offrent aux utilisateurs plus de contrôle sur leurs applications l'accès à la position de leur appareil.
Lorsqu'une application exécutée sous Android 11 demande l'accès à la position, les utilisateurs disposent de quatre options:
- Toujours autoriser
- Autoriser seulement si l'appli est en cours d'utilisation (sous Android 10)
- Une seule fois (sous Android 11)
- Refuser
Android 10
Android 11
Dans cet atelier de programmation, vous allez apprendre à recevoir des notifications de position et à activer la localisation sur n'importe quelle version d'Android, en particulier Android 10 et 11. À la fin de l'atelier de programmation, vous disposerez d'une application qui respectera les bonnes pratiques actuelles pour récupérer les mises à jour de la position.
Prérequis
- Connaissances du développement Android
- Une certaine 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 son utilisation).
- Modifier une application existante pour qu'elle prenne en charge la demande d'accès à la position en ajoutant du code pour s'abonner à la position ou se désabonner
- Ajoutez la prise en charge de l'application à Android 10 et 11 en ajoutant une logique pour accéder aux données de localisation au premier plan ou lorsqu'elles sont en cours d'utilisation.
Prérequis
- Android Studio 3.4 ou version ultérieure pour exécuter le code
- Un appareil/é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 lancer le plus rapidement possible, vous pouvez vous appuyer sur ce projet de démarrage. Si Git est installé, il vous suffit d'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 récupérer le projet sous forme de fichier ZIP:
Importer le projet
Ouvrez Android Studio, puis sélectionnez Open an existing Android Studio project (Ouvrir un projet Android Studio existant). à partir de 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.)
Dans l'angle supérieur gauche de la fenêtre du projet, un message semblable à l'image ci-dessous devrait s'afficher si vous êtes dans la vue Android. Si vous êtes dans la vue Project (Projet), vous devez développer le projet pour afficher la même chose.
Il y a deux dossiers (base
et complete
). Chacun d'eux est appelé "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 fini 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 vous recevez une invite du type Actualiser pour que les modifications de langue soient prises en compte ou similaire, sélectionnez Oui.
Comprendre le projet de démarrage
La configuration et la demande de localisation sont maintenant effectuées 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
devrait correspondre au contenu du module complete
. Le module complete
peut être utilisé pour vérifier votre travail ou pour vous y référer en cas de problème.
Les composants clés sont les suivants:
MainActivity
: UI permettant à l'utilisateur d'autoriser l'application à accéder à la position de l'appareilLocationService
: service qui s'abonne ou se désabonne aux changements de position, et s'affiche en tant que service de premier plan (avec une notification) si l'utilisateur quitte l'activité de l'application. Vous ajoutez ici le code de la zone géographique.Util
: ajoute des fonctions d'extension pour la classeLocation
et enregistre l'emplacement dansSharedPreferences
(couche de données simplifiée).
Configuration de l'émulateur
Pour en savoir plus sur la configuration d'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
base
dans le menu déroulant, puis cliquez sur Exécuter:
- Notez que l'application suivante s'affiche sur votre appareil:
Vous remarquerez peut-être qu'aucune information de localisation ne s'affiche sur l'écran de sortie. En effet, vous n'avez pas encore ajouté le code de la zone géographique.
3. Ajout du lieu...
Concepts
L'objectif de cet atelier de programmation est de vous montrer comment recevoir des notifications de position et, à terme, 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 proposées au début de l'atelier de programmation. Voici leur signification:
- Autoriser seulement si l'appli est en cours d'utilisation
- Cette option est recommandée pour la plupart des applications. Également appelé "pendant l'utilisation" ou "premier plan uniquement" , cette option a été ajoutée sur Android 10 et permet aux développeurs de récupérer la position uniquement lorsque l'application est en cours d'utilisation. 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.
- Ponctuel uniquement
- Ajoutée dans Android 11, cette option est la même que l'option Autoriser seulement si l'appli est utilisée, mais pour une durée limitée. Pour en savoir plus, consultez la section Autorisations ponctuelles.
- Refuser
- Cette option empêche l'accès aux informations de localisation.
- Toujours autoriser
- Cette option permet d'accéder à votre position en permanence, mais requiert une autorisation supplémentaire pour Android 10 ou version ultérieure. Vous devez également vous assurer que votre cas d'utilisation est valide et que vous respectez les règles relatives à la localisation. Cette option n'est pas abordée dans cet atelier de programmation, car il s'agit d'un cas d'utilisation plus rare. Toutefois, si vous disposez d'un cas d'utilisation valide et souhaitez savoir comment gérer correctement la localisation en permanence, y compris l'accès aux données de localisation en arrière-plan, consultez l'exemple LocationUpdatesBackgroundKotlin.
Services, services de premier plan et liaison
Pour assurer la compatibilité totale des mises à jour de position avec l'option Autoriser seulement si l'appli est utilisée, 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 notifications de position lorsque votre application est visible et que l'utilisateur la quitte, vous devez associer/dissocier ce Service
à l'élément d'interface utilisateur.
Comme cet atelier de programmation porte uniquement sur les notifications de position, vous trouverez tout le code dont vous avez besoin dans la classe ForegroundOnlyLocationService.kt
. Vous pouvez parcourir cette classe et la MainActivity.kt
pour voir comment elles fonctionnent ensemble.
Pour en savoir plus, consultez Présentation des services et Présentation des services liés.
Autorisations
Pour recevoir des notifications de 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
dans votre fichier manifeste Android, respectivement. Sans ces autorisations, votre application ne pourra pas demander l'accès à la position au moment de l'exécution.
Ces autorisations couvrent les cas Ponctuel uniquement et Autoriser seulement si l'appli est en cours d'utilisation lorsque votre application est utilisée sur un appareil équipé d'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
.
Examinez les classes principales:
FusedLocationProviderClient
- Il s'agit de l'élément central du framework de localisation. Une fois créée, elle vous permet de demander des notifications de position et d'obtenir la dernière position connue.
LocationRequest
- Il s'agit d'un objet de données qui contient des paramètres de qualité de service pour les requêtes (intervalles de mise à jour, priorités et précision). Il est transmis à
FusedLocationProviderClient
lorsque vous demandez des mises à jour de la position. LocationCallback
- Permet de recevoir des notifications lorsque la position de l'appareil a changé ou ne peut plus être déterminée. Elle transmet un
LocationResult
, où 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, commencez à utiliser le code.
4. Ajouter des fonctionnalités de localisation
Cet atelier de programmation porte sur l'option de localisation la plus courante: Autoriser seulement si l'appli est utilisée.
Pour recevoir des notifications de position, votre application doit avoir une activité visible ou un service en cours d'exécution au premier plan (avec une notification).
Autorisations
Le but de cet atelier de programmation est de vous montrer comment recevoir des notifications de position, et non comment demander l'autorisation d'accéder à la position. Le code basé sur les autorisations est donc déjà écrit pour vous. N'hésitez pas à les ignorer si vous les avez déjà comprises.
Voici les principales autorisations (aucune action n'est requise pour cette partie):
- Déclarez l'autorisation que vous utilisez dans
AndroidManifest.xml
. - Avant d'essayer d'accéder aux informations de localisation, vérifiez si l'utilisateur a autorisé votre application à le faire. Si votre application n'a pas encore reçu l'autorisation, demandez l'accès.
- Gérez le choix des autorisations de l'utilisateur. (Vous pouvez consulter ce code dans
MainActivity.kt
.)
Si vous recherchez TODO: Step 1.0, Review Permissions
dans AndroidManifest.xml
ou MainActivity.kt
, vous voyez tout le code écrit pour les autorisations.
Pour en savoir plus, consultez Présentation des autorisations.
Maintenant, commencez à écrire un code de localisation.
Examiner les variables clés nécessaires aux mises à jour de la position
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, afin de comprendre les classes clés et les variables que vous utilisez pour recevoir des notifications de position.
// 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 recevoir des notifications de 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. Plus tard, vous ajouterez du code ici pour demander des notifications de position.
Initialiser la LocationRequest
- Dans le module
base
, recherchezTODO: Step 1.3, Create a LocationRequest
dans 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 leur fonctionnement.
Initialiser le LocationCallback
- Dans le module
base
, recherchezTODO: Step 1.4, Initialize the LocationCallback
dans 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 FusedLocationProviderClient
appellera lorsqu'une nouvelle mise à jour de la position est disponible.
Dans votre rappel, vous obtenez d'abord la dernière position à l'aide d'un objet LocationResult
. Ensuite, informez votre Activity
du nouvel emplacement à l'aide d'une annonce locale (s'il est actif) ou mettez à jour Notification
si ce service est exécuté en tant que Service
de premier plan.
- Lisez les commentaires pour comprendre à quoi sert chaque partie.
S'abonner aux changements de lieu
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 changes
dans 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 notifications de position.
Vous reconnaissez probablement les éléments LocationRequest
et LocationCallback
que vous avez définis 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 en cas de mise à jour. Enfin, l'objet Looper
spécifie le thread du rappel.
Vous remarquerez également que ce code se trouve dans une instruction try/catch
. Cette méthode nécessite un tel blocage, car une erreur SecurityException
se produit lorsque votre application n'est pas autorisée à accéder aux informations de localisation.
Se désabonner des modifications de lieu
Lorsque l'application n'a plus besoin d'accéder aux informations de localisation, il est important de se désabonner des notifications de position.
- Dans le module
base
, recherchezTODO: Step 1.6, Unsubscribe to location changes
dans 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 à FusedLocationProviderClient
que vous ne souhaitez plus recevoir de notifications de position pour votre LocationCallback
. addOnCompleteListener()
donne 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 blocage, car une erreur 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 qui contiennent le code d'abonnement/de désabonnement sont appelées. Ils sont déclenchés dans la classe principale lorsque l'utilisateur appuie sur le bouton. Si vous souhaitez l'afficher, examinez la classe MainActivity.kt
.
Exécuter l'application
Exécutez votre application à partir d'Android Studio et cliquez sur le bouton de localisation.
Les informations d'emplacement doivent 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 prendre en charge Android 10.
Votre application est déjà abonnée aux changements de lieu. Vous n'avez donc pas beaucoup de travail à faire.
Il vous suffit d'indiquer que votre service de premier plan doit être 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
targetSdkVersion
sur29
.
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).
Ensuite, votre application est 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 à votre position pendant l'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 appli est compatible avec la localisation Android 10 pendant l'utilisation en suivant les bonnes pratiques de localisation dans Android.
Exécuter l'application
Exécutez votre application à partir d'Android Studio et cliquez sur le bouton de localisation.
Tout devrait fonctionner comme avant, mais désormais sous Android 10. Si vous n'avez pas encore accepté les autorisations pour les établissements, l'écran d'autorisation devrait maintenant s'afficher.
6. Compatibilité avec Android 11
Dans cette section, vous allez cibler Android 11.
Bonne nouvelle ! Vous n'avez pas besoin de modifier les fichiers, sauf le fichier build.gradle
.
SDK cible 11
- Dans le module
base
, recherchezTODO: Step 2.1, Target SDK
dans 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).
Ensuite, votre application est prête pour Android 11.
Exécuter l'application
Exécutez votre application à partir d'Android Studio et essayez de cliquer sur le bouton.
Tout devrait fonctionner comme avant, mais désormais sous Android 11. Si vous n'avez pas encore accepté les autorisations pour les établissements, 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éder à la position comme indiqué dans cet atelier de programmation, votre application peut suivre son niveau d'accès à la position de l'appareil.
Cette page liste quelques bonnes pratiques clés concernant les autorisations d'accéder à la position. Pour savoir comment protéger les données des utilisateurs sécurité des données, consultez les bonnes pratiques pour les autorisations des applications.
Vous ne devez demander que les autorisations dont vous avez besoin
Ne demandez des autorisations que si nécessaire. Exemple :
- Ne demandez pas l'autorisation d'accéder à la position au démarrage de l'application, sauf en cas d'absolue nécessité.
- Si votre application cible Android 10 ou une version ultérieure et que vous disposez d'un service de premier plan, déclarez un
foregroundServiceType
de"location"
dans le fichier manifeste. - Ne demandez pas l'autorisation d'accéder à la position en arrière-plan, sauf si vous disposez d'un cas d'utilisation valide, comme décrit dans l'article Accès plus sûr et plus transparent à la position de l'utilisateur.
Permettre la dégradation progressive si l'autorisation n'est pas accordée
Pour garantir une expérience utilisateur de qualité, concevez votre application de sorte 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 votre cas d'utilisation est valide
- Demander des notifications de position