Android: LocationManager vs Google Play Services

151

Quiero crear una aplicación que se centre en obtener la ubicación actual del usuario y luego encontrar puntos de interés (como bares, restaurantes, etc.) que estén cerca de él a través de la API de Google Places .

Al buscar en la web un lugar para comenzar, me encontré con algunos tutoriales que usan la LocationManagerclase y otros que usan los Servicios de Google Play para encontrar la ubicación de los usuarios.

A primera vista, ambos hacen lo mismo, pero como soy nuevo en esto, me confundo un poco y no sé qué método se adapta mejor a mis necesidades. Entonces, quiero preguntarte:

¿Cuáles son las diferencias entre estos dos métodos para encontrar ubicaciones (si las hay)?

SoCo
fuente
1
visite aquí stackoverflow.com/questions/21397177/…
Mohammad Tauqir

Respuestas:

319

Ubicación del usuario en Android

Obtener la ubicación del usuario en Android es un poco menos sencillo que en iOS. Para comenzar la confusión, hay dos formas totalmente diferentes de hacerlo. El primero usa las API de Android android.location.LocationListenery el segundo usa las API de los servicios de Google Play com.google.android.gms.location.LocationListener. Veamos los dos.

  1. API de ubicación de Android

    Las API de ubicación de Android utilizan tres proveedores diferentes para obtener la ubicación:

    • LocationManager.GPS_PROVIDER- Este proveedor determina la ubicación mediante satélites. Dependiendo de las condiciones, este proveedor puede tardar un tiempo en devolver una corrección de ubicación.
    • LocationManager.NETWORK_PROVIDER- Este proveedor determina la ubicación según la disponibilidad de la torre celular y los puntos de acceso WiFi. Los resultados se recuperan mediante una búsqueda en la red.
    • LocationManager.PASSIVE_PROVIDER- Este proveedor devolverá ubicaciones generadas por otros proveedores. Recibirá actualizaciones de ubicación pasivamente cuando otras aplicaciones o servicios las soliciten sin solicitar las ubicaciones usted mismo.

La esencia de esto es que obtienes un objeto del LocationManagersistema, implementas LocationListenery llamas requestLocationUpdatesal LocationManager.

Aquí hay un fragmento de código:

    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);

Guía de API de Google sobre estrategias de ubicaciónexplica el código bastante bien. Pero también mencionan que en la mayoría de los casos, obtendrá un mejor rendimiento de la batería, así como una precisión más adecuada, utilizando en su lugar la API de Google Location Services . ¡Ahora comienza la confusión!

  1. API de servicios de ubicación de Google

La API de servicios de ubicación de Google forma parte del APK de servicios de Google Play ( aquí se explica cómo configurarlo ). Están construidos sobre la API de Android. Estas API proporcionan un "Proveedor de ubicación fusionada" en lugar de los proveedores mencionados anteriormente. Este proveedor elige automáticamente qué proveedor subyacente usar, en función de la precisión, el uso de la batería, etc. Es rápido porque obtiene la ubicación de un servicio de todo el sistema que lo actualiza constantemente. Y puede usar funciones más avanzadas como geofencing.

Para usar los Servicios de ubicación de Google, su aplicación debe conectarse a GooglePlayServicesClient. Para conectarse con el cliente, su actividad (o fragmento, más o menos) necesita implementarse GooglePlayServicesClient.ConnectionCallbackse GooglePlayServicesClient.OnConnectionFailedListenerinterfaces. Aquí hay un código de muestra:

    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 
    }
  • ¿Por qué es locationClient.getLastLocation()nulo?

El locationClient.getLastLocation()tiene la última ubicación conocida del cliente. Sin embargo, el proveedor de ubicación fusionada solo mantendrá la ubicación en segundo plano si al menos un cliente está conectado a ella. Una vez que se conecta el primer cliente, inmediatamente intentará obtener una ubicación. Si su actividad es el primer cliente en conectarse y usted llama de getLastLocation()inmediato onConnected(), puede que no sea suficiente tiempo para que ingrese la primera ubicación. Esto resultará en locationser null.

Para resolver este problema, debe esperar (indeterminadamente) hasta que el proveedor obtenga la ubicación y luego llamar getLastLocation(), lo que es imposible saber. Otra opción (mejor) es implementar la com.google.android.gms.location.LocationListenerinterfaz para recibir actualizaciones periódicas de ubicación (y apagarla una vez que obtenga la primera actualización).

    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!!!
    }

En este código, verifica si el cliente ya tiene la última ubicación (en onConnected). Si no, está solicitando actualizaciones de ubicación y desactivando las solicitudes (en onLocationChanged()devolución de llamada) tan pronto como reciba una actualización.

