44

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 for onLocationChanged to be called and it's never called. I've also seen a similar question here: FusedLocationApi.getLastLocation always null

Here 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.

Community
  • 1
  • 1
Can Poyrazoğlu
  • 33,241
  • 48
  • 191
  • 389
  • 3
    There are no `ACCESS_GPS` or `ACCESS_LOCATION` permissions in Android. Beyond that, it is very difficult to help you without code. – CommonsWare Apr 22 '15 at 11:42
  • @CommonsWare I don't know how I ended up that way, anyway, it shouldn't affect the behavior. – Can Poyrazoğlu Apr 22 '15 at 11:44
  • are 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. – Amit K. Saha Apr 22 '15 at 11:48
  • Could you paste the code where you initialize api client and where you get null? – Borja Alvarez Apr 22 '15 at 11:48
  • for avoiding null location try using both the providers GPS_PROVIDER and NETWORK_PROVIDER and hence add netwrok specific permissions – Napolean Apr 22 '15 at 12:05
  • @AmitK.Saha yes, it's a real device, see my updated question. – Can Poyrazoğlu Apr 22 '15 at 13:16
  • @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. – Ravi Bhandari Apr 23 '15 at 05:30
  • Any solution on this? – lagos Feb 15 '16 at 09:53
  • @lagos yes, just follow the first answer. – Haikal Nashuha Oct 28 '16 at 13:53
  • I request all of you please take a look at this answer http://stackoverflow.com/a/35833552/3278589 – Subho Feb 17 '17 at 13:51
  • 1
    that 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. – Saik Caskey Jun 20 '17 at 12:52

14 Answers14

20

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.

Jemshit
  • 9,501
  • 5
  • 69
  • 106
Amit K. Saha
  • 5,871
  • 2
  • 27
  • 35
  • I 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. – Daniel O Nov 15 '19 at 19:21
19

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..

Pei
  • 11,452
  • 5
  • 41
  • 45
Ravi Bhandari
  • 4,682
  • 8
  • 40
  • 68
  • 6
    Note that you need to implement GoogleApiClient.ConnectionCallbacks and com.google.android.gms.location.LocationListener – DJ_Polly Jun 21 '15 at 05:18
  • 1
    so what is the major difference with the author's code? Sequence of commands? – Mando Jul 30 '16 at 06:44
  • 2
    @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. – Haikal Nashuha Oct 28 '16 at 13:56
  • 3
    You don't even use fusedLocationProviderApi ... the question is "Why is FusedLocationApi.getLastLocation null" not "how do I location updates without FusedLocationApil" – Saik Caskey Jun 20 '17 at 12:44
5

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.

Iris Veriris
  • 448
  • 5
  • 7
  • 1
    This is correct, I had a similar issue a while back http://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 – Ersen Osman Feb 17 '17 at 16:47
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();
    }
}

May Help

Ketan Ramani
  • 4,874
  • 37
  • 42
3

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

Borja Alvarez
  • 189
  • 13
  • 7
    You should disconnect the google api client before calling on the super method in OnStop() of your Activity class. – Mrigank Jan 14 '16 at 03:15
2

With android APILEVEL above 23 you need some run time permissions. Location service ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION are also need permissions.

Checkout this documentation https://developer.android.com/training/permissions/requesting.html

Axe
  • 6,285
  • 3
  • 31
  • 38
1

I don't think that is a coding issue.

Seems that device location provider is having difficulties to pinpoint location on the proposed time, and locationChanged() method is never called.

Check the if the device configuration to location services isn't selected with a harder location mode (like GPS only).

If so, your code can't determine your location by GPS if you are indoor (as I guess you are). Pick the High Accuracy option and your problems will be solved.

amelvin
  • 8,919
  • 4
  • 38
  • 59
Renascienza
  • 1,647
  • 1
  • 13
  • 16
1

I found the solution.

I was testing my app on a phone with API 22 and it worked fine, however, on API 17 location kept returning null.

As it turns out, you have to allow your phone to use google location services. You can do it by going to Settings->Location Access->Check the "WLAN & mobile network location" (it might be called different in another API). Its' description is this:

Let apps use Google's location service to estimate your location faster. Anonymous location data will be collected and sent to Google.

By enabling it, I suddenly began to get much needed fused location data.

Hope this helps!

Starwave
  • 2,352
  • 2
  • 23
  • 30
1

This is the exact solution. But I wanted to add some little explanation steps so that anybody gets the exact concepts. Why it is returning null, I agree to follow Amit K answer. But, to guarantee on avoiding location NullPointerException, you start your location related processing inside onLocationChanged() callback.

1) onCreate() of Android Component (Eg, Activity, Fragment or Service. Note: Not IntentService), build and then connect the GoogleApiClient as below.

buildGoogleApiClient();
mGoogleApiClient.connect();

where, buildGoogleApiClient() implementation is,

protected synchronized void buildGoogleApiClient() {
        Log.i(TAG, "Building GoogleApiClient");

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

    }

Later on onDestroy(), you can disconnect GoogleApiClient as,

@Override
    public void onDestroy() {
        Log.i(TAG, "Service destroyed!");
        mGoogleApiClient.disconnect();
        super.onDestroy();
    }

The step 1 makes sure you build and connect the GoogleApiClient.

1) GoogleApiClient instance first time gets connected on method onConnected(). Now, your next step should look onConnected() method.

@Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.i(TAG, "GoogleApiClient connected!");
        buildLocationSettingsRequest();
        createLocationRequest();
        location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        Log.i(TAG, " Location: " + location); //may return **null** because, I can't guarantee location has been changed immmediately 
    }

Above, you called a method createLocationRequest() to create location request. The method createLocationRequest() looks like below.

protected void createLocationRequest() {
        //remove location updates so that it resets
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); //Import should not be **android.Location.LocationListener**
    //import should be **import com.google.android.gms.location.LocationListener**;

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        //restart location updates with the new interval
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

    }

3) Now, on onLocationChange() callback of LocationListener interface, you get new location.

@Override
    public void onLocationChanged(Location location) {
        Log.i(TAG, "Location Changed!");
        Log.i(TAG, " Location: " + location); //I guarantee of change of location here.


    }

You get the result like this in Logcat: 03-22 18:34:17.336 817-817/com.LiveEarthquakesAlerts I/LocationTracker: Location: Location[fused 37.421998,-122.084000 acc=20 et=+15m35s840ms alt=0.0]

Note: The location above got is Google Headquarter's location although I am in Arkansas. This happens when you use Emulator. On real device, it shows correct address.

To be able to do these three steps, you should have configured your build.gradle as below:

 compile 'com.google.android.gms:play-services-location:10.2.1'
Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64
  • 1
    everyone knows where the boilerplate code can be found.. the question was about why the provider would return null for last location – Saik Caskey Jun 20 '17 at 12:50
  • 1) If it GoogleApiClient doesn't find the Location object then it returns the null. It is a very obvious thing. – Uddhav P. Gautam Jun 21 '17 at 18:21
  • That is not a helpful response. Obviously OP wouldn't be asking if it was an obvious issue – Saik Caskey Jun 21 '17 at 19:02
  • @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. https://play.google.com/store/apps/details?id=com.LiveEarthquakesAlerts&hl=en. Further, there is onLocationChanged() callback, which can absolutely guarantee that you got the location. You can customize your location requests accordingly. – Uddhav P. Gautam Jul 25 '17 at 15:26
  • 3
    Watch 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: https://developer.android.com/training/location/change-location-settings.html .. 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 – Saik Caskey Jul 25 '17 at 15:33
  • @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 Jul 25 '17 at 15:43
  • @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. – Uddhav P. Gautam Jul 25 '17 at 15:47
  • 1
    "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" – Saik Caskey Jul 25 '17 at 15:55
  • @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. – Uddhav P. Gautam Jul 25 '17 at 15:56
0

I was facing the same issue. In my case, the problem was with allowing the permissions for the application. I had denied the FINE LOCATION permission that was asked when the first time app started.

Try uninstalling the app from your device and then redeploying it. It will again ask for the permission. Allow fine location access.

Worked in my case !!

Rishabh
  • 9
  • 2
  • Uninstalling is not necessary. Permissions can be modified during execution of applications. – kaiya Jun 22 '22 at 11:14
0

Try this,

    private static int UPDATE_INTERVAL = 10000; // 10 sec
    private static int FATEST_INTERVAL = 5000; // 5 sec
    private static int DISPLACEMENT = 10; // 10 meters


   private void createLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(UPDATE_INTERVAL);
    mLocationRequest.setFastestInterval(FATEST_INTERVAL);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
  }

 @Override
    public void onConnected(@Nullable Bundle bundle) {
        mLastLocation = LocationServices.FusedLocationApi
            .getLastLocation(mGoogleApiClient);
       if(mLastLocation == null){
           LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }
Kishan Vaghela
  • 7,678
  • 5
  • 42
  • 67
0

Check in your device whether you have enabled the location or not.

You can either enable it from Notification Panel or from Settings as:

Settings -> Personal -> Location

I have used only permission that is :

ACCESS_FINE_LOCATION

My working code is:

package com.go.findlocation;

import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

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

private GoogleApiClient mGoogleApiClient = null;
//private Location mLocation = null;
private LocationManager mLocationManager = null;
private LocationRequest mLocationRequest = null;

private TextView tv1 = null;
private TextView tv2 = null;

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

    mLocationRequest = new LocationRequest();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(10000);
    mLocationRequest.setFastestInterval(7000);
    mLocationRequest.setSmallestDisplacement(1);

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

    mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    tv1 = (TextView) findViewById(R.id.tv1);
    tv2 = (TextView) findViewById(R.id.tv2);
}

@Override
public void onConnected(@Nullable Bundle bundle) {

    Log.d("abc", "def");

    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    Log.d("ghi", "jkl");

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

    Log.d("connected", String.valueOf(mGoogleApiClient.isConnected()));

   /* if (mLocation != null) {
        tv1.setText(String.valueOf(mLocation.getLatitude()));
        tv2.setText(String.valueOf(mLocation.getLongitude()));
    } else
        Toast.makeText(this, "mLocation is null", Toast.LENGTH_SHORT).show();*/
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

@Override
protected void onStart() {

    mGoogleApiClient.connect();
    super.onStart();
}

@Override
protected void onStop() {

    if (mGoogleApiClient.isConnected())
        mGoogleApiClient.disconnect();
    super.onStop();
}

@Override
public void onLocationChanged(Location location) {

    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }

    Log.d("mno",String.valueOf(mGoogleApiClient.isConnected()));

if (location != null)
    {
        tv1.setText(String.valueOf(location.getLatitude()));
        tv2.setText(String.valueOf(location.getLongitude()));
        Toast.makeText(this, location.getLatitude()+" "+location.getLongitude(), Toast.LENGTH_SHORT).show();
    }
    else
        Toast.makeText(this, "location is null", Toast.LENGTH_SHORT).show();
}
}
Dhruvam Gupta
  • 482
  • 5
  • 10
-1

faced similar issue 30min ago, code was running before new simulator. After changing lat lng of simulator it started to work again

kemalony
  • 195
  • 1
  • 7
-1

I just made a discovery, maybe it will help some of you. I was getting null from getLastLocation() and it turns out it was because I tried to get the location with only the GPS turned on, but apparently you also have to have Wi-Fi turned on (even if not connected to any network). I am wondering if that's my device fault (Samsung tablet)... I am doing more digging into the topic but as for now nothing found. I would appreciate anyone sharing more knowledge about this issue.

laszlo
  • 494
  • 4
  • 18
  • The answer contains only a guess and no explanation even though previous posts have already pointed out the problem. – kaiya Jun 22 '22 at 11:17