update studio services received manager fused example current android geolocation location google-play-services

studio - location update android



FusedLocationApi.getLastLocation siempre nulo (9)

Aquí está la respuesta exacta y la explicación.

LocationClient getLastLocation () return null

Simplemente me gustaría recuperar la ubicación del dispositivo en mi proyecto de Android y para hacerlo utilizo el enfoque de servicios de reproducción:

protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder( MainSearchActivity.this ) .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { @Override public void onConnected( Bundle bundle ){ Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if( location == null ){ LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationListener() { @Override public void onLocationChanged(Location location) { lastLocation = location; } }); } } @Override public void onConnectionSuspended( int i ){ } }) .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() { @Override public void onConnectionFailed( ConnectionResult connectionResult ){ if( connectionResult.hasResolution() ){ try { // Start an Activity that tries to resolve the error connectionResult.startResolutionForResult(MainSearchActivity.this, CONNECTION_FAILURE_RESOLUTION_REQUEST); }catch( IntentSender.SendIntentException e ){ e.printStackTrace(); } }else{ Utils.logger("Location services connection failed with code " + connectionResult.getErrorCode(), Utils.LOG_DEBUG ); } } }) .addApi(LocationServices.API) .build(); mGoogleApiClient.connect(); } public Location retrieveLastLocation(){ Location loc = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if( loc == null) { } return loc; //TODO: What if loc is null? }

pero la variable loc SIEMPRE es nula. Es como tal en diferentes teléfonos, cada vez. También lastLocation, que trato de asignar en onLocationChanged, nunca cambia. Siempre nulo.

Estos son los permisos que configuré para la aplicación

<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="com.vogella.android.locationapi.maps.permission.MAPS_RECEIVE" /> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

Simplemente no lo entiendo: ¿por qué los LocationServices no pueden recuperar una posición? Tengo todas las configuraciones de geolocalización habilitadas en los tres dispositivos que probé: - /

Gracias por cualquier ayuda


Como se dijo en this publicación, el proveedor de ubicación fusionada solo mantendrá la ubicación en segundo plano si al menos un cliente está conectado a ella.

Pero no queremos iniciar la aplicación Maps para obtener la última ubicación, y tampoco podemos decir que nuestros usuarios inicien la aplicación Maps para obtener la última ubicación.

Lo que necesitamos hacer es

  1. Tenemos que solicitar la actualización de ubicación de FusedLocationProviderClient
  2. Entonces podemos obtener la última ubicación de FusedLocationProviderClient , no sería nulo.

Solicitar ubicación

LocationRequest mLocationRequest = LocationRequest.create(); mLocationRequest.setInterval(60000); mLocationRequest.setFastestInterval(5000); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); LocationCallback mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult == null) { return; } for (Location location : locationResult.getLocations()) { if (location != null) { //TODO: UI updates. } } } }; LocationServices.getFusedLocationProviderClient(context).requestLocationUpdates(mLocationRequest, mLocationCallback, null);

Obtener la última ubicación

LocationServices.getFusedLocationProviderClient(context).getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() { @Override public void onSuccess(Location location) { //TODO: UI updates. } });

Para obtener el mejor resultado en Inicio de la solicitud de Actividad para la actualización de ubicación, y luego puede obtener la última ubicación.


Creo que hay una pequeña falla que no es visible para mí en el código que se muestra.

mGoogleApiClient está construido pero parece no estar conectado. Puede verificar esto llamando a mGoogleApiClient.isConnected() .

Puede anular el método onStart y llamar a connect allí. O puede anular onResume() en caso de que desee acceder a la ubicación siempre que su actividad sea visible.

@Override protected void onStart() { super.onStart(); if (mGoogleApiClient != null) { mGoogleApiClient.connect(); } }


El Location Provider fusionado solo mantendrá la ubicación en segundo plano si al menos un cliente está conectado a él. Ahora, solo activar el servicio de ubicación no garantizará almacenar la última ubicación conocida.

Una vez que se conecta el primer cliente, inmediatamente intentará obtener una ubicación. Si su actividad es el primer cliente que se conecta y se invoca getLastLocation() inmediato en onConnected() , puede que no haya tiempo suficiente para que llegue la primera ubicación.

Le sugiero que inicie la aplicación Mapas primero, para que haya al menos alguna ubicación confirmada, y luego pruebe su aplicación.


Esto está relacionado con la respuesta de Amit K. Saha, pero para mí, en uno de mis dispositivos Lollipop seguía siendo null . Así que abrí la aplicación de mapas y obtuve la siguiente pantalla pidiéndome que active todo ese jazz para mejorar mi ubicación.

Una vez que lo hice una vez, mi dispositivo pudo recibir la ubicación con solo una llamada a getLastLocation() ;

Supongo que uno tendría que pedir estos permisos en la instalación de la aplicación para los usuarios que aún no hayan usado su aplicación de mapas.


Estoy usando el siguiente código para obtener la ubicación según la última documentación de Android https://developer.android.com/training/location/retrieve-current https://developer.android.com/training/location/receive-location-updates

MainActivity.java

public class MainActivity extends AppCompatActivity { private static final int REQUEST_CHECK_SETTINGS = 1; private static final int REQUEST_GRANT_PERMISSION = 2; private FusedLocationProviderClient fusedLocationClient; LocationRequest locationRequest; private Location currentLocation; private LocationCallback locationCallback; Button getUpdates,removeUpdates; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); createLocationRequest(); settingsCheck(); getUpdates = findViewById(R.id.button); removeUpdates = findViewById(R.id.button2); getUpdates.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_GRANT_PERMISSION); return; } if(locationCallback==null) buildLocationCallback(); if(currentLocation==null) fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper()); } }); removeUpdates.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_GRANT_PERMISSION); return; } if(locationCallback!=null) fusedLocationClient.removeLocationUpdates(locationCallback); } }); } protected void createLocationRequest() { locationRequest = LocationRequest.create(); locationRequest.setInterval(10000); locationRequest.setFastestInterval(5000); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); } // Check for location settings public void settingsCheck() { LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest); SettingsClient client = LocationServices.getSettingsClient(this); Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build()); task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() { @Override public void onSuccess(LocationSettingsResponse locationSettingsResponse) { // All location settings are satisfied. The client can initialize // location requests here. Log.d("TAG", "onSuccess: settingsCheck"); getCurrentLocation(); } }); 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. Log.d("TAG", "onFailure: settingsCheck"); 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. } } } }); } public void getCurrentLocation(){ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1); return; } fusedLocationClient.getLastLocation() .addOnSuccessListener(this, new OnSuccessListener<Location>() { @Override public void onSuccess(Location location) { Log.d("TAG", "onSuccess: getLastLocation"); // Got last known location. In some rare situations this can be null. if (location != null) { currentLocation=location; Log.d("TAG", "onSuccess:latitude "+location.getLatitude()); Log.d("TAG", "onSuccess:longitude "+location.getLongitude()); }else{ Log.d("TAG", "location is null"); buildLocationCallback(); } } }); } private void buildLocationCallback() { locationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult == null) { return; } for (Location location : locationResult.getLocations()) { // Update UI with location data currentLocation=location; Log.d("TAG", "onLocationResult: "+currentLocation.getLatitude()); } }; }; } //called after user responds to location permission popup @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode==REQUEST_GRANT_PERMISSION){ getCurrentLocation(); } } //called after user responds to location settings popup @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.d("TAG", "onActivityResult: "); if(requestCode==REQUEST_CHECK_SETTINGS && resultCode==RESULT_OK) getCurrentLocation(); if(requestCode==REQUEST_CHECK_SETTINGS && resultCode==RESULT_CANCELED) Toast.makeText(this, "Please enable Location settings...!!!", Toast.LENGTH_SHORT).show(); }}