Tenga en cuenta que locationClient.requestLocationUpdates(locationRequest, this);debe estar dentro de la onConnecteddevolución de llamada, de lo contrario, recibirá un IllegalStateExceptionmensaje porque intentará solicitar ubicaciones sin estar conectado al Cliente de servicios de Google Play.

  • El usuario ha deshabilitado los Servicios de ubicación

Muchas veces, el usuario deshabilitaría los servicios de ubicación (para ahorrar batería o razones de privacidad). En tal caso, el código anterior aún solicitará actualizaciones de ubicación, pero onLocationChangednunca se le llamará. Puede detener las solicitudes comprobando si el usuario ha deshabilitado los servicios de ubicación.

Si su aplicación requiere que habiliten los servicios de ubicación, querrá mostrar un mensaje o un brindis. Desafortunadamente, no hay forma de verificar si el usuario ha deshabilitado los servicios de ubicación en la API de servicios de ubicación de Google. Para esto, tendrá que recurrir a la API de Android.

En su onCreatemétodo:

    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;

Y usa la locationEnabledbandera en tu onConnectedmétodo así:

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

ACTUALIZAR

El documento se actualiza, se elimina LocationClient y la API admite habilitar el GPS con un clic desde el cuadro de diálogo:

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.
            }
        }
    }
});

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

Nuevo cliente de ubicación: FusedLocationProviderClient

  private FusedLocationProviderClient fusedLocationClient;

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

Se recomienda pasar por https://developer.android.com/training/location antes de realizar cualquier tarea de ubicación.

PRENSA
fuente
9
Puede SettingsApi.checkLocationSettings()verificar si el usuario ha habilitado los Servicios de ubicación (consulte aquí: developers.google.com/android/reference/com/google/android/gms/… ).
kaolick
3
LocationClient ya no existe. Para obtener una guía actualizada y clara de Ubicación, consulte este artículo: blog.teamtreehouse.com/beginners-guide-location-android
lm2a
1
Y página de entrenamiento con el ejemplo de SettingsApi: developer.android.com/training/location/…
androidguy
2
¡También puedes crear una geovalla usando LocationManager! ¿La API de ubicación fusionada funciona en dispositivos que no tienen servicios de Google Play?
Muhammad Babar
Esta puede ser otra mejor manera de verificar el estado de 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 }
activación
32

En mi experiencia, "precisión más apropiada" no significa mejor de ninguna manera. A menos que me falte algo, si desea asegurarse de que se utiliza el GPS, LocationManager es el único camino a seguir. Rastreamos vehículos con nuestra aplicación y, de nuevo, a menos que me falte algo, los Servicios de Google Play proporcionan algunas ubicaciones muy inexactas con bastante frecuencia.

Equipo
fuente
2
Sí, desde mi experiencia, los Servicios de Google Play a veces proporcionan una ubicación inexacta.
VY
2
Sí, la API de servicios de ubicación de Google Play Services puede proporcionar información de ubicación muy engañosa. Los módems WiFi se mueven, los módems WiFi se actualizan con información de ubicación incorrecta (es decir, si la ubicación es falsificada por un dispositivo Android que actualiza la ubicación del módem WiFi) y hay una serie de otras circunstancias que pueden dar lugar a datos de ubicación incorrectos de la triangulación del módem WiFi. En todas nuestras aplicaciones donde la ubicación precisa es obligatoria, usamos solo GPS.
user1608385
27

Debes usar la API de ubicación de Google Play Services en lugar de LocationManager. Según los documentos:

Las API de ubicación de los servicios de Google Play son preferibles a las API de ubicación del marco de Android (android.location) como una forma de agregar conocimiento de ubicación a su aplicación. Si actualmente está utilizando las API de ubicación del marco de Android, le recomendamos encarecidamente que cambie a las API de ubicación de los servicios de Google Play lo antes posible.

En cuanto a por qué cambiar, Google dice esto:

La API de Google Location Services, parte de Google Play Services, proporciona un marco más potente y de alto nivel que maneja automáticamente los proveedores de ubicación, el movimiento del usuario y la precisión de la ubicación. También maneja la programación de actualizaciones de ubicación en función de los parámetros de consumo de energía que proporcione. En la mayoría de los casos, obtendrá un mejor rendimiento de la batería, así como una precisión más adecuada, mediante el uso de la API de servicios de ubicación.

NoChinDeluxe
fuente
2
¿Tiene enlaces a esa documentación de la que provienen estas citas? Sería interesante ver si Google está diciendo algo diferente ahora.
Edward Brey
3
Por supuesto que dicen esto, ¡porque quieren sus datos de ubicación!
Flyview
Cuando agrega servicios de Google Play a su aplicación, si un usuario instala su aplicación, se le pedirá que "actualice" los servicios de Google Play para usar su aplicación. En caso de que su teléfono esté casi lleno (con memes de Whatsapp y otras cosas) o si el usuario no tiene los datos, lo siento, amigo mío
Dr. Deo
2
@Flyview ¡Sí! Lol, la forma en que lo dicen lo hace sonar como si fuera una solución mágica. ¡El mayor inconveniente es que necesitas los servicios de Google Play en el dispositivo!
varun
25

