Android: LocationManager vs services Google Play


151

Je souhaite créer une application centrée sur l'obtention de l'emplacement actuel de l'utilisateur, puis trouver des points d'intérêt (tels que des bars, des restaurants, etc.) qui sont proches de lui via l' API Google Places .

En cherchant sur le Web un endroit où commencer, je suis tombé sur des didacticiels qui utilisent la LocationManagerclasse et d'autres qui utilisent les services Google Play afin de trouver l'emplacement des utilisateurs.

À première vue, les deux font la même chose, mais comme je suis nouveau dans ce domaine, je suis un peu confus et je ne sais pas quelle méthode convient le mieux à mes besoins. Alors, je veux vous demander:

Quelles sont les différences entre ces deux méthodes de recherche d'emplacements (s'il y en a)?


Réponses:


320

Localisation de l'utilisateur sur Android

Obtenir la position de l'utilisateur sur Android est un peu moins simple que sur iOS. Pour commencer la confusion, il existe deux façons totalement différentes de le faire. Le premier utilise les API Android de android.location.LocationListener, et le second utilise les API des services Google Play com.google.android.gms.location.LocationListener. Passons en revue les deux.

  1. API de localisation d'Android

    Les API de localisation d'Android utilisent trois fournisseurs différents pour obtenir la localisation -

    • LocationManager.GPS_PROVIDER- Ce fournisseur détermine l'emplacement à l'aide de satellites. Selon les conditions, ce fournisseur peut prendre un certain temps pour renvoyer un correctif d'emplacement.
    • LocationManager.NETWORK_PROVIDER- Ce fournisseur détermine l'emplacement en fonction de la disponibilité de la tour cellulaire et des points d'accès WiFi. Les résultats sont récupérés au moyen d'une recherche réseau.
    • LocationManager.PASSIVE_PROVIDER- Ce fournisseur renverra les emplacements générés par d'autres fournisseurs. Vous recevez passivement des mises à jour de localisation lorsque d'autres applications ou services en font la demande sans en faire la demande.

L'essentiel est que vous obtenez un objet du LocationManagersystème, implémentez le LocationListeneret appelez le requestLocationUpdatessur le LocationManager.

Voici un extrait de code:

    LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
      // Called when a new location is found by the network location provider.
      makeUseOfNewLocation(location);
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}
  };

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

Guide API de Google sur les stratégies de localisationexplique assez bien le code. Mais ils mentionnent également que dans la plupart des cas, vous obtiendrez de meilleures performances de la batterie, ainsi qu'une précision plus appropriée, en utilisant plutôt l' API Google Location Services . Maintenant, la confusion commence!

  1. API des services de localisation de Google

L'API des services de localisation de Google fait partie de l'APK des services Google Play ( voici comment la configurer ). Ils sont construits sur l'API d'Android. Ces API fournissent un «fournisseur d'emplacement fusionné» au lieu des fournisseurs mentionnés ci-dessus. Ce fournisseur choisit automatiquement le fournisseur sous-jacent à utiliser, en fonction de la précision, de l'utilisation de la batterie, etc. Il est rapide car vous obtenez l'emplacement d'un service à l'échelle du système qui continue de le mettre à jour. Et vous pouvez utiliser des fonctionnalités plus avancées telles que le géorepérage.

