Optimiser les services de localisation pour une meilleure autonomie

Les limites de localisation en arrière-plan introduites dans Android 8.0 (niveau d'API 26) ont mis à nouveau l'accent sur la façon dont l'utilisation des services de localisation affecte la décharge de la batterie. Cette page traite des bonnes pratiques concernant les services de localisation, ainsi que des mesures que vous pouvez prendre dès maintenant pour rendre vos applications plus économes en énergie. Ces bonnes pratiques sont bénéfiques pour votre application, quelle que soit la version de la plate-forme sur laquelle elle s'exécute.

Les limites relatives à la localisation en arrière-plan dans Android 8.0 ont introduit les modifications suivantes :

  • La collecte des données de localisation en arrière-plan est limitée, et la position est calculée et diffusée seulement quelques fois par heure.
  • Les recherches Wi-Fi sont plus efficientes et les mises à jour de la position ne sont pas calculées lorsque l'appareil reste connecté au même point d'accès statique.
  • La réactivité du géorepérage passe de quelques dizaines de secondes à environ deux minutes. Ce changement améliore sensiblement les performances de la batterie, qui sont jusqu'à 10 fois meilleures sur certains appareils.

Cette page part du principe que vous utilisez les API des services de localisation Google, qui offrent une plus grande précision et réduisent l'impact sur la batterie par rapport aux API de localisation du framework. Sur cette page, nous partons du principe que vous connaissez l'API Fused Location Provider, qui combine les signaux des réseaux GPS, Wi-Fi et mobiles, ainsi que l'accéléromètre, le gyroscope, le magnétomètre et d'autres capteurs. Vous devriez également connaître l'API de géorepérage, reposant sur l'API Fused Location Provider et optimisée pour les performances de la batterie.

Comprendre la décharge de la batterie

La décharge de la batterie est directement liée à la collecte des données de localisation en fonction des aspects suivants :

  • Précision : la précision des données de localisation. En règle générale, plus la précision est élevée, plus la décharge de la batterie est importante.
  • Fréquence : la fréquence à laquelle la position est calculée. Plus la position est calculée fréquemment, plus la batterie est sollicitée.
  • Latence : la rapidité de livraison des données de localisation. Une latence inférieure nécessite généralement plus de batterie.

Précision

Vous pouvez spécifier la précision de la localisation à l'aide de la méthode setPriority(), en transmettant l'une des valeurs suivantes en tant qu'argument :

  • PRIORITY_HIGH_ACCURACY fournit la localisation la plus précise possible. Cette localisation est calculée en utilisant autant d'entrées que nécessaire (la méthode utilise le GPS, le Wi-Fi et les données mobiles, et utilise un éventail de capteurs). Elle peut entraîner une décharge importante de la batterie.
  • PRIORITY_BALANCED_POWER_ACCURACY fournit une localisation précise tout en optimisant l'énergie consommée. La méthode utilise très rarement le GPS. Elle utilise généralement une combinaison des données Wi-Fi et des données mobiles pour calculer la position de l'appareil.
  • PRIORITY_LOW_POWER s'appuie principalement sur les antennes-relais et évite les entrées GPS et Wi-Fi, offrant une précision approximative (au niveau de la ville) avec une décharge minimale de la batterie.
  • PRIORITY_NO_POWER reçoit de manière passive les positions provenant d'autres applications pour lesquelles la position a déjà été calculée.

Les besoins de localisation de la plupart des applications peuvent être satisfaits à l'aide de l'option PRIORITY_BALANCED_POWER_ACCURACY ou PRIORITY_LOW_POWER. L'option PRIORITY_HIGH_ACCURACY doit être réservée aux applications qui s'exécutent au premier plan et qui nécessitent des mises à jour de la position en temps réel (par exemple, une application de cartographie).

Fréquence

Vous pouvez spécifier la fréquence de localisation à l'aide de deux méthodes :

  • Utilisez la méthode setinterval() pour spécifier l'intervalle selon lequel la position est calculée pour votre application.
  • Utilisez le paramètre setFastestInterval() pour spécifier l'intervalle selon lequel la position calculée pour d'autres applications est diffusée vers votre application.

Vous devez transmettre la plus grande valeur possible lorsque vous utilisez setInterval(). Cela est particulièrement vrai pour la collecte des données de localisation en arrière-plan, qui est souvent une source indésirable de décharge de la batterie. La définition d'intervalles de quelques secondes doit être réservée aux cas d'utilisation au premier plan. Les limites de localisation en arrière-plan introduites dans Android 8.0 appliquent ces stratégies, mais votre application doit s'efforcer de les appliquer sur les appareils Android 7.0 ou version antérieure.

Latence

Vous pouvez spécifier une latence à l'aide de la méthode setMaxWaitTime(), qui transmet généralement une valeur plusieurs fois supérieure à l'intervalle spécifié dans la méthode setInterval(). Ce paramètre retarde la livraison de la position, et plusieurs notifications de position peuvent être livrées par lots. Ces deux modifications permettent de réduire l'utilisation de la batterie.

Si votre application n'a pas besoin immédiatement d'une mise à jour de la position, vous devez transmettre la valeur la plus élevée possible à la méthode setMaxWaitTime(), en acceptant plus de latence au profit d'une plus grande quantité de données et d'une meilleure efficacité de la batterie.

Lorsque vous utilisez des zones de géorepérage, les applications doivent transmettre une valeur élevée à la méthode setNotificationResponsiveness() pour préserver la batterie. Nous vous recommandons une durée de cinq minutes ou plus.

Cas d'utilisation des données de localisation

Cette section décrit quelques scénarios typiques de collecte de données de localisation, ainsi que des recommandations pour une utilisation optimale de l'API de géorepérage et de l'API Fused Location Provider.

Mises à jour au premier plan ou visibles par l'utilisateur

Exemple : une application de cartographie qui nécessite des mises à jour fréquentes et précises avec une latence très faible. Toutes les mises à jour sont effectuées au premier plan : l'utilisateur démarre une activité, consomme des données de localisation, puis arrête l'activité après un court laps de temps.

Utilisez la méthode setPriority() avec la valeur PRIORITY_HIGH_ACCURACY ou PRIORITY_BALANCED_POWER_ACCURACY.

L'intervalle spécifié dans la méthode setInterval() dépend du cas d'utilisation : pour les scénarios en temps réel, définissez la valeur sur quelques secondes. Sinon, limitez-vous à quelques minutes (nous vous recommandons de choisir au moins deux minutes pour réduire l'utilisation de la batterie).

Connaître la position de l'appareil

Exemple : une application météo a besoin de connaître la position de l'appareil.

Utilisez la méthode getLastLocation(), qui renvoie la position la plus récente disponible (qui peut être nulle dans de rares cas). Cette méthode permet d'obtenir facilement un emplacement et qui, contrairement au fait de demander de manière active des mises à jour de la position, n'entraîne pas de frais associés. Utilisez-la avec la méthode isLocationAvailable(), qui renvoie true lorsque la position renvoyée par getLastLocation() est raisonnablement à jour.

Lancer des mises à jour lorsqu'un utilisateur se trouve à un emplacement spécifique

Exemple : demander des mises à jour lorsqu'un utilisateur se trouve à une certaine distance de son lieu de travail, de son domicile ou d'un autre lieu.

Utilisez le géorepérage conjointement avec les mises à jour Fused Location Provider. Demandez des mises à jour lorsque l'application reçoit un déclencheur d'entrée dans une zone de géorepérage, et supprimez les mises à jour lorsque l'application reçoit un déclencheur de sortie d'une zone de géorepérage. Cela garantit que l'application ne reçoit des mises à jour de position plus précises que lorsque l'utilisateur est entré dans une zone définie.

Pour ce scénario, le workflow typique peut consister à afficher une notification lors de la transition d'entrée dans la zone de géorepérage, et à lancer une activité contenant du code permettant de demander des mises à jour lorsque l'utilisateur appuie sur la notification.

Lancer des mises à jour en fonction de l'état de l'activité de l'utilisateur

Exemple : demander des mises à jour uniquement lorsque l'utilisateur est à vélo ou en voiture.

Utilisez l'API Activity Recognition conjointement avec les mises à jour Fused Location Provider. Demandez des mises à jour lorsque l'activité ciblée est détectée, et supprimez les mises à jour lorsque l'utilisateur cesse d'effectuer cette activité.

Pour ce cas d'utilisation, le workflow typique peut consister à afficher une notification pour l'activité détectée et à lancer une activité contenant du code permettant de demander des mises à jour lorsque l'utilisateur appuie sur la notification.

Mises à jour de position en arrière-plan de longue durée associées à des zones géographiques

Exemple : l'utilisateur souhaite être averti lorsque l'appareil se trouve à proximité d'un revendeur.

Il s'agit d'un excellent cas d'utilisation pour le géorepérage. Comme le cas d'utilisation implique presque certainement la localisation en arrière-plan, utilisez la méthode addGeofences(GeofencingRequest, PendingIntent).

Vous devez définir les options de configuration suivantes :

  • Si vous suivez les transitions pendant lesquelles l'utilisateur reste dans la zone de géorepérage, utilisez la méthode setLoiteringDelay() en transmettant une valeur d'environ cinq minutes ou moins.

  • Utilisez la méthode setNotificationResponsiveness() en transmettant une valeur d'environ cinq minutes. Toutefois, envisagez d'utiliser une valeur d'environ 10 minutes si votre application peut gérer le délai supplémentaire de réactivité.

Une application ne peut enregistrer simultanément qu'un maximum de 100 zones de géorepérage. Dans le cas où une application souhaite effectuer le suivi d'un grand nombre de revendeurs, il peut être utile que l'application enregistre une grande zone de géorepérage (au niveau de la ville), puis qu'elle enregistre de manière dynamique des zones de géorepérage plus petites (pour les lieux situés dans la ville) pour les magasins dans la zone de géorepérage plus étendue. Lorsque l'utilisateur entre dans une grande zone de géorepérage, des zones de géorepérage plus petites peuvent être ajoutées. Lorsque l'utilisateur quitte la zone de géorepérage de plus grande taille, les petites zones de géorepérage peuvent être supprimées, et des zones de géorepérage peuvent être enregistrées pour une nouvelle zone.

Mises à jour de position en arrière-plan de longue durée sans composant d'application visible

Exemple : une application qui suit la position de l'utilisateur de manière passive

Si possible, utilisez la méthode setPriority() avec l'option PRIORITY_NO_POWER, car elle ne consomme presque pas de batterie. Si l'utilisation de PRIORITY_NO_POWER n'est pas possible, utilisez PRIORITY_BALANCED_POWER_ACCURACY ou PRIORITY_LOW_POWER, mais évitez d'utiliserPRIORITY_HIGH_ACCURACY pour les tâches prolongées en arrière-plan, car cette option décharge considérablement la batterie.

Si vous avez besoin de plus de données de localisation, utilisez un emplacement passif en appelant la méthode setFastestInterval() et en transmettant une valeur inférieure à celle que vous transmettez à setInterval(). Lorsqu'elle est combinée à l'option PRIORITY_NO_POWER, la localisation passive peut fournir l'emplacement calculé par d'autres applications avec opportunisme, sans frais supplémentaires.

Modérez la fréquence en ajoutant une latence à l'aide de la méthode setMaxWaitTime(). Par exemple, si vous utilisez la méthode setinterval() avec une valeur d'environ 10 minutes, vous devez appeler setMaxWaitTime() avec une valeur comprise entre 30 et 60 minutes. Avec ces options, la localisation est calculée pour votre application toutes les 10 minutes environ. Toutefois, celle-ci n'est activée que toutes les 30 à 60 minutes avec des données de localisation disponibles sous forme de mise à jour par lot. Cette approche accepte plus de latence au profit d'une plus grande quantité de données disponible et de meilleures performances de la batterie.

Mises à jour fréquentes et très précises lorsque l'utilisateur interagit avec d'autres applications

Exemple : une application de navigation ou de fitness continue de fonctionner lorsque l'utilisateur éteint l'écran ou ouvre une autre application.

Utilisez un service de premier plan. Si votre application est susceptible d'effectuer un travail coûteux pour le compte de l'utilisateur, nous vous recommandons d'en informer l'utilisateur. Un service de premier plan nécessite une notification persistante. Pour en savoir plus, consultez la page Présentation des notifications.

Bonnes pratiques concernant la localisation

La mise en œuvre des bonnes pratiques décrites dans cette section permet de réduire l'utilisation de la batterie par votre application.

Supprimer les mises à jour de la position

Une cause fréquente de décharge inutile de la batterie est l'impossibilité de supprimer les mises à jour de la position géographique lorsqu'elles ne sont plus nécessaires. Cela peut se produire, par exemple, lorsque les méthodes onStart() ou onResume() d'une activité contiennent un appel de requestlocationUpdates() sans appel correspondant de removeLocationUpdates() dans les méthodes de cycle de vie onPause() ou onStop().

Vous pouvez utiliser des composants compatibles avec le cycle de vie pour mieux gérer le cycle de vie des activités dans votre application. Pour en savoir plus, consultez la page Gérer les cycles de vie avec des composants compatibles avec le cycle de vie.

Définir des délais avant expiration

Pour éviter la décharge de la batterie, définissez un délai raisonnable pour l'arrêt des mises à jour de la position. Le délai d'expiration garantit que les mises à jour ne se poursuivent pas indéfiniment et protège l'application dans les cas où des mises à jour sont demandées, mais pas supprimées (par exemple, en raison d'un bug dans le code).

Pour une requête Fused Location Provider, ajoutez un délai avant expiration en appelant setExpirationDuration(), qui reçoit un paramètre qui représente le temps écoulé, en millisecondes, depuis le dernier appel de la méthode. Vous pouvez également ajouter un délai avant expiration en appelant setExpirationTime(), qui reçoit un paramètre qui représente le délai d'expiration en millisecondes depuis le dernier démarrage du système.

Pour ajouter un délai avant expiration à une requête de zone de géorepérage, appelez la méthode setExpirationDuration().

Requêtes par lot

Pour tous les cas d'utilisation hors premier plan, regroupez les requêtes par lot. Vous pouvez utiliser la méthode setInterval() pour spécifier l'intervalle auquel vous souhaitez calculer la position. Ensuite, utilisez la méthode setMaxWaitTime() pour définir l'intervalle auquel l'emplacement est diffusé à votre application. La valeur transmise à la méthode setMaxWaitTime() doit être un multiple de la valeur transmise à la méthode setInterval(). Prenons l'exemple de la requête de position suivante :

Kotlin

val request = LocationRequest()
request.setInterval(10 * 60 * 1000)
request.setMaxWaitTime(60 * 60 * 1000)

Java

LocationRequest request = new LocationRequest();
request.setInterval(10 * 60 * 1000);
request.setMaxWaitTime(60 * 60 * 1000);

Dans ce cas, la position est calculée environ toutes les 10 minutes, et environ 6 points de données de localisation sont distribués par lot environ toutes les heures. Bien que vous receviez toujours les mises à jour de position toutes les 10 minutes environ, vous préservez la batterie, car votre appareil n'est activé que toutes les heures environ.

Utiliser des mises à jour de position passives

Dans les cas d'utilisation en arrière-plan, il est recommandé de limiter les mises à jour de la position. Les limites d'Android 8.0 appliquent cette pratique, mais les applications exécutées sur des appareils plus anciens doivent limiter autant que possible la localisation en arrière-plan.

Il est probable que pendant que votre application est exécutée en arrière-plan, une autre application demande fréquemment des mises à jour de position au premier plan. Les services de localisation mettent ces mises à jour à disposition de votre application. Prenons la requête de localisation suivante, qui utilise les données de localisation avec opportunisme :

Kotlin

val request = LocationRequest()
request.setInterval(15 * 60 * 1000)
request.setFastestInterval(2 * 60 * 1000)

Java

LocationRequest request = new LocationRequest();
request.setInterval(15 * 60 * 1000);
request.setFastestInterval(2 * 60 * 1000);

Dans l'exemple précédent, la position est calculée pour votre application toutes les 15 minutes environ. Si d'autres applications demandent la localisation, les données sont mises à la disposition de votre application dans un intervalle maximum de deux minutes.

Bien que l'utilisation passive de l'emplacement n'entraîne pas de décharge de la batterie, soyez particulièrement vigilant lorsque la réception de données de localisation déclenche des opérations coûteuses d'E/S ou de processeur. Pour minimiser l'impact sur la batterie, l'intervalle spécifié dans setFastestInterval() ne doit pas être trop petit.

Vous pouvez améliorer considérablement les performances de la batterie des appareils de vos utilisateurs en suivant les recommandations de cette page. Les utilisateurs sont moins susceptibles de supprimer les applications qui ne déchargent pas leur batterie.