Why is FusedLocationApi.getLastLocation null
Solution 1
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 storing 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..
Then you are setting mLocationRequest.setFastestInterval(30000);
which basically means 30 seconds. so at least 30 seconds after and generally according to your setting preferred time is 120 secs, isn't it a very long time if there is no stored last known location at all? plus you are setting battery balanced priority, which will make you waiting longer time.
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
I suggest you to launch Maps app first, so that there is at least some confirmed location and then test your app.
Solution 2
I am using FusedLocationProvider api in my app, Here is my code that works both on device and emulator -
@Override
protected void onCreate(Bundle savedInstanceState){
//put your code here
....
getLocation();
}
private void getLocation(){
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(LOCATION_INTERVAL);
locationRequest.setFastestInterval(LOCATION_INTERVAL);
fusedLocationProviderApi = LocationServices.FusedLocationApi;
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (googleApiClient != null) {
googleApiClient.connect();
}
}
@Override
public void onConnected(Bundle arg0) {
fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
@Override
public void onLocationChanged(Location location) {
Toast.makeText(mContext, "location :"+location.getLatitude()+" , "+location.getLongitude(), Toast.LENGTH_SHORT).show();
}
this is working code of mine.
Hope my code help you.
Cheers..
Solution 3
If it returns null, this means you need start receiving location updates with LocationServices.FusedLocationApi.requestLocationUpdates before retrieving the location.
For me, a solution to the problem was to call the:
LocationServices.FusedLocationApi.requestLocationUpdates(locationApiClient,locationRequest, this);
before the:
App.setLocation(LocationServices.FusedLocationApi.getLastLocation(locationApiClient));
The problem is that the last location does not exist so it was null.
If the problem persist try this:
Check the necessary permissions.
Ensure you've enabled position on your device, then restart.
Solution 4
I have used FusedAPI and Below code is working for me... Test in Real device
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Looper;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.PermissionChecker;
import android.widget.ProgressBar;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCanceledListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, ResultCallback<LocationSettingsResult> {
private static final int REQUEST_CHECK_SETTINGS = 214;
private static final int REQUEST_ENABLE_GPS = 516;
private final int REQUEST_LOCATION_PERMISSION = 214;
protected GoogleApiClient mGoogleApiClient;
protected LocationSettingsRequest mLocationSettingsRequest;
/* For Google Fused API */
private FusedLocationProviderClient mFusedLocationClient;
private SettingsClient mSettingsClient;
private LocationCallback mLocationCallback;
private LocationRequest mLocationRequest;
private Location mCurrentLocation;
/* For Google Fused API */
private Context context;
private ProgressBar progressBar;
private AsyncTask task;
private GoogleMap mMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
try {
int permissionCheck = PermissionChecker.checkCallingOrSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
Helper.showLog("Permission is already allowed. Build Client");
buildGoogleApiClient();
} else {
Helper.showLog("Permission is requested");
ActivityCompat.requestPermissions(MapsActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
protected synchronized void buildGoogleApiClient() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mSettingsClient = LocationServices.getSettingsClient(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
connectGoogleClient();
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
Helper.showLog("Location Received");
mCurrentLocation = locationResult.getLastLocation();
onLocationChanged(mCurrentLocation);
}
};
}
private void connectGoogleClient() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int resultCode = googleAPI.isGooglePlayServicesAvailable(this);
if (resultCode == ConnectionResult.SUCCESS) {
mGoogleApiClient.connect();
} else {
int REQUEST_GOOGLE_PLAY_SERVICE = 988;
googleAPI.getErrorDialog(this, resultCode, REQUEST_GOOGLE_PLAY_SERVICE);
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(30 * 1000);
mLocationRequest.setFastestInterval(5 * 1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
mLocationSettingsRequest = builder.build();
mSettingsClient
.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Helper.showLog("GPS Success");
requestLocationUpdate();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(MapsActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sie) {
Helper.showLog("PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Helper.showLog("Location settings are inadequate, and cannot be fixed here. Fix in Settings.");
}
}
}).addOnCanceledListener(new OnCanceledListener() {
@Override
public void onCanceled() {
Helper.showLog("checkLocationSettings -> onCanceled");
}
});
}
@Override
public void onConnectionSuspended(int i) {
connectGoogleClient();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
buildGoogleApiClient();
}
@Override
public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
}
@Override
public void onLocationChanged(Location location) {
String latitude = String.valueOf(location.getLatitude());
String longitude = String.valueOf(location.getLongitude());
if (latitude.equalsIgnoreCase("0.0") && longitude.equalsIgnoreCase("0.0")) {
requestLocationUpdate();
} else {
//Perform Your Task with LatLong
}
}
@SuppressLint("MissingPermission")
private void requestLocationUpdate() {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CHECK_SETTINGS) {
switch (resultCode) {
case Activity.RESULT_OK:
Helper.showLog("User allow to access location. Request Location Update");
requestLocationUpdate();
break;
case Activity.RESULT_CANCELED:
Helper.showLog("User denied to access location.");
openGpsEnableSetting();
break;
}
} else if (requestCode == REQUEST_ENABLE_GPS) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!isGpsEnabled) {
openGpsEnableSetting();
} else {
requestLocationUpdate();
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_LOCATION_PERMISSION) {
int permissionCheck = PermissionChecker.checkCallingOrSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
Helper.showLog("User Allowed Permission Build Google Client");
buildGoogleApiClient();
} else {
Helper.showLog("User Denied Permission");
}
}
}
private void openGpsEnableSetting() {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, REQUEST_ENABLE_GPS);
}
@Override
protected void onDestroy() {
//Remove location update callback here
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
super.onDestroy();
}
}
Helper Class
public class Helper {
public static void showLog(String message) {
Log.e("Ketan", "" + message);
}
public static void showToast(Context context, String message) {
Toast.makeText(context, "" + message, Toast.LENGTH_SHORT).show();
}
}
Solution 5
Probably, your problem is where you connect the client, I cannot test now, but as google doc shows in the example, you should connect the client in your onStart()
method in the activity.
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
For me, this make getLocation work
Related videos on Youtube
Can Poyrazoğlu
Has most experience in iOS programming and UI design. Loves astrophotography, board sports, feeding street animals, authoring his humble blog, and flying drones.
Updated on July 10, 2020Comments
-
Can Poyrazoğlu almost 4 years
I am trying to get location by using
FusedLocationApi.getLastLocation
and I've got the location permissions in the manifest file:<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
However, I am getting
null
when I request the location from the system. I was just testing turning off and on location services so it may be related to that (of course, it's ON when I'm trying this). But even after returning null, I'm waiting foronLocationChanged
to be called and it's never called. I've also seen a similar question here: FusedLocationApi.getLastLocation always nullHere is my code:
protected LocationRequest createLocationRequest() { LocationRequest mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(120000); mLocationRequest.setFastestInterval(30000); mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); return mLocationRequest; } protected GoogleApiClient getLocationApiClient(){ return new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } LocationRequest locationRequest = createLocationRequest(); @Override public void onLocationChanged(Location location) { App.setLocation(location); // NEVER CALLED } @Override public void onConnected(Bundle bundle) { App.setLocation(LocationServices.FusedLocationApi.getLastLocation(locationApiClient)); //RETURNS NULL LocationRequest locationRequest = createLocationRequest(); LocationServices.FusedLocationApi.requestLocationUpdates(locationApiClient, locationRequest, this); }
And on
onCreate
of my app:locationApiClient = getLocationApiClient(); locationApiClient.connect();
Where
this
is my application object. Why am I getting null (yes, I do know it may be null in some rare circumstances as stated in the documents, but I'm ALWAYS getting this, not rarely) and still not getting location updates thereafter? It's a real device (Samsung Galaxy S3) without a SIM card, if it helps.-
CommonsWare about 9 yearsThere are no
ACCESS_GPS
orACCESS_LOCATION
permissions in Android. Beyond that, it is very difficult to help you without code. -
Can Poyrazoğlu about 9 years@CommonsWare I don't know how I ended up that way, anyway, it shouldn't affect the behavior.
-
Amit K. Saha about 9 yearsare you testing on real device? besides documentation says, If client is not connected null will be returned. make sure your client is connected at all.
-
Borja Alvarez about 9 yearsCould you paste the code where you initialize api client and where you get null?
-
Napolean about 9 yearsfor avoiding null location try using both the providers GPS_PROVIDER and NETWORK_PROVIDER and hence add netwrok specific permissions
-
Can Poyrazoğlu about 9 years@AmitK.Saha yes, it's a real device, see my updated question.
-
Can Poyrazoğlu about 9 years@BorjaAlvarez updated the question.
-
Ravi Bhandari about 9 years@Can Poyrazoğlu hade you check my answer.YOu can also check it by seting LocationRequest.PRIORITY_HIGH_ACCURACY, because there may be no such app that geting location update in your device.
-
lagos over 8 yearsAny solution on this?
-
Haikal Nashuha over 7 years@lagos yes, just follow the first answer.
-
Subho about 7 yearsI request all of you please take a look at this answer stackoverflow.com/a/35833552/3278589
-
Saik Caskey almost 7 yearsthat answer is exactly the same crap that is all over this post. The question is not concerning location callbacks, the question is concerning FusedLocationProvider returning null for getLastLocation. I for one am seeing it say null, then report correctly, then report null again seconds later, on only some devices.
-
-
DJ_Polly almost 9 yearsNote that you need to implement GoogleApiClient.ConnectionCallbacks and com.google.android.gms.location.LocationListener
-
Mrigank over 8 yearsYou should disconnect the google api client before calling on the super method in OnStop() of your Activity class.
-
Alexey Strakh almost 8 yearsso what is the major difference with the author's code? Sequence of commands?
-
Can Poyrazoğlu over 7 yearsdon't you think I've tried all the possible combinations of location settings?
-
Haikal Nashuha over 7 years@AlexeyStrakh Yes. When the app starts the googleApiClient's lastLocation object was null. Consequently, calling last location on null object will return null, so the algorithm should be improved by first updating the location, then when googleApiClient acquired current location, you proceed by asking it. Be careful tho as if the location doesn't change, the onLocationChanged will not be triggered.
-
Ersen Osman about 7 yearsThis is correct, I had a similar issue a while back stackoverflow.com/q/35830987/4243687 The lastKnownLoction is simply a cached location. In fact, when other apps request a location, this location is then cached
-
Saik Caskey almost 7 yearsYou don't even use fusedLocationProviderApi ... the question is "Why is FusedLocationApi.getLastLocation null" not "how do I location updates without FusedLocationApil"
-
Saik Caskey almost 7 yearsThat doesn't come close to explaining why it is null
-
Saik Caskey almost 7 yearseveryone knows where the boilerplate code can be found.. the question was about why the provider would return null for last location
-
Uddhav P. Gautam almost 7 years1) If it GoogleApiClient doesn't find the Location object then it returns the null. It is a very obvious thing.
-
Saik Caskey almost 7 yearsThat is not a helpful response. Obviously OP wouldn't be asking if it was an obvious issue
-
Uddhav P. Gautam almost 7 years@SaikCaskey, mind your language man. This is absolutely not the boilerplate code that I found on the internet. I have developed a complex project and wrote the research paper. I put the snippet here. You might want to see my app, which uses FusedLocationProvider. play.google.com/store/apps/…. Further, there is onLocationChanged() callback, which can absolutely guarantee that you got the location. You can customize your location requests accordingly.
-
Saik Caskey almost 7 yearsWatch my language? :S You still aren't answering the question... added to that, how is this anything but boilerplate code? Just because you use it in your app or used it for a research paper doesn't mean it's yours, or that it's not very easy to find (ahem: developer.android.com/training/location/… .. your code is almost identical). You cannot absolutely guarantee that there will be a last location unless everything is working, the case where this is not the case is the case explored in this question
-
Uddhav P. Gautam almost 7 years@SaikCaskey, I guarantee there is last location inside onLocationChange() callback. It is absolutely zero change that onLocationChange() be called in Null location. And If onLocationChang() is giving new location in every my location request (which I can ask in every 2 seconds), I can guarantee I am getting my new location.
-
Uddhav P. Gautam almost 7 years@SaikCaskey, why the location is returning null, it depends on system. FocusedLocation Provider based on your current condition intelligently switches to various location providing systems (like GPS, Wifi, Internet .. etc). It is kind of very hard to exactly explain this. But I explained on how we can avoid NullPointerException.
-
Saik Caskey almost 7 years"It is absolutely zero change that onLocationChange() be called in Null location" - that is simply not relevant to the question actually (getLastLocation). The question "Why is FusedLocationApi.getLastLocation null" is not answered by "here's my code" and "here's how to avoid a null pointer". "it depends on system" is a much better answer, although it's exactly as useful to people experiencing the problem as "here's my code"
-
Uddhav P. Gautam almost 7 years@SaikCaskey, I said it clearly in my answer. I never said my answer is his exact answer. But it solves the issues in the practical world. I was stuck during that time when I wanted to solve my issues. Therefore, I thought providing exactly working code helps other developers. It is my trying man, you are welcome to like it.
-
Daniel O over 4 yearsI had same issue as OP but while using the emulator, after I manually set the device's location. Opening Maps in the emulator fixed this for me.
-
kaiya almost 2 yearsUninstalling is not necessary. Permissions can be modified during execution of applications.
-
kaiya almost 2 yearsThis doesn't answer the question of "Why is ...?"
-
kaiya almost 2 yearsThe answer contains only a guess and no explanation even though previous posts have already pointed out the problem.