Pour utiliser les services de localisation de Google, votre application doit se connecter au GooglePlayServicesClient. Pour vous connecter au client, votre activité (ou fragment, ou presque) doit être implémentée GooglePlayServicesClient.ConnectionCallbackset GooglePlayServicesClient.OnConnectionFailedListeners'interfacer. Voici un exemple de code:

    public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
    LocationClient locationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        locationClient = new LocationClient(this, this, this);
    }

    @Override
    public void onConnected(Bundle bundle) {
    Location location = locationClient.getLastLocation() ;
        Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDisconnected() {
    Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // code to handle failed connection
        // this code can be found here — http://developer.android.com/training/location/retrieve-current.html 
    }
  • Pourquoi est locationClient.getLastLocation()nul?

Le locationClient.getLastLocation()obtient le dernier emplacement connu du client. Cependant, le fournisseur d'emplacement fusionné ne conservera l'emplacement en arrière-plan que si au moins un client y est connecté. Une fois le premier client connecté, il essaiera immédiatement d'obtenir un emplacement. Si votre activité est le premier client de se connecter et que vous appelez getLastLocation()tout de suite dans onConnected(), qui pourrait ne pas être assez de temps pour le premier emplacement à venir. Cela se traduira par locationêtre null.

Pour résoudre ce problème, vous devez attendre (indéterminé) jusqu'à ce que le fournisseur obtienne l'emplacement, puis appeler getLastLocation(), ce qui est impossible à savoir. Une autre (meilleure) option consiste à implémenter l' com.google.android.gms.location.LocationListenerinterface pour recevoir des mises à jour de localisation périodiques (et à la désactiver une fois que vous avez obtenu la première mise à jour).

    public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
    // . . . . . . . . more stuff here 
    LocationRequest locationRequest;
    LocationClient locationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // . . . . other initialization code
        locationClient = new LocationClient(this, this, this);
    locationRequest = new LocationRequest();
    // Use high accuracy
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        // Set the update interval to 5 seconds
    locationRequest.setInterval(UPDATE_INTERVAL);
        // Set the fastest update interval to 1 second
    locationRequest.setFastestInterval(FASTEST_INTERVAL);
    }
    // . . . . . . . . other methods 
    @Override
    public void onConnected(Bundle bundle) {
        Location location = locationClient.getLastLocation();
        if (location == null)
            locationClient.requestLocationUpdates(locationRequest, this);
        else
            Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
    }
    // . . . . . . . . other methods
    @Override
    public void onLocationChanged(Location location) {
        locationClient.removeLocationUpdates(this);
        // Use the location here!!!
    }

Dans ce code, vous vérifiez si le client possède déjà le dernier emplacement (in onConnected). Sinon, vous demandez des mises à jour de localisation et désactivez les demandes (en onLocationChanged()rappel) dès que vous recevez une mise à jour.

Notez que le locationClient.requestLocationUpdates(locationRequest, this);doit être dans le onConnectedrappel, sinon vous obtiendrez un IllegalStateExceptioncar vous tenterez de demander des emplacements sans être connecté au client des services Google Play.

  • L'utilisateur a désactivé les services de localisation

Plusieurs fois, l'utilisateur aurait désactivé les services de localisation (pour économiser la batterie ou pour des raisons de confidentialité). Dans un tel cas, le code ci-dessus demandera toujours des mises à jour de localisation, mais onLocationChangedne sera jamais appelé. Vous pouvez arrêter les demandes en vérifiant si l'utilisateur a désactivé les services de localisation.

Si votre application les oblige à activer les services de localisation, vous souhaiterez afficher un message ou un toast. Malheureusement, il n'existe aucun moyen de vérifier si l'utilisateur a désactivé les services de localisation dans l'API des services de localisation de Google. Pour cela, vous devrez recourir à l'API d'Android.

Dans votre onCreateméthode:

    LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
    locationEnabled = false;
    Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show();
}
else locationEnabled = true;

Et utilisez le locationEnableddrapeau dans votre onConnectedméthode comme ceci:

    if (location != null) {
    Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
else if (location == null && locationEnabled) {
    locationClient.requestLocationUpdates(locationRequest, this);
}

METTRE À JOUR

Le document est mis à jour, LocationClient est supprimé et l'API prend en charge l'activation du GPS en un seul clic dans la boîte de dialogue:

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
    // All location settings are satisfied. The client can initialize
    // location requests here.
    // ...
}
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this,
                        REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException sendEx) {
                // Ignore the error.
            }
        }
    }
});

Lien https://developer.android.com/training/location/change-location-settings#prompt

Nouveau client d'emplacement: FusedLocationProviderClient

  private FusedLocationProviderClient fusedLocationClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}

Il est recommandé de passer par https://developer.android.com/training/location avant d'effectuer des tâches de localisation.


9
Vous pouvez utiliser SettingsApi.checkLocationSettings()pour vérifier si l'utilisateur a activé les services de localisation (voir ici: developer.google.com/android/reference/com/google/android/gms/… ).
kaolick

3
LocationClient n'existe plus. Pour un guide mis à jour et clair de l'emplacement, veuillez consulter cet article: blog.teamtreehouse.com/beginners-guide-location-android
lm2a

1
Et page de formation avec exemple SettingsApi: developer.android.com/training/location/…
androidguy

2
Vous pouvez également créer une géo-clôture en utilisant LocationManager! L'API de localisation fusionnée fonctionne-t-elle sur les appareils qui ne disposent pas de services Google Play?
Muhammad Babar

Cela peut être un autre meilleur moyen de vérifier l'état d'activation / désactivation du GPS fun isLocationEnabled(context: Context): Boolean { val locationMode: Int try { locationMode = Settings.Secure.getInt( context.contentResolver, Settings.Secure.LOCATION_MODE ) } catch (e: SettingNotFoundException) { e.printStackTrace() return false } return locationMode != Settings.Secure.LOCATION_MODE_OFF }
Wahib Ul Haq

32

D'après mon expérience, «une précision plus appropriée» ne signifie en aucun cas meilleure. À moins que je ne manque quelque chose, si vous voulez vous assurer que le GPS est utilisé, LocationManager est la seule solution. Nous suivons les véhicules avec notre application et, encore une fois, à moins que je ne manque quelque chose, les services Google Play fournissent assez souvent des emplacements très inexacts.


2
Oui, d'après mon expérience, les services Google Play fournissent parfois une localisation inexacte.
VY

2
Oui, l'API des services de localisation des services Google Play peut fournir des informations de localisation très trompeuses. Les modems WiFi sont déplacés, les modems WiFi sont mis à jour avec des informations de localisation incorrectes (c'est-à-dire si l'emplacement est usurpé par un appareil Android qui met à jour l'emplacement du modem WiFi) et il existe une foule d'autres circonstances qui peuvent entraîner des données de localisation incorrectes à partir de la triangulation du modem WiFi. Dans toutes nos applications où la localisation précise est obligatoire, nous utilisons uniquement le GPS.
user1608385

27

Vous devez utiliser l'API de localisation des services Google Play au lieu de LocationManager. Selon la documentation:

Les API de localisation des services Google Play sont préférées aux API de localisation du framework Android (android.location) comme moyen d'ajouter la reconnaissance de la localisation à votre application. Si vous utilisez actuellement les API de localisation du framework Android, nous vous encourageons vivement à passer aux API de localisation des services Google Play dès que possible.

Quant à savoir pourquoi changer, Google dit ceci:

L'API des services de localisation Google, qui fait partie des services Google Play, fournit un cadre plus puissant et de haut niveau qui gère automatiquement les fournisseurs de localisation, les déplacements des utilisateurs et la précision de la localisation. Il gère également la planification des mises à jour d'emplacement en fonction des paramètres de consommation d'énergie que vous fournissez. Dans la plupart des cas, vous obtiendrez de meilleures performances de la batterie, ainsi qu'une précision plus appropriée, en utilisant l'API des services de localisation.


2
Avez-vous des liens vers cette documentation d'où proviennent ces citations? Il serait intéressant de voir si Google dit quelque chose de différent maintenant.
Edward Brey

3
Bien sûr, ils disent cela, car ils veulent vos données de localisation!
Flyview

Lorsque vous ajoutez des services Google Play à votre application, si un utilisateur installe votre application, il sera invité à «mettre à jour» les services Google Play pour utiliser votre application. Dans le cas où son téléphone est presque plein (avec des mèmes WhatsApp et des trucs) ou si l'utilisateur n'a pas les données, désolé pour vous mon ami
Dr Deo

2
@Flyview Ouais! Lol, la façon dont ils le disent donne l'impression que c'est une solution magique! Le plus gros inconvénient est que vous avez besoin des services Google Play sur l'appareil !!!
varun

25

J'utilise l'API des services de localisation Google depuis un certain temps. Il présente des avantages, car il résume la complexité d'avoir plusieurs sources pour déterminer les positions. Cependant, il encapsule trop lourdement , de sorte que lorsque vous obtenez une position étrange, vous n'avez aucun moyen de déterminer d'où vient cette position étrange.

