-1

Ciao! I have an Activity that needs the current location so an user can see which objects are close to him.

Well, I'm going to crazy with GoogleApiClient, FusedLocation, callbacks and so on and the only result I get is that getLastLocation returns null.

My Activity implements GoogleApiClient.ConnectionCallbacks and GoogleApiClient.OnConnectionFailedListener.

In OnCreate I call getLocation() that is like this:

private void getLocation(){
    locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(60*1000);
    locationRequest.setFastestInterval(10*1000);
    mFusedLocationApi = LocationServices.FusedLocationApi;
    gApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    if (gApiClient != null) {
        gApiClient.connect();
    }
}

I also have this:

@Override
protected void onStart() {
    super.onStart();
    if (gApiClient != null) {
        gApiClient.connect();
    }
}

@Override
protected void onStop() {
    gApiClient.disconnect();
    super.onStop();
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Log.w("ADVSEARCH","Error on connection failed");
}

@Override
public void onConnectionSuspended(int i) {
    Log.w("ADVSEARCH","Error on connection suspended");
}

@Override
public void onConnected(Bundle bundle) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

        //lastlocation = LocationServices.FusedLocationApi.getLastLocation(gApiClient);


        mFusedLocationApi.requestLocationUpdates(gApiClient, locationRequest, new com.google.android.gms.location.LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                lastlocation = location;
            }
        });
    }
    lastlocation = LocationServices.FusedLocationApi.getLastLocation(gApiClient);
}

And yes, in OnCreate I check for permissions. Minimum API 16, Target API 25. Every time I open the app the first time it crashes because I use distanceTo on a null object. What am I missing? The more I search, the more I get confused.

tuzzo
  • 75
  • 1
  • 1
  • 10
  • "Every time I open the app the first time it crashes because I use `distanceTo` on a null object" -- you are not using `distanceTo()` in your code listings in the question. – CommonsWare Nov 22 '17 at 19:16
  • @CommonsWare it's just a `distanceTo()` in a `clickListener`, there aren't other relevant lines. I only write the code about the location and I know that `lastLocation` is null because I log it before the `distanceTo()`. – tuzzo Nov 22 '17 at 19:33
  • 2
    Well, `getLastLocation()` can return `null`. You need to not attempt to use `lastlocation` until it is set, either by `getLastLocation()` or by `onLocationChanged()`. For example, you might disable that button until you get a non-`null` location. – CommonsWare Nov 22 '17 at 19:35

1 Answers1

1

I think it could be different thing e.g. you didn't set all stuff in the Manifest file or you have no permission at runtime (you need to allow this at first start of the App or you set this manually in the app settings). try this...

build.gradle

implementation 'com.google.android.gms:play-services-location:11.6.0'

in your Activity.java

private static final int PERMISSION_REQUEST_FINE_LOCATION = 1;

private void getLocationRequest() {
    FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this);
    if (!checkPermission()) {
        getLocationPermissions();
        return;
    }
    client.getLastLocation()
            .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                @Override
                public void onSuccess(Location location) {
                    // Got last known location. In some rare situations this can be null.
                    if (location != null) {
                        // Logic to handle location object
                        Log.e("TAG", "location = " + location);
                    } else {
                        Log.e("TAG", "not successful");
                    }
                }
            });
}

private boolean checkPermission() {
    return isGranted(ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)) &&
            isGranted(ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION));
}

@TargetApi(Build.VERSION_CODES.M)
private void getLocationPermissions() {
    requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION},
            PERMISSION_REQUEST_FINE_LOCATION);
}

@Override
public void onRequestPermissionsResult(int code, @Nullable String permissions[], @Nullable int[] results) {
    switch (code) {
        case PERMISSION_REQUEST_FINE_LOCATION:
            if (isPermissionGranted(results)) {
                getLocationRequest();
            }
    }
}

private boolean isPermissionGranted(int[] results) {
    return results != null && results.length > 0 && isGranted(results[0]);
}

private boolean isGranted(int permission) {
    return permission == PackageManager.PERMISSION_GRANTED;
}

This asks if you didn't have the permissions set yet and calls getLocationRequest again after a positive dialog result.

And check if you have this in your AndroidManifest.xml

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

<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.location.network" />

Of cause you have to fit to your needs (fine or coarse locations etc.).

Hope this gets you on track ;)

Peppermint Paddy
  • 1,269
  • 9
  • 14