Archivo XML

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.locationexample.MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="88dp" android:text="getLocationUpdates" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.502" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:text="RemoveLocationUpdates" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button" app:layout_constraintVertical_bias="0.363" /</android.support.constraint.ConstraintLayout>

Archivo de manifiesto

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.locationexample"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>


Primero, cree un objeto LocationRequest :

// Create the LocationRequest object mLocationRequest = LocationRequest.create() .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval(10 * 1000) // 10 seconds, in milliseconds .setFastestInterval(1 * 1000); // 1 second, in milliseconds

Luego, asegúrese de que el usuario haya otorgado permiso para usar la ubicación. Si es así, obtenga la ubicación de requestLocationUpdates siguiente manera:

void getLocation() { Location location = null; if (ContextCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1); /*TODO!! INSERT CODE TO PROMPT USER TO GIVE PERMISSION*/ } else { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } mLastLocation = location; LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this); }

Asegúrese de eliminar las actualizaciones si solo necesita una ubicación sin supervisión constante. De esta manera, nunca obtendrá una Location nula.

Para obtener más información, vaya a blog.teamtreehouse.com/beginners-guide-location-android .



Si getLastLocation () siempre devuelve nulo, intente este truco. Lo he usado para resolver mi problema. Implemente LocationListener (import com.google.android.gms.location.LocationListener) en su actividad.

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); Context mContext = this; manager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); createLocationRequest(); mGoogleApiClient = new GoogleApiClient.Builder(mContext) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); mGoogleApiClient.connect(); } private void createLocationRequest(){ mLocationRequest = LocationRequest.create(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mLocationRequest.setInterval(SET_INTERVAL); mLocationRequest.setFastestInterval(FASTEST_INTERVAL); }

onStart o onResume (prefiero onResume)

@Override protected void onResume() { super.onResume(); if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) ) { if (mGoogleApiClient != null) { mGoogleApiClient.connect(); } }else{ // Showyourmesg(); } } @Override protected void onPause() { super.onPause(); if (mGoogleApiClient != null) { mGoogleApiClient.disconnect(); } } protected void startLocationUpdates(){ LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest,this); } protected void stopLocationUpdates() { LocationServices.FusedLocationApi.removeLocationUpdates( mGoogleApiClient, this); }

Ahora, en su método onLocationChanged, verifique si googleApiClient está conectado o no. Si está conectado, desconéctelo y vuelva a conectarlo.

@Override public void onLocationChanged(Location location) { Log.d("SplashAct", "LocatinChngListner, loc: " + location.getLatitude() + "," + location.getLongitude()); if (mGoogleApiClient != null) if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()){ mGoogleApiClient.disconnect(); mGoogleApiClient.connect(); } else if (!mGoogleApiClient.isConnected()){ mGoogleApiClient.connect(); } }

Y finalmente, en su método onConntected ()

@Override public void onConnected(Bundle bundle) { Log.d("ACTIVITY", "ApiClient: OnConnected"); mLastLocation = LocationServices.FusedLocationApi.getLastLocation( mGoogleApiClient); if (mLastLocation == null){ startLocationUpdates(); // bind interface if your are not getting the lastlocation. or bind as per your requirement. } if (mLastLocation != null){ while (latitude == 0 || longitude == 0){ pDialog.setMessage("Getting Location"); pDialog.show(); latitude = mLastLocation.getLatitude(); longitude = mLastLocation.getLongitude(); if (latitude != 0 && longitude != 0){ stopLocationUpdates(); // unbind the locationlistner here or wherever you want as per your requirement. pDialog.dismiss(); // location data received, dismiss dialog, call your method or perform your task. } } } }

Intentamos conectarnos repetidamente con googleApiClient, incluso si ya está conectado, para que podamos obtener los datos de lastLocation. Esto dependerá de los intervalos de LocationRequest. También puede obtener los datos de ubicación en onLocationChanged y realizar su tarea desde allí.