usa ubicación ubicacion servicio seleccionar remotamente que prueba para ofrece movil google forma este dispositivo desde desactivar continuar calibrar aplicacion aparece activar activa android geolocation gps google-play-services

android - ubicacion - El proveedor de la ubicación fusionada no parece usar el receptor GPS



seleccionar aplicacion de ubicacion de prueba no aparece (12)

¿Qué hay en el método OnConnected ?

En este método, debe crear el objeto LocationRequest con prioridad PRIORITY_HIGH_ACCURACY .

@Override public void onConnected(Bundle dataBundle) { mLocationRequest = LocationRequest.create(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mLocationClient.requestLocationUpdates(mLocationRequest, fusedListener); }

Android 4.3 en Moto G, Android 4.4.2 en Nexus 7 2012, Android 4.4.2 en Nexus 5. Android Studio 0.4.

No quiero recibir actualizaciones de ubicación regulares, solo quiero una ubicación precisa cuando el usuario presiona un botón.

He seguido este ejemplo: https://developer.android.com/training/location/retrieve-current.html

En archivo manifiesto:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Compruebo que los Servicios de reproducción están disponibles usando GooglePlayServicesUtil.isGooglePlayServicesDisponible

En la actividad principal:

//in activity onCreate method mLocationClient = new LocationClient(this, this, this); @Override protected void onStart() { mLocationClient.connect(); super.onStart(); } @Override protected void onStop() { mLocationClient.disconnect(); super.onStop(); } //in button onclick method mCurrentLocation = mLocationClient.getLastLocation();

No tengo tarjeta SIM. Si habilito Wifi, a veces obtengo una ubicación precisa. Otras veces mCurrentLocation es nulo.

Si deshabilito Wifi, mCurrentLocation siempre es nulo.

Estoy probando afuera en varios lugares siempre con una vista clara del cielo. Esperé tres minutos en cada ubicación.

Nunca veo el icono de GPS aparecer en la barra de notificaciones de Android en la parte superior de la pantalla.

Tengo estas configuraciones de ubicación:

Una aplicación de prueba de GPS logra usar el GPS con éxito en el interior en el mismo dispositivo con Wi-Fi desactivado para que el GPS funcione:

El registro de actualizaciones de ubicación, como en https://developer.android.com/training/location/receive-location-updates.html , tampoco funciona. Método registrado nunca llamado.

¿Qué estoy haciendo mal?


Como nadie ha compartido este enlace, he encontrado que esta es la documentación más útil http://developer.android.com/guide/topics/location/strategies.html

"Es probable que la corrección de ubicación más reciente sea la más precisa. Sin embargo, como la precisión de una corrección de ubicación varía, la corrección más reciente no siempre es la mejor. Debe incluir la lógica para elegir arreglos de ubicación según varios criterios. los criterios también varían según los casos de uso de la aplicación y las pruebas de campo ".

Su mejor opción es mantener activo un oyente de localización siempre que la actividad esté en primer plano y seleccionar la ubicación en caché más precisa cuando se presione el botón. Es posible que deba mostrar una ruleta o algo así y desactivar el botón mientras espera que aparezca una medición precisa.


Creo que estás probando tu aplicación en Indoor, no funciona ...

y flujo de código ...

public void setUpLocationClientIfNeeded() { createLocReq(); if (mLocationClient == null) { mLocationClient = new LocationClient(getApplicationContext(), this, // ConnectionCallbacks this); // OnConnectionFailedListener } } private void createLocReq() { if (mLocationRequest == null) { // Create a new global location parameters object mLocationRequest = LocationRequest.create(); // Set the update interval mLocationRequest.setInterval(LocationServices.UPDATE_INTERVAL_IN_MILLISECONDS); // Use high accuracy mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // Set the interval ceiling to one minute mLocationRequest.setFastestInterval(LocationServices.FAST_INTERVAL_CEILING_IN_MILLISECONDS); mLocationClient = new LocationClient(getApplicationContext(), this, this); mLocationClient.connect(); } } public void updateLocation(Location location) { if (lastTrackedLat == 0.0) { lastTrackedLat = location.getLatitude(); } if (lastTrackedLng == 0.0) { lastTrackedLng = location.getLongitude(); } currentLat = location.getLatitude(); currentLng = location.getLongitude(); } @Override public void onLocationChanged(Location location) { if (location != null) { this.location = location; updateLocation(location); } } public Location getLocation() { // mLocationClient.getLastLocation(); return location; }


De acuerdo con los documentos

Este método proporciona una forma simplificada de obtener ubicación. Es especialmente adecuado para aplicaciones que no requieren una ubicación precisa y que no desean mantener una lógica adicional para las actualizaciones de ubicación.

por lo que puede devolver o no una ubicación muy precisa.

El GPS puede tardar un tiempo en getLastLocation por lo que llamar a getLastLocation puede devolver una ubicación o no.

es mejor que solicite actualizaciones de ubicación y, luego de obtener una ubicación, simplemente deje de solicitar actualizaciones de ubicación.

También mirando el código que proporcionó, ¿está esperando que LocationClient conecte antes de intentar obtener una ubicación? Eso sin duda le dará una ubicación nula ya que no está conectado para obtener la ubicación todavía.

lo que deberías hacer es onConnected tu onConnected la última ubicación allí, por ejemplo

public void onConnected(Bundle connectionHint) { Location location = mLocationClient.getLastLocation(); }

como se dice en ese ejemplo onConnected es Called by Location Services when the request to connect the client finishes successfully. At this point, you can request the current location or start periodic updates Called by Location Services when the request to connect the client finishes successfully. At this point, you can request the current location or start periodic updates


El problema es con getLastLocation() porque usa una ubicación en caché. Tuve el mismo problema ya que también intenté usar este enfoque simple. Desde entonces, he cambiado a escuchar actualizaciones (y parar después de la primera actualización exitosa de forma automática).

Este es mi código que funciona.

En primer lugar, el control de disponibilidad en la aplicación (no esencial, puede estar en la actividad y sin guardar el resultado):

public class MainApp extends Application { public static enum PlayServices { NOT_CHECKED, AVAILABLE, UNAVAILABLE }; public static PlayServices mPlayServices = PlayServices.NOT_CHECKED; @Override public void onCreate() { super.onCreate(); if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) { MainApp.mPlayServices = MainApp.PlayServices.AVAILABLE; } } }

Luego, a la Actividad:

public class MainActivity extends SherlockFragmentActivity implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {

En su onCreate() :

if (MainApp.mPlayServices != MainApp.PlayServices.UNAVAILABLE) { mLocationClient = new LocationClient(this, this, this); mLocationRequest = LocationRequest.create(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mLocationRequest.setInterval(5000); mLocationRequest.setNumUpdates(1); mLocationRequest.setFastestInterval(1000); mUpdatesRequested = false; MainApp.prefs.edit().putBoolean(MainApp.KEY_LOCATION_UPDATES_REQUESTED, mUpdatesRequested) .commit(); }

El resto de la clase MainActivity :

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d(this.getClass().getSimpleName(), "onActivityResult(" + requestCode + ", " + resultCode + ")"); // Decide what to do based on the original request code switch (requestCode) { case MainApp.PLAY_CONNECTION_FAILURE_RESOLUTION_REQUEST: /* * If the result code is Activity.RESULT_OK, try * to connect again */ switch (resultCode) { case Activity.RESULT_OK: // here we want to initiate location requests! mLocationClient = new LocationClient(this, this, this); break; } break; } } @Override public void onConnected(Bundle dataBundle) { Log.d(this.getClass().getSimpleName(), "onConnected()"); Log.d(this.getClass().getSimpleName(), "Google Play Services are available."); MainApp.mPlayServices = MainApp.PlayServices.AVAILABLE; if (!mUpdatesRequested) { LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); boolean gps_enabled = false; try { gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER); } catch (Exception ex) { } boolean network_enabled = false; try { network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER); } catch (Exception ex) { } // don''t start listeners if no provider is enabled MainApp.locEnabled = gps_enabled || network_enabled; if (!MainApp.locEnabled) { // we have access to PlayServices, but user has disabled location visibility --> alert him alertLocationOff(); } else { mLocationClient.requestLocationUpdates(mLocationRequest, this); mUpdatesRequested = true; } } } @Override public void onDisconnected() { Log.d(this.getClass().getSimpleName(), "onDisconnected()"); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { Log.d(this.getClass().getSimpleName(), "onConnectionFailed()"); Log.d(this.getClass().getSimpleName(), "Google Play Services not available."); MainApp.mPlayServices = MainApp.PlayServices.UNAVAILABLE; /* * Google Play services can resolve some errors it detects. * If the error has a resolution, try sending an Intent to * start a Google Play services activity that can resolve * error. */ if (connectionResult.hasResolution()) { try { // Start an Activity that tries to resolve the error connectionResult.startResolutionForResult(this, MainApp.PLAY_CONNECTION_FAILURE_RESOLUTION_REQUEST); /* * Thrown if Google Play services canceled the original * PendingIntent */ } catch (IntentSender.SendIntentException e) { // Log the error e.printStackTrace(); } } else { /* * If no resolution is available, display a dialog to the * user with the error. */ GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), this, 0).show(); } } @SuppressLint("NewApi") @Override public void onLocationChanged(Location location) { Log.d(this.getClass().getSimpleName(), "onLocationChanged(), location=" + location); if (location != null) { boolean present = true; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { present = Geocoder.isPresent(); } if (present) { (new ExtractLocationTask(this)).execute(location); } else { Log.e(this.getClass().getSimpleName(), "Geocoder not present"); MainApp.mPlayServices = MainApp.PlayServices.UNAVAILABLE; } } } private class ExtractLocationTask extends AsyncTask<Location, Void, Boolean> { Context mContext; public ExtractLocationTask(Context context) { super(); mContext = context; } @Override protected Boolean doInBackground(Location... params) { Log.d(getClass().getSimpleName(), "ExtractLocationTask.onPreExecute()"); boolean found = false; try { Geocoder geoCoder_local = new Geocoder(mContext, Locale.getDefault()); Geocoder geoCoder_en = new Geocoder(mContext, Locale.ENGLISH); List<Address> addresses_local = geoCoder_local.getFromLocation(params[0].getLatitude(), params[0].getLongitude(), 10); List<Address> addresses_en = geoCoder_en.getFromLocation(params[0].getLatitude(), params[0].getLongitude(), 10); if (addresses_local != null && addresses_local.size() > 0) { // do what you want with location info here // based on mLocationRequest.setNumUpdates(1), no need to call // removeLocationUpdates() MainApp.locEnabled = true; mUpdatesRequested = false; MainApp.prefs.edit() .putBoolean(MainApp.KEY_LOCATION_UPDATES_REQUESTED, mUpdatesRequested).commit(); found = true; } } catch (IOException e) { Log.e(this.getClass().getSimpleName(), "Exception: ", e); } return found; } @Override protected void onPostExecute(Boolean found) { Log.d(getClass().getSimpleName(), "ExtractLocationTask.onPostExecute()"); if (found) { // update UI etc. } else if (!mUpdatesReRequested) { mLocationClient.requestLocationUpdates(mLocationRequest, (LocationListener) mContext); mUpdatesRequested = true; mUpdatesReRequested = true; } } }

¡Espero que esto te ayude a hacer que funcione!


El proveedor de ubicación no activará el GPS hasta que algunos clientes soliciten (suscriban) una ubicación de alta precisión (como se describe en ejemplos proporcionados por otros usuarios). La aplicación de prueba GPS no usa el proveedor de ubicación, pero usa una forma antigua y "directa" de obtener la ubicación.

También hay un mecanismo de expiración, que elimina información sobre la última ubicación después de algún tiempo si se cree que está obsoleta.

Resumiendo todo lo anterior, es muy posible que LP (Proveedor de ubicación) no tenga nada que ofrecerle.


Hay dos cosas que suceden aquí que ocasionan que a veces obtengas un null , y algunas veces obtienes una ubicación.

Primero, está creando una nueva instancia de LocationClient en el método onClick , que no es la misma instancia a la que llama connect() en onStart() . Esto creará un comportamiento impredecible en el que a veces el cliente tendrá tiempo suficiente para conectarse antes de devolver un resultado de LocationClient.getLastLocation() , y en ocasiones no lo hará.

En segundo lugar, debe proteger la llamada a LocationClient.getLastLocation() con una llamada a LocationClient.isConnected() . Dice lo siguiente en los documentos de LocationClient.isConnected() : https://developer.android.com/reference/com/google/android/gms/location/LocationClient.html#isConnected()

Comprueba si el cliente está actualmente conectado al servicio, para que las solicitudes a otros métodos tengan éxito. Las aplicaciones deben proteger las acciones del cliente causadas por el usuario con una llamada a este método.

Como el usuario activa el código onClick() tocando el botón, debe llamar a este método antes de tratar de obtener la última ubicación.

Entonces, tu código debería verse así:

LocationClient mLocationClient; Location mCurrentLocation; @Override protected void onCreate() { ... mLocationClient = new LocationClient(this, this, this); ... } @Override protected void onStart() { mLocationClient.connect(); super.onStart(); } @Override protected void onStop() { mLocationClient.disconnect(); super.onStop(); } public void onClick(View v) { ... if (mLocationClient.isConnected()) { // You should get a valid location here mCurrentLocation = mLocationClient.getLastLocation(); } }

Esto debería darle al LocationClient tiempo suficiente para conectarse y darle una ubicación válida, que con suerte debería incluir datos de GPS.


Lo solucioné El problema era que "Deje que las aplicaciones de Google accedan a su ubicación" estaba desactivado:

Cuando lo enciendo obtengo lecturas de GPS y cuando está apagado no lo hago.

Lo había dejado por dos razones:

  1. Estoy desarrollando una aplicación para utilizar en muchos dispositivos de una empresa y quiero que sea necesaria una configuración manual mínima

  2. La pantalla dice claramente "Esta configuración afecta únicamente a las aplicaciones de Google". Sé que Play Services es el software de Google, pero no creo que Google espere que un usuario final lo entienda.

Luego recibí la actualización de Android 4.4.2 y la página de configuración de ubicación ha cambiado. Parece que puedo desactivar los Informes de Ubicación de Google y aún obtener las lecturas de GPS del proveedor de ubicación fusionada:

Entonces, tal vez Google se dio cuenta de que la configuración era confusa y la mejoró. De cualquier manera, habría ahorrado mucho tiempo si hubiera obtenido 4.4.2 hace unos días.


Prefiero usar el Servicio que implementa LocationListener para obtener una ubicación actual casi exacta. Normalmente tomo los siguientes pasos:

  1. Inicialice LocationManager y llame a requestLocationUpdates para GPS_PROVIDER y NETWORK_PROVIDER en onCreate()
  2. Llame a getLastKnownLocation para GPS_PROVIDER y NETWORK_PROVIDER y use getTime() para conocer la última ubicación más reciente.
  3. Transmitir la última ubicación (si es <30 segundos de antigüedad) (opcional)
  4. Mientras tanto, cuando se llama a onLocationChanged , comparo la ubicación recientemente actualizada con la última mejor ubicación (si existe) y verifico el nivel de precisión.
  5. Si es preciso delta <MIN_ACCURACY (variable de usuario), úselo como la mejor ubicación
  6. Transmitir la mejor ubicación actual
  7. Debe eliminar LocationManager locationManager.removeUpdates(this);
  8. Llamar a StopSelf (); (También puede detener el servicio de la actividad en onDestroy )

EDITAR:

OK ... El método anterior estaba usando la API de ubicación, a continuación he codificado usando Fused Provider (GooglePlayServices). He probado en mi Nexus 5 (Android 4.4.2), SIN SIM, SIN WIFI ... y obtengo resultados.

Edición 2: también he probado en Android 2.3.3 LG Optimus (Sin SIM y Wifi) y me tomó alrededor de 5 minutos obtener el bloqueo (usando Fused Provided), pero obtuve el ícono de ubicación al instante.

public class HomeActivity extends FragmentActivity implements ActionBar.OnNavigationListener, GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener { private LocationClient locationClient; private LocationRequest locationRequest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); // ... int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (resp == ConnectionResult.SUCCESS) { locationClient = new LocationClient(this, this, this); locationClient.connect(); } else { Toast.makeText(this, "Google Play Service Error " + resp, Toast.LENGTH_LONG).show(); } } @Override public void onConnected(Bundle connectionHint) { if (locationClient != null && locationClient.isConnected()) { locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationRequest.setInterval(100); locationClient.requestLocationUpdates(locationRequest, this); } } @Override public void onLocationChanged(Location location) { try { if (location != null) { LatLng gps = new LatLng(location.getLatitude(), location.getLongitude()); Log.v("JD", "My Location: " + gps.toString()); } } catch (Exception e) { Log.d("JD", "onLocationChanged", e); } } }


Prueba esto:

public final static int MINACCURACY = 50; private LocationManager lm; private LocationListener listener; private void foundLoc(double x, double y) { // do something with x,y Log.v("DEBUG", x + "," + y); } public void findMe(View v) { lm = (LocationManager) getSystemService(LOCATION_SERVICE); listener = new LocationListener() { @Override public void onLocationChanged(Location location) { if(location.getAccuracy() < MINACCURACY) { foundLoc(location.getLatitude(), location.getLongitude()); lm.removeUpdates(listener); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } }; lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0, listener); }

MINACCURACY está en metros. De esta manera, al presionar un botón (que llama al método findMe), el GPS está habilitado, su ubicación se encuentra con una precisión mínima, el método foundLoc obtiene los datos y el oyente finaliza (lo cual, a su vez, desactiva el GPS).


Sin una tarjeta SIM, el coarse location provider no tiene forma de conocer la posición aproximada, a menos que pueda encontrar una red WiFi que haya sido asignada por Google.

Solicitar la última ubicación conocida puede dar como resultado una ubicación obsoleta, y como tal es bastante inútil. Supongo que esta es la posición que se grabó la última vez que alguna aplicación solicitó una actualización de ubicación.

Uso el siguiente código para obtener una ubicación reciente:

Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_COARSE); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(false); final LocationManager manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); .... LocationListener listener = new LocationListener() { @Override public void onLocationChanged(Location lastKnownLocation) { .... } // rest of interface } manager.requestSingleUpdate(criteria, listener, null);

La última llamada garantiza que solicitemos la ubicación actual , no la ubicación en la que pudo encontrar una cantidad de tiempo desconocida anteriormente.

Puede intentar cambiarlo a Criteria.ACCURACY_FINE para encender el GPS. Tenga en cuenta que si el GPS no tiene una solución durante bastante tiempo, puede tomar más de varios minutos antes de que sea realmente capaz de obtener una solución. Mientras tanto, esperaría que veas el icono del GPS que indica que está esperando una solución.


Todo lo que necesita hacer es agregar una propiedad de prioridad al objeto de solicitud como este.

public void onConnected(Bundle arg0) { locationrequest = LocationRequest.create(); locationrequest.setInterval(1000); locationrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationclient.requestLocationUpdates(locationrequest, this); }

Tal vez use una variable booleana para permitirle al usuario tener opciones para forzar el GPS como

boolean forceGPS=false; . . .//make the user choose to change the value of the boolean . . public void onConnected(Bundle arg0) { locationrequest = LocationRequest.create(); locationrequest.setInterval(1000); if(forceGPS==true) { locationrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); } locationclient.requestLocationUpdates(locationrequest, this); }