Locationclient Getlastlocation() Return Null

LocationClient getLastLocation() return null

Currently the Fused Location Provider will only maintain background location if at least one client is connected to it. Once the first client connects, it will immediately try to get a location. If your activity is the first client to connect and you call getLastLocation() right away in onConnected(), that might not be enough time for the first location to come in.

Play Location Services getLastLocation returns null

First

It's kind of bug on old Android devices.

Apparently the location APIs have different behavior on different Android versions (LocationManager has issues on Android >= 4.1, while Play Services has issues on Android 2.3), see here.

So what I ended up with is below:

Trying to retrieve last location by play services, if failed try with LocationManager.

Second

I would like to thank you all for your valuable suggestions, I get the hint to use the previous workaround from AndroidHacker's post so I think he is the one who deserve the bounty.

LocationClient getLastLocation() returning null

mLocationClient.getLastLocation(); might return null if you don't have any last location saved by the device. If you read its documentation, it says;

It returns the best most recent location currently available.
If a location is not available, which should happen very rarely, null will be returned

Also inside the onLocationChanged method you might want to set the Location to the latest location, when your location gets changed.

@Override
public void onLocationChanged(final Location location) {
mCurrentLocation = location;
}

locationclient.getlastlocation() always returns null on emulator

What eventually worked for me was setting a location (I use Genymotion, so the "GPS widget" in the upper right corner), then starting Google Maps, and then running my app.

My guess is that my app wasn't actually setting the current location (which I thought connecting my locationClient would do automatically) - Google Maps checks and sets the location, so getLastLocation actually has something to return.

getLastLocation() return null after moving code

The flow should be:

  1. Add location permission in AndroidManifest.xml
  2. Check if user has given that permission, if yes, check location settings; and of not then first ask for permission
  3. If permission is granted and location settings are ON, then you should do what you want.

In your case, from the code you've shown, you are not checking location settings and just after requesting permission, you are trying to getLastLocation() which should be inside of if statement when permission is granted and when permission is granted in onRequestPermissionsResult()

EDIT:
Add/Change the following code:

1.

protected void createLocationRequest() {
if (mLocationRequest == null) {
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
}
}

2.

private void checkLocationSettings() {

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);

final Task<LocationSettingsResponse> result =
LocationServices.getSettingsClient(MapsActivity.this).checkLocationSettings(builder.build());

result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
@Override
public void onComplete(@NonNull Task<LocationSettingsResponse> task) {

Log.e(TAG, "onComplete() called with: task = [" + task.isComplete() + "]");
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
getLastKnownLocation(mFusedLocationClient);
}
});


result.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(TAG, "onFailure() called with: e = [" + e + "]");
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MapsActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.e("MapsActivity", "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");
getLastKnownLocation(mFusedLocationClient);
}


public void getLastKnownLocation(FusedLocationProviderClient cl) {
// Get last location
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
Log.e(TAG, "onSuccess() called with: location = [" + location + "]");
// Got last known location. In some rare situations this can be null.
if (location != null) {
longitude = location.getLongitude();
latitude = location.getLatitude();
Log.e("MapsActivity", "onSuccess() called with: location = [" + location + "]");
LatLng mCurrentLocation = new LatLng(latitude, longitude);
mMap.addMarker(new MarkerOptions().position(mCurrentLocation).title("Current position"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(mCurrentLocation));

// Set zoom level
mMap.animateCamera(CameraUpdateFactory.zoomTo(19.0f));
Toast.makeText(getApplicationContext(), "value is " + latitude + "poi" + longitude, Toast.LENGTH_LONG).show();
}
}
});
}



@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MY_PERMISSION_FINE_LOCATION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
createLocationRequest();
checkLocationSettings();
} else {
Toast.makeText(getApplicationContext(), "This app requires location permission to be granted", Toast.LENGTH_LONG).show();
finish();
}
break;


}

  1. And only this code related to location in onMapReady():

    // Check if localization permission is granted
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
    == PackageManager.PERMISSION_GRANTED
    && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
    == PackageManager.PERMISSION_GRANTED) {
    mMap.setMyLocationEnabled(true);
    createLocationRequest();
    checkLocationSettings();


    } else {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    ActivityCompat.requestPermissions(this
    , new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}
    , MY_PERMISSION_FINE_LOCATION);
    }
    }

Make sure you have both below permissions in manifest:

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

FusedLocationApi.getLastLocation always null

The fused Location Provider will only maintain background location if at least one client is connected to it. Now just turning on the location service will not guarantee to store the last known location.

Once the first client connects, it will immediately try to get a location. If your activity is the first client to connect and getLastLocation() is invoked right away in onConnected(), that might not be enough time for the first location to arrive..

I suggest you to launch the Maps app first, so that there is at least some confirmed location, and then test your app.

getLastLocation returns a null value

getLastLocation() has a high tendency to return null. It also does not request a new location, so even if you get a location, it could be very old, and not reflect the current location. Better to register a listener, even if you just unregister after you get the first onLocationChanged() callback.

This question gets asked a lot, and usually is marked as a duplicate of questions like this one

However, in your case, it also looks like you just forgot to call connect():

 buildGoogleApiClient();
mGoogleApiClient.connect(); //added

You can use the code in this answer as a reference for registering for location callbacks, which is suggested if you want to get an accurate current location.

Edit: Since you need only one location, here is a slightly modified version of that code, which requests location updates, and then un-registers for location updates after the first location comes in.

public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {

LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
private double mLatitude;
private double mLongitude;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

buildGoogleApiClient();
mGoogleApiClient.connect();
}

@Override
protected void onPause(){
super.onPause();
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}

protected synchronized void buildGoogleApiClient() {

mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}

@Override
public void onConnected(Bundle bundle) {

mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

//mLocationRequest.setSmallestDisplacement(0.1F);

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}

@Override
public void onConnectionSuspended(int i) {
Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
}

@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
//no need to do a null check here:
mLatitude = location.getLatitude();
mLongitude = location.getLongitude();

//remove location updates if you just need one location:
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
}


Related Topics



Leave a reply



Submit