0

I am using the following functions for opening up a Settings API dialog to enable the user to turn on location services and then access the current location of the user:

 public void onConnected(Bundle bundle) {

    if(ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED) {
        googleMapGlobal.setMyLocationEnabled(true);
        Location mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
        if (mCurrentLocation == null) {
           // Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            //getApplicationContext().startActivity(intent);
            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);
            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();
                    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(VendorsOnMap.this, 1000);
                            } 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;
                    }
                }
            });
        } else {
            CameraPosition position = CameraPosition.builder()
                    .target(new LatLng(mCurrentLocation.getLatitude(),
                            mCurrentLocation.getLongitude()))
                    .zoom(15f)
                    .bearing(0.0f)
                    .tilt(0.0f)
                    .build();
            googleMapGlobal.animateCamera(CameraUpdateFactory
                    .newCameraPosition(position), null);
            LatLng latLng = new LatLng(31.220, 75.750);
            Toast.makeText(getApplicationContext(), mCurrentLocation.getLatitude() + ", " + mCurrentLocation.getLongitude(), Toast.LENGTH_LONG).show();
            googleMapGlobal.addMarker(new MarkerOptions().position(latLng).title("Marker here"));
        }
    }
    else{
        ActivityCompat.requestPermissions(getParent(),
                new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSION_ACCESS_FINE_LOCATION);
    }

}


protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    final LocationSettingsStates states = LocationSettingsStates.fromIntent(intent);
    if (ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        {
            Toast.makeText(getApplicationContext(), resultCode + " " + Activity.RESULT_OK, Toast.LENGTH_SHORT).show();
            switch (requestCode) {
                case 1000:
                    switch (resultCode) {
                        case Activity.RESULT_OK:
                            googleMapGlobal.setMyLocationEnabled(true);
                            Location mCurrentLocation;
                            mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
                            CameraPosition position = CameraPosition.builder()
                                    .target(new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()))
                                    .zoom(15f)
                                    .bearing(0.0f)
                                    .tilt(0.0f)
                                    .build();
                            googleMapGlobal.animateCamera(CameraUpdateFactory.newCameraPosition(position), null);
                            LatLng latLng = new LatLng(31.220, 75.750);
                            Toast.makeText(getApplicationContext(), mCurrentLocation.getLatitude() + ", " + mCurrentLocation.getLongitude(), Toast.LENGTH_LONG).show();
                            googleMapGlobal.addMarker(new MarkerOptions().position(latLng).title("Marker here"));
                            break;
                        case Activity.RESULT_CANCELED:
                            break;
                        default:
                            break;
                    }
                    break;
            }
        }
    }
}

The problem is when I use the app by turning the location on, it runs absolutely fine but if I turn on the location from the Settings API dialog from within the app, the location returned is null. Please help.

Karan Dua
  • 45
  • 5
  • http://stackoverflow.com/questions/31521849/getlastlocation-returns-a-null-value – Daniel Nugent Feb 10 '16 at 17:22
  • @DanielNugent The link you gave shows location to be returned null everytime, but it my case it happens only when the location services are turned on from within the app (Settings API Dialog). – Karan Dua Feb 10 '16 at 17:36
  • What you're seeing is expected behavior for this use case. There is not enough time for another app to request a location between the time that you enable services and when you try to get a location. You should never rely on getLastLocation(), as it can and will return null often. – Daniel Nugent Feb 10 '16 at 17:39
  • Be sure to read the answers/comments here: http://stackoverflow.com/questions/16830047/locationclient-getlastlocation-return-null – Daniel Nugent Feb 10 '16 at 17:41

1 Answers1

-1

Got it to working. I was making a basic mistake in understanding how getLastLocation() works. It actually seeks the location received by the system and not the app. This is my modified code. I have now used the Settings API Dialog to enable the user to turn on location services but before that I made a call to requestLocationUpdates() to allow my app to request location updates. Then I called the getLastLocation() in an infinite loop till the value returned by it is not null. This way I got the current location of the device.

public void onConnected(Bundle bundle) {

    if(ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED) {
        googleMapGlobal.setMyLocationEnabled(true);
        locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(0);
        locationRequest.setFastestInterval(5 * 1000);
        locationRequest.setNumUpdates(5);
        LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
           // Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            //getApplicationContext().startActivity(intent);
            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();
                    final LocationSettingsStates state = result.getLocationSettingsStates();
                    switch (status.getStatusCode()) {
                        case LocationSettingsStatusCodes.SUCCESS:
                            // All location settings are satisfied. The client can initialize location
                            // requests here.
                            while(mCurrentLocation==null) {
                                if(ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED)
                                    mCurrentLocation=LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
                            }
                            CameraPosition position = CameraPosition.builder()
                                    .target(new LatLng(mCurrentLocation.getLatitude(),
                                            mCurrentLocation.getLongitude()))
                                    .zoom(15f)
                                    .bearing(0.0f)
                                    .tilt(0.0f)
                                    .build();
                            googleMapGlobal.animateCamera(CameraUpdateFactory
                                    .newCameraPosition(position), null);
                            LatLng latLng = new LatLng(31.220, 75.750);
                            Toast.makeText(getApplicationContext(), mCurrentLocation.getLatitude() + ", " + mCurrentLocation.getLongitude(), Toast.LENGTH_LONG).show();
                            googleMapGlobal.addMarker(new MarkerOptions().position(latLng).title("Marker 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(VendorsOnMap.this, 1000);
                            } 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;
                    }
                }
            });


    }
    else{
        ActivityCompat.requestPermissions(getParent(),
                new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSION_ACCESS_FINE_LOCATION);
    }

}


protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    final LocationSettingsStates states = LocationSettingsStates.fromIntent(intent);
    if (ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        {
            Toast.makeText(getApplicationContext(), resultCode + " " + Activity.RESULT_OK, Toast.LENGTH_SHORT).show();
            switch (requestCode) {
                case 1000:
                    switch (resultCode) {
                        case Activity.RESULT_OK:
                            while (mCurrentLocation==null){
                                mCurrentLocation=LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
                            }
                            CameraPosition position = CameraPosition.builder()
                                    .target(new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()))
                                    .zoom(15f)
                                    .bearing(0.0f)
                                    .tilt(0.0f)
                                    .build();

                            googleMapGlobal.animateCamera(CameraUpdateFactory.newCameraPosition(position), null);
                            LatLng latLng = new LatLng(31.220, 75.750);
                            Toast.makeText(getApplicationContext(), mCurrentLocation.getLatitude() + ", " + mCurrentLocation.getLongitude(), Toast.LENGTH_LONG).show();
                            googleMapGlobal.addMarker(new MarkerOptions().position(latLng).title("Marker here"));
                            break;
                        case Activity.RESULT_CANCELED:
                            break;
                        default:
                            break;
                    }
                    break;
            }
        }
    }

Here mCurrentLocation is a global variable of Location type.

Karan Dua
  • 45
  • 5
  • 2
    Infinite loop on the main thread? NOT good. Your code right now would freeze your entire app, and throw an ANR if you don't get a location right away (which could happen for many reasons) The correct way would be to call `requestLocationUpdates()` in `onResult()`, and get the location from `onLocationChanged()`. You can call `getLastLocation()` once, if the location is not null, use it. Otherwise, call `requestLocationUpdates()`, and process the Location once you get one in 'onLocationChanged()' – Daniel Nugent Feb 10 '16 at 21:45
  • Yeah! Sorry for that! My bad for placing while loop in UI thread. I did the same task by placing the infinite loop in AsyncTask which doesn't freezes the UI and does my job as well. – Karan Dua May 23 '16 at 17:17