La ubicación de Android regresa nula después de habilitar el GPS en el diálogo

Cuando entro en una pantalla, compruebo si el GPS está activado, si no, se muestra el cuadro de diálogo para habilitar el GPS. Cuando el usuario hace clic en Sí, onActivityResult -> GPS está activado e bash obtener la ubicación, pero esto siempre devuelve nulo

Cuando entro en la pantalla con el GPS ya activado, la ubicación se recupera correctamente. He estado luchando con esto durante unos días y parece que no puedo encontrar ningún recurso.

UserLocationUtilities.java

public class UserLocationUtilities implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener{ GoogleApiClient googleApiClient; Activity activity; protected static final int REQUEST_CHECK_SETTINGS = 0x1; boolean isGPSEnabled = false; // flag for network status boolean isNetworkEnabled = false; // flag for GPS status boolean canGetLocation = false; protected LocationManager locationManager; protected LocationListener locationListener; protected Location location; protected double latitude,longitude; protected boolean gps_enabled,network_enabled; // The minimum distance to change Updates in meters private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters // The minimum time between updates in milliseconds private static final long MIN_TIME_BW_UPDATES = 1 * 1000 * 60; // 1 minute public UserLocationUtilities(Activity activity){ this.activity = activity; } public void settingsRequest() { if(googleApiClient == null){ googleApiClient = new GoogleApiClient.Builder(activity) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this).build(); googleApiClient.connect(); } LocationRequest locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationRequest.setInterval(30 * 1000); locationRequest.setFastestInterval(5 * 1000); LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest); builder.setAlwaysShow(true); //this is the key ingredient PendingResult result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build()); result.setResultCallback(new ResultCallback() { @Override public void onResult(LocationSettingsResult result) { final Status status = result.getStatus(); final LocationSettingsStates state = result.getLocationSettingsStates(); switch (status.getStatusCode()) { case LocationSettingsStatusCodes.SUCCESS: // All location settings are satisfied. The client can initialize location // requests here. break; case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: // Location settings are not satisfied. But could be fixed by showing the user // a dialog. try { // Show the dialog by calling startResolutionForResult(), // and check the result in onActivityResult(). status.startResolutionForResult(activity, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException e) { // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings are not satisfied. However, we have no way to fix the // settings so we won't show the dialog. break; } } }); } public Location getLocation() { if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { try { locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE); isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); if (!isGPSEnabled && !isNetworkEnabled) { // no network provider is enabled } else { this.canGetLocation = true; if (isNetworkEnabled) { locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("Network", "Network"); if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } } } // if GPS Enabled get lat/long using GPS Services if (isGPSEnabled) { if (location == null) { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("GPS Enabled", "GPS Enabled"); if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } } } } } } catch (Exception e) { e.printStackTrace(); } } return location; } public boolean isLocationEnabled() { int locationMode = 0; String locationProviders; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ try { locationMode = Settings.Secure.getInt(activity.getApplicationContext().getContentResolver(), Settings.Secure.LOCATION_MODE); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } return locationMode != Settings.Secure.LOCATION_MODE_OFF; }else{ locationProviders = Settings.Secure.getString(activity.getApplicationContext().getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED); return !TextUtils.isEmpty(locationProviders); } } @Override public void onConnected(Bundle bundle) { } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } @Override public void onLocationChanged(Location location) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } } 

Después de que el usuario selecciona Sí en el cuadro de diálogo Configuración, en ActivoResultado, hago location = userlocationutilities.getLocation (); Y siempre devuelve nulo. Si cambia de pantalla y vuelve, se recupera la ubicación.

 @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { // Check for the integer request code originally supplied to startResolutionForResult(). case REQUEST_CHECK_SETTINGS: switch (resultCode) { case Activity.RESULT_OK: //location settings dialog, user selected YES to enabling location location = userLocationUtilities.getLocation(); if(location != null){ //location of user FOUND Toast.makeText(getActivity(), "Lat: "+location.getLatitude()+" Long: "+location.getLongitude(), Toast.LENGTH_LONG).show(); getRingsNearMeCall(); }else{ //location of user NOT FOUND Toast.makeText(getActivity(), "null location", Toast.LENGTH_LONG).show(); } break; case Activity.RESULT_CANCELED: //location settings dialog, user selected NO to enabling location userLocationUtilities.settingsRequest(); //ask user again with Location Settings Dialog break; } break; } } 

Editted: hago el requestPermission en el fragmento, se concede el permiso

 if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(getActivity(), new String[] { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }, PERMISSION_ACCESS_FINE_LOCATION); }else{ checkLocationSettingsGetRings(); } 

Finalmente, encuentro una solución: creo un subproceso y espero mi ubicación disponible.

 @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode){ case REQUEST_LOCATION: switch (resultCode){ case Activity.RESULT_OK: mHandler = new Handler(); runnable = new Runnable() { @Override public void run() { mHandler.postDelayed(this,1000); checkLocationAvailable(); } }; mHandler.postDelayed(runnable,1000); break; case Activity.RESULT_CANCELED: break; } } } 

Crear una función para detener el hilo cuando mi ubicación esté disponible.

 private void checkLocationAvailable(){ if (mMap.getMyLocation() != null) { mHandler.removeCallbacks(runnable); // do stuff } } 

No es una buena solución, pero espero que ayude.

Añadir este método de anulación para mí su trabajo bien–

@Override public void onLocationChanged(Location location) { getLocation("onLocationChanged"); }

LocationSettingsRequest se usa solo para que la configuración de la ubicación sea adecuada, por ejemplo, si desea recibir ubicaciones más precisas (HIGH_ACCURACY), entonces necesita que el GPS esté activado. Entonces, en ese caso, LocationSettingsRequest solicita al diálogo que permita la configuración de cambio de API.

Después de presionar OK, puede ver que el GPS está habilitado. Pero esto no significa que se le haya otorgado para realizar una solicitud de ubicación todavía.

 @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CHECK_SETTINGS: switch (resultCode) { case Activity.RESULT_OK: // Here means required settings are adequate. // We can make location request. // But are we granted to use request location updates ? break; } break; } } } 

Eso está bien, pero está verificando el permiso, pero nunca hizo pedidos de solicitud de permisos . Esta es la primera razón posible de ser nulo.

 public Location getLocation() { if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { ... } return location; } 

Incluso se le ha concedido previamente para hacer solicitud de ubicación

  location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 

El método getLastKnownLocation () podría devolver nulo, esto no es un comportamiento inesperado. Esta es la segunda razón posible de ser nulo.

Está realizando una solicitud de ubicación, pero la variable de ubicación global nunca se asigna en la callback onLocationChanged.

  @Override public void onLocationChanged(Location location) { // global location variable is not assigned ? // getLocation() method will return null if getLastKnownLocation() // did not return null previously. } 

Esta es la tercera razón posible de ser nulo.