Dans la vraie vie, j'ai fait apparaître plusieurs valeurs bizarres, étant à 10 kilomètres de la position réelle. La seule explication est que ces emplacements fous proviennent d'erreurs dans les bases de données Googles Wi-Fi ou NWK - des erreurs qui seront toujours présentes, car les topologies Wi-Fi et réseau changent chaque jour. Mais malheureusement (et étonnamment) l'API ne vous donne aucune information sur la façon dont une position individuelle a été dérivée.

entrez la description de l'image ici

Cela vous laisse avec les problèmes de devoir filtrer les valeurs anormales en fonction de la vérification de la plausibilité de la vitesse, de l'accélération, du roulement, etc.

... ou revenez à la bonne vieille API du framework et n'utilisez que le GPS, ce que j'ai décidé de faire jusqu'à ce que Google améliore l'API fusionnée.


7

L'API des services de localisation Google , qui fait partie des services Google Play, fournit un cadre plus puissant et de haut niveau qui gère automatiquement les fournisseurs de localisation , les déplacements des utilisateurs et la précision de la localisation . Il gère également la planification de la mise à jour de l'emplacement en fonction des paramètres de consommation d'énergie que vous fournissez. Dans la plupart des cas, vous obtiendrez de meilleures performances de la batterie , ainsi qu'une précision plus appropriée, en utilisant l'API des services de localisation.

Des différences plus détaillées entre les deux API Google Play Service Location API et Android Framework Location API peuvent être trouvées ici


J'ai utilisé votre réponse pour répondre à ma propre question si cela vous convient. Merci beaucoup! stackoverflow.com/questions/39852955/…
Leniaal

@Leniaal, alors ne pensez-vous pas que ma réponse mérite un vote favorable?
Dhruvam Gupta

C'est un document vieux de 3 ans. Mais voici un plus 1
Tiré

5

Oui, l'API des services de localisation des services Google Play peut fournir des informations de localisation très trompeuses. Les modems WiFi sont déplacés, les modems WiFi sont mis à jour avec des informations de localisation incorrectes (c'est-à-dire si l'emplacement est usurpé par un appareil Android qui met à jour l'emplacement du modem WiFi) et il existe une foule d'autres circonstances qui peuvent entraîner des données de localisation incorrectes à partir de la triangulation du modem WiFi. Dans toutes nos applications où la localisation précise est obligatoire, nous utilisons uniquement le GPS.


3

Différences entre les deux API Google Play Service Location API et Android Framework Location API basée sur le service GPS

FusedLocationProviderClient

  1. Pour la première récupération, l'emplacement ne doit pas être nul (par exemple: une autre application doit mettre à jour l'emplacement Lastknown dans la base de données GoogleplayService. S'il est nul, il faut contourner le problème)
  2. Pour la prochaine récupération séquentielle, il utilise une requestLocationUpdates()méthode pour récupérer l'emplacement.
  3. L'extraction de l'emplacement est uniquement basée sur locationRequest.setInterval(milliseconds)et setFastestInterval(milliseconds)non sur le changement d'emplacement de l'utilisateur
  4. La valeur LatLng retournée ne contient que 7 valeurs décimales (par exemple: 11,9557996, 79,8234599), pas aussi précises
  5. Recommandé, lorsque les exigences de votre application prennent la distance de localisation actuelle négligeable de (précision de 50 à 100 mètres)
  6. Efficace dans l'utilisation de la batterie.

LocationManager Api

  1. L'extraction de l'emplacement de l'utilisateur est appelée à l'aide de locationManager.requestLocationUpdates ()
  2. La recherche d'emplacement en fonction du changement d'emplacement de l' utilisateur et des intervalles de temps locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, milliseconds, mindistance, Mylocationlistener)

  3. La valeur LatLng renvoyée contient 14 valeurs décimales (par exemple: 11,94574594963342 79,81166719458997) des valeurs de localisation précises

  4. Recommandé pour les applications basées sur la localisation, lorsque cela nécessite plus de précision, même en mètres.
  5. L'utilisation de la batterie est basée sur l'intervalle de récupération et la distance de récupération.

Hey! 1 ° est au plus 111_111 mètres (20_000_000 / 180). Ainsi, 0,0000001 ° est 0,011 m = 1 cm. Je ne sais pas où vous avez besoin d'une meilleure résolution GPS. Et je ne sais même pas comment obtenir une meilleure résolution GPS.
babay
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.