Saltar al contenido

Android: LocationManager vs Google Play Services

Solución:

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 es utilizar las API de Android de android.location.LocationListenery el segundo está utilizando las API de los servicios de Google Play. com.google.android.gms.location.LocationListener. Repasemos ambos.

  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 poco 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 de red.
    • LocationManager.PASSIVE_PROVIDER – Este proveedor devolverá ubicaciones generadas por otros proveedores. Recibes actualizaciones de ubicación de forma pasiva cuando otras aplicaciones o servicios las solicitan sin que tú mismo las solicites.

La esencia de esto es que obtienes un objeto de LocationManager del sistema, implemente el LocationListenery llama al requestLocationUpdates sobre el 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ón explica 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, si utiliza la API de servicios de ubicación de Google. ¡Ahora comienza la confusión!

  1. API de servicios de ubicación de Google

La API de servicios de ubicación de Google es parte del APK de Google Play Services (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 sigue actualizándolo. Y puede utilizar funciones más avanzadas, como geocercas.

Para utilizar los servicios de ubicación de Google, su aplicación debe conectarse al GooglePlayServicesClient. Para conectarse con el cliente, su actividad (o fragmento, más o menos) debe implementar GooglePlayServicesClient.ConnectionCallbacks y GooglePlayServicesClient.OnConnectionFailedListener interfaces. 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 que es locationClient.getLastLocation() null?

los locationClient.getLastLocation() obtiene 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 él. Una vez que el primer cliente se conecte, inmediatamente intentará obtener una ubicación. Si tu actividad es el primer cliente en conectarse y llamas getLastLocation() de inmediato en onConnected(), puede que no sea suficiente tiempo para que llegue la primera ubicación. Esto dará como resultado location ser null.

Para resolver este problema, debe esperar (indeterminadamente) hasta que el proveedor obtenga la ubicación y luego llamar getLastLocation(), que es imposible de saber. Otra (mejor) opción es implementar la com.google.android.gms.location.LocationListener interfaz para recibir actualizaciones periódicas de ubicación (y apáguela 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, está comprobando si el cliente ya tiene la última ubicación (en onConnected). De lo contrario, 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 el locationClient.requestLocationUpdates(locationRequest, this); tiene que estar dentro del onConnected devolución de llamada, o de lo contrario obtendrá una IllegalStateException porque intentará solicitar ubicaciones sin estar conectado al cliente de servicios de Google Play.

  • El usuario ha desactivado los servicios de ubicación

Muchas veces, el usuario tendría los servicios de ubicación deshabilitados (para ahorrar batería o por razones de privacidad). En tal caso, el código anterior aún solicitará actualizaciones de ubicación, pero onLocationChanged nunca se llamará. Puede detener las solicitudes comprobando si el usuario ha desactivado 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 desactivado los servicios de ubicación en la API de servicios de ubicación de Google. Para ello, tendrá que volver a recurrir a la API de Android.

En tus onCreate mé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 el locationEnabled bandera en tu onConnected método como este:

    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, LocationClient se elimina y la API admite la habilitación del GPS con un clic en el cuadro de diálogo:

task.addOnSuccessListener(this, new OnSuccessListener() 
@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.

En mi experiencia, “precisión más apropiada” no significa mejor de ninguna manera. A menos que me falte algo, si quieres asegurarte de que se usa el GPS, LocationManager es el único camino a seguir. Realizamos un seguimiento de los vehículos con nuestra aplicación y, de nuevo, a menos que me falte algo, Google Play Services proporciona algunas ubicaciones muy inexactas con bastante frecuencia.

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

Se prefieren las API de ubicación de los servicios de Google Play a las API de ubicación del marco de trabajo 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 trabajo de Android, se le recomienda 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 servicios de ubicación de Google, que forma parte de los servicios de Google Play, proporciona un marco más potente y de alto nivel que gestiona automáticamente los proveedores de ubicación, el movimiento de los usuarios 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.

Finalizando este artículo puedes encontrar las críticas de otros creadores, tú todavía eres capaz dejar el tuyo si te gusta.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *