android - manager - LocationClient getLastLocation() return null
location manager android example (13)
En las versiones SDK 23
También deberá solicitar explícitamente el permiso de ubicación durante el tiempo de ejecución , según https://developer.android.com/training/permissions/requesting.html , además de tenerlo en el archivo de manifiesto.
No se producirá ningún error explícito si no tiene los permisos durante el tiempo de ejecución, el proveedor de la ubicación simplemente devolverá nulo.
Ayudaría si Google documentara esto, y también lanzara una excepción en lugar de simplemente devolver el nulo. Regresar nulo es lo menos útil que se puede hacer en esta situación.
Al igual que las preguntas que alguien hizo antes de probar uno de los nexus s (4.0.4 con google play service disponible) y avd (4.2.2 con google api), en ambos casos, ubicaciónclienteLocalizar getLastLocation()
siempre devuelve null
.
public class MainActivity extends Activity implements LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
boolean mUpdatesRequested = false;
boolean mConnected = false;
SharedPreferences mPrefs;
SharedPreferences.Editor mEditor;
private TextView mText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mText = (TextView) findViewById(R.id.text);
mLocationRequest = LocationRequest.create();
mLocationRequest
.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest
.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
mUpdatesRequested = false;
mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES,
Context.MODE_PRIVATE);
mEditor = mPrefs.edit();
mLocationClient = new LocationClient(this, this, this);
}
@Override
public void onStart() {
super.onStart();
/*
* Connect the client. Don''t re-start any requests here; instead, wait
* for onResume()
*/
mLocationClient.connect();
}
@Override
protected void onResume() {
super.onResume();
// If the app already has a setting for getting location updates, get it
if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) {
mUpdatesRequested = mPrefs.getBoolean(
LocationUtils.KEY_UPDATES_REQUESTED, false);
// Otherwise, turn off location updates until requested
} else {
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
mEditor.commit();
}
}
@Override
public void onStop() {
// If the client is connected
if (mLocationClient.isConnected()) {
stopPeriodicUpdates();
}
// After disconnect() is called, the client is considered "dead".
mLocationClient.disconnect();
super.onStop();
}
@Override
public void onPause() {
// Save the current setting for updates
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED,
mUpdatesRequested);
mEditor.commit();
super.onPause();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void getLocation(View v) {
// If Google Play Services is available
if (isGooglePlayServicesAvailable()) {
if (!mConnected)
mText.setText("location client is not connected to service yet");
else {
// Get the current location
Location currentLocation = mLocationClient.getLastLocation();
// Display the current location in the UI
mText.setText(LocationUtils.getLocationString(currentLocation));
}
}
}
private boolean isGooglePlayServicesAvailable() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d(LocationUtils.APPTAG, "google play service is available");
// Continue
return true;
// Google Play services was not available for some reason
} else {
// Display an error dialog
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode,
this, 0);
if (dialog != null) {
Log.e(LocationUtils.APPTAG,
"google play service is unavailable");
}
return false;
}
}
private void stopPeriodicUpdates() {
mLocationClient.removeLocationUpdates(this);
// mConnectionState.setText(R.string.location_updates_stopped);
}
@Override
public void onConnectionFailed(ConnectionResult arg0) {
mConnected = false;
Log.d(LocationUtils.APPTAG, "connection failed");
}
@Override
public void onConnected(Bundle arg0) {
mConnected = true;
Log.d(LocationUtils.APPTAG,
"location client connected to the location server");
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0,
new android.location.LocationListener() {
@Override
public void onStatusChanged(String provider, int status,
Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onLocationChanged(final Location location) {
}
});
Log.d(LocationUtils.APPTAG, "done trying to get location");
}
@Override
public void onDisconnected() {
// TODO Auto-generated method stub
mConnected = false;
Log.d(LocationUtils.APPTAG,
"location client disconnected from the location server");
}
@Override
public void onLocationChanged(Location arg0) {}
}
la mayoría de ellos provienen de ejemplos dados por google. En el código anterior, hava intentado el método así:
LocationRequest request = LocationRequest.create();
request.setNumUpdates(1);
mLocationClient.requestLocationUpdates(request, this);
y
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0,
new android.location.LocationListener() {
@Override
public void onStatusChanged(String provider, int status,Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onLocationChanged(final Location location) {}
});
En onConnected()
antes de llamar a getLastLocation()
, pero todavía no recibes suerte. ¿Dónde está el error? Gracias de antemano.
Actualmente, el Fused Location Provider
solo mantendrá la ubicación de fondo si al menos un cliente está conectado a ella. Una vez que el primer cliente se conecta, inmediatamente intentará obtener una ubicación. Si su actividad es el primer cliente que se conecta y llama a getLastLocation()
inmediato en onConnected()
, puede que no sea suficiente tiempo para que onConnected()
la primera ubicación.
Corro y funciona perfectamente en el dispositivo Nexus 7. Ustedes, por error, escribieron la versión anterior LocationListener que no se usa con la nueva API.
Tienes que configurar el nuevo LocationListener.
Necesitas importar esta clase y luego probar.
import com.google.android.gms.location.LocationListener;
Y anula el único método según la nueva API
@Override
public void onLocationChanged(final Location newLocation)
{}
Por favor, intente de esta manera y avíseme si aún enfrenta algún problema.
Gracias.
Debe verificar si el usuario ha habilitado la ubicación a través de Wi-Fi / GSM o GPS. Si no hay ningún proveedor de ubicación disponible, obtienes null
.
Este código muestra la pantalla con la configuración de ubicación:
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
El problema también puede deberse a que su dispositivo no tiene habilitada la opción "Wi-Fi y ubicación de red móvil".
LocationClient (el proveedor de ubicación fusionada) usa tanto GPS como WiFi. El GPS tarda un rato en encontrar su ubicación, mientras que el wifi es mucho más rápido. Sin embargo, si alguno de estos 2 servicios está conectado, se llamará al método de devolución de llamada en Conectado. Y si intenta llamar a LocationClient.getLastLocation () en el método onConnected de inmediato, es muy probable que obtenga un valor nulo si su servicio de ubicación wifi está desactivado. Es solo porque el GPS simplemente no es lo suficientemente rápido.
Para resolver el problema por ti mismo localmente, habilita "Wi-Fi y ubicación de red móvil". Puede hacerlo yendo a "Configuración> Personal> Acceso a la ubicación> Wi-Fi y la ubicación de la red móvil".
Sin embargo, si desea resolver el problema para los usuarios de su aplicación, será mejor que compruebe si getLastLocation () devuelve null. Si lo hace, solicite a su usuario que habilite el servicio tal como lo hace google map.
Con suerte, eso ayuda.
Esta es la solución que funciona exactamente, probablemente en circunstancias ligeramente diferentes. Pero quería agregar algunos pequeños pasos de explicación para que cualquiera obtenga los conceptos exactos:
1) onCreate () del Componente Android (por ejemplo, Actividad , Fragmento o Servicio . Nota: Not IntentService ), compila y luego conecta el GoogleApiClient como se muestra a continuación.
buildGoogleApiClient();
mGoogleApiClient.connect();
donde, la implementación de buildGoogleApiClient () es,
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
Más adelante onDestroy (), puede desconectar GoogleApiClient como,
@Override
public void onDestroy() {
Log.i(TAG, "Service destroyed!");
mGoogleApiClient.disconnect();
super.onDestroy();
}
El paso 1 asegura que construye y conecta el GoogleApiClient.
1) La primera instancia de GoogleApiClient se conecta en el método onConnected (). Ahora, su próximo paso debería ser el método Connect ().
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.i(TAG, "GoogleApiClient connected!");
buildLocationSettingsRequest();
createLocationRequest();
location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Log.i(TAG, " Location: " + location); //may return **null** because, I can''t guarantee location has been changed immmediately
}
Arriba, llamó a un método createLocationRequest () para crear una solicitud de ubicación. El método createLocationRequest () se ve a continuación.
protected void createLocationRequest() {
//remove location updates so that it resets
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); //Import should not be **android.Location.LocationListener**
//import should be **import com.google.android.gms.location.LocationListener**;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
//restart location updates with the new interval
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
3) Ahora, en la retrollamada onLocationChange () de la interfaz LocationListener, obtienes una nueva ubicación.
@Override
public void onLocationChanged(Location location) {
Log.i(TAG, "Location Changed!");
Log.i(TAG, " Location: " + location); //I guarantee,I get the changed location here
}
Obtienes el resultado así en Logcat: 03-22 18: 34: 17.336 817-817 / com.LiveEarthquakesAlerts I / LocationTracker: Ubicación: Ubicación [fusionado 37.421998, -122.084000 acc = 20 et = + 15m35s840ms alt = 0.0]
Para poder hacer estos tres pasos, debe haber configurado su build.gradle de la siguiente manera:
compile ''com.google.android.gms:play-services-location:10.2.1''
Estaba enfrentando un problema similar.
Llame a mLocationClient.getLastLocation()
en onConnected
o después de que se haya establecido Connection to Google Play Services. Si llama a este método antes de que se conecte Location Client, la ubicación devuelta sería null
.
Puede verificar si el cliente de ubicación está conectado por mLocationClient.isConnected()
.
Espero que esto ayude.
La geolocalización del servicio Google play no puede funcionar sin conexión a Internet, de manera indiferente para el GPS. Por lo tanto, verifique la aplicación con los datos móviles encendidos.
La solución más fácil, aunque ralentiza un poco, es utilizar una función de ayuda. Mi problema era que se conectaría, pero antes de encontrar una ubicación, intentaría acceder a ella y presionar un puntero nulo.
public Location getLocation(LocationClient locationClient){
if(locationClient.getLastLocation() == null){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getLocation(locationClient);
}else{
return locationClient.getLastLocation();
}
}
Simplemente use esto en onConnected
y configure lo que quiera que la ubicación use con esta función, pasando su cliente de ubicación.
@Override
public void onConnected(Bundle dataBundle) {
Location temp = getLocation(mLocationClient);
mLocation = temp;
}
Además, si no desea obtener la ubicación de onConnected
por cualquier razón, puede usar la misma función auxiliar en cualquier lugar siempre que pase su locationClient
onConnected
.
Me enfrenté a problemas similares en mis pruebas con teléfonos Samsung (Android muy personalizado y sin soporte para desarrolladores).
LocationManager y LocationClient no obtienen el GPS de los proveedores. Deben ser kickstart cada vez que necesite la ubicación de ellos. Haga esto antes de las llamadas a LocationManager.getLastKnownLocation
O LocationClient.getLastLocation
. Estas API volverán.
YOUR_APPLICATION_CONTEXT.getLocationManager().requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0, 0, new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onLocationChanged(final Location location) {
}
});
También estaba enfrentando el mismo problema en mi aplicación, y lo único que faltaba era que la aplicación solo solicitaba ACCESS_COARSE_LOCATION y no ACCESS_FINE_LOCATION. Agregué el permiso posterior y todo funcionó bien.
Tuve el mismo problema al seguir las instrucciones del tutorial . En el teléfono funcionaba y en el emulador (Genymotion) no funcionaba.
Solución
En su AndroidManifest.xml, cambie esto:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
a esto:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
... y obtienes la ubicación de inmediato. No es necesario cambiar su código (para escuchar las actualizaciones de ubicación).
Solo necesita una solicitud de actualización para la ubicación. Si con 26 permiciones de Android SDK está bien:
private void setLocation(Context context) {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).build();
googleApiClient.connect();
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(2000);
locationRequest.setFastestInterval(2000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
showMessage(" All location settings are satisfied.");
mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this)
.addApi(LocationServices.API)
.addConnectionCallbacks(connectionCallbacks)
.addOnConnectionFailedListener(connectionFailedListener)
.build();
mGoogleApiClient.connect();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
l.a(" Location settings are not satisfied. Show the user a dialog to upgrade location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
showMessage("PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
showMessage("Location settings are inadequate, and cannot be fixed here. Dialog not created.");
break;
}
}
});
}
y en el método de devolución de llamada conectado:
@Override
public void onConnected(@Nullable Bundle bundle) {
l.a(3232);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if(null==mLastLocation){// !!!!!!!!!!!! here it can happen !!!!!!!
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
locationWasFound = true;
sevumPora.setLocation(mLastLocation);
mGoogleApiClient.disconnect();
}
});
return;
}
locationWasFound = true;
sevumPora.setLocation(mLastLocation);
mGoogleApiClient.disconnect();
}