He estado usando la API de servicios de ubicación de Google durante bastante tiempo. Tiene ventajas, ya que encapsula la complejidad de tener varias fuentes para determinar posiciones. Sin embargo, encapsula demasiado , de modo que cuando obtienes una posición extraña, no tienes forma de determinar de dónde vino esa posición extraña.

En la vida real he aparecido varios valores extraños, a 10 kilómetros de distancia de la posición real. La única explicación es que estas locas locaciones provienen de errores en las bases de datos de Google Wi-Fi o NWK, errores que siempre estarán allí, ya que las topologías de red y Wi-Fi cambian todos los días. Pero desafortunadamente (y sorprendentemente) la API no le brinda información sobre cómo se derivó una posición individual.

ingrese la descripción de la imagen aquí

Esto te deja con los problemas de tener que filtrar los valores anormales basados ​​en la verificación de plausibilidad de velocidad, aceleración, demora, etc.

... o regrese a la buena API de framework y use solo GPS, que es lo que decidí hacer hasta que Google mejore la API fusionada.

j3App
fuente
7

La API de Google Location Services , parte de Google Play Services, proporciona un marco de trabajo de alto nivel más potente que maneja automáticamente los proveedores de ubicación , el movimiento del usuario y la precisión de la ubicación . También maneja la programación de actualizaciones de ubicación en función de los parámetros de consumo de energía que proporcione. En la mayoría de los casos, obtendrá un mejor rendimiento de la batería , así como una precisión más adecuada, mediante el uso de la API de servicios de ubicación.

Diffferences más detallada entre las dos API Google Play Service Location API y Android Marco Ubicación API se puede encontrar aquí

Dhruvam Gupta
fuente
Usé tu respuesta para responder mi propia pregunta si está bien. ¡Muchas gracias! stackoverflow.com/questions/39852955/…
Leniaal
@Leniaal, ¿no crees que mi respuesta merece un voto positivo?
Dhruvam Gupta
Ese es un documento de 3 años. Pero aquí hay un plus 1
Drew el
5

Sí, la API de servicios de ubicación de Google Play Services puede proporcionar información de ubicación muy engañosa. Los módems WiFi se mueven, los módems WiFi se actualizan con información de ubicación incorrecta (es decir, si la ubicación es falsificada por un dispositivo Android que actualiza la ubicación del módem WiFi) y hay una serie de otras circunstancias que pueden dar lugar a datos de ubicación incorrectos de la triangulación del módem WiFi. En todas nuestras aplicaciones donde la ubicación precisa es obligatoria, usamos solo GPS.

usuario1608385
fuente
4

Diferencias entre las dos API API de ubicación del servicio de Google Play y la API de ubicación de Android Framework basadas en el servicio GPS

FusedLocationProviderClient

  1. Para la primera búsqueda, la ubicación no debe ser nula (es decir: alguna otra aplicación necesita actualizar la ubicación de Lastknown en la base de datos de GoogleplayService. Si es nula, debe solucionarse)
  2. Para el siguiente Fetch secuencial, utiliza el requestLocationUpdates()método para recuperar la ubicación.
  3. La búsqueda de ubicación solo se basa locationRequest.setInterval(milliseconds)y setFastestInterval(milliseconds)no se basa en el cambio de ubicación del usuario
  4. El valor LatLng devuelto contiene solo 7 valores decimales (por ejemplo: 11.9557996, 79.8234599), no tan precisos
  5. Recomendado, cuando el requisito de su aplicación toma una distancia de ubicación actual insignificante (precisión de 50 a 100 metros)
  6. Efectivo en el uso de la batería.

LocationManager Api

  1. La búsqueda de ubicación del usuario se invoca mediante locationManager.requestLocationUpdates ()
  2. La búsqueda de ubicación basada en el cambio de ubicación del usuario y los intervalos de tiempo locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, milliseconds, mindistance, Mylocationlistener)

  3. El valor LatLng devuelto contiene 14 valores decimales (por ejemplo: 11.94574594963342 79.81166719458997) valores de ubicación precisos

  4. Recomendado para la aplicación basada en la ubicación, cuando necesita más precisión incluso en metros.
  5. El uso de la batería se basa en el intervalo de recuperación y la distancia de recuperación.
Sackurise
fuente
¡Oye! 1 ° es como máximo 111_111 metros (20_000_000 / 180). Entonces, 0.0000001 ° es 0.011m = 1 cm. No sé dónde necesitas una mejor resolución de GPS. Y ni siquiera sé cómo puedes lograr una mejor resolución GPS.
babay