9

I'm creating a location client at the moment, currently i have

 public void startUpdatingLocationProcess(Context context) {

     parentContext = context;

    if (mFusedLocationClient == null){
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(parentContext);

        LocationRequest mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        if (ContextCompat.checkSelfPermission(parentContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
        {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, new LocationCallback(){
                @Override
                public void onLocationResult(LocationResult locationResult) {

                    onLocationChanged(locationResult.getLastLocation());
                }

            } , Looper.myLooper());

         }


}

This is in a LocationApi class that i want to run throughout the applications lifecycle, this particular app runs many activities so i don't want to "recreate" the request every time i destroy and create a new activity.

The permission for FINE_LOCATION is allowed and checked, there are no errors in the logcat and the code runs the requestLocationUpdates method on creation of the mFusedLocationClient object, but it never calls the "onLocationResult" method.

Is there something i'm missing with using this api?

Brandon
  • 1,158
  • 3
  • 12
  • 22

3 Answers3

7

Before requesting location updates, your app must connect to location services and make a location request. Some thing like this:

private static LocationRequest createLocationRequest() {
    LogHelper.trace("createLocationRequest");
    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(200000);
    mLocationRequest.setFastestInterval(300000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    return mLocationRequest;
}

public static void checkLocationService(final Fragment fragment, final FusedLocationProviderClient client, final OnSuccessListener<LocationSettingsResponse> successListener, OnFailureListener failureListener) {

    LogHelper.trace("checkLocationService");
    final LocationRequest request = createLocationRequest();
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
            .addLocationRequest(request);

    SettingsClient settingsClient = LocationServices.getSettingsClient(fragment.getActivity());
    Task<LocationSettingsResponse> task = settingsClient.checkLocationSettings(builder.build());

    task.addOnSuccessListener(fragment.getActivity(), new OnSuccessListener<LocationSettingsResponse>() {
        @Override
        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
            LogHelper.trace("onSuccess");
            startLocationService(client, request, new LocationCallback());
            successListener.onSuccess(locationSettingsResponse);
        }
    });

    task.addOnFailureListener(fragment.getActivity(), failureListener);
}
No Body
  • 671
  • 5
  • 14
  • Hi! I've added in the connection to location services and make the request, i'm getting a response from the "OnFailureListener" stating - com.google.android.gms.common.api.ResolvableApiException: 6: RESOLUTION_REQUIRED i'm still looking into the error, i have a check for FINE_LOCATION before the method call and i have INTERNET permission in the manifest also, any idea why i would be getting this response? :) – Brandon Oct 01 '18 at 10:19
  • Hi! Sorry for the late response as i'm doing this at work, I found the issue for the failureListener being called, i didn't check my Location Settings on the device i was testing on. I am now getting through to the client.requestLocationUpdates(request, new LocationCallback(){ @Override public void onLocationResult(LocationResult locationResult) { onLocationChanged(locationResult.getLastLocation()); } } , Looper.myLooper()); – Brandon Oct 02 '18 at 01:17
  • but the onLocationResult is never being called, i have this wrappe in a permission check for ACCESS FINE LOCATION that it is passing but still no response – Brandon Oct 02 '18 at 01:17
  • After you made a location request and call requestLocationUpdates you must use client.getLastLocation() to get last location from google play service. The response may be null, if it is null you must call it again because it takes a few seconds to update. – No Body Oct 02 '18 at 04:56
  • So I swapped out devices and it worked, ran it on emulator and it worked, so the only problem was the actual tablet itself, and I’m not sure why, I used the emulator to mimic the android version and api version, all the same settings and versions worked for a mobile device and emulator, it just didn’t work on the tablet for some unknown reason :/ – Brandon Oct 02 '18 at 05:33
  • You can check GPS on your tablet. What is brand and model of your tablet? – No Body Oct 02 '18 at 06:23
  • I use the same code exactly and it is NOT working on my HTC M8 device. – Bahaa Salaheldin Nov 30 '18 at 03:26
  • 1
    What's the `client` used in parameters? And also what's the `startLocationService` method and where's the `successListener` ? – Mohamad Mousheimish Apr 19 '20 at 13:16
  • It hardly will work, because `onSuccess` is called, but `onLocationResult` isn't. – CoolMind Jan 20 '21 at 09:34
  • @MohamadMousheimish, I think, `startLocationService ` is `mFusedLocationClient.requestLocationUpdates` and listeners are `mFusedLocationClient.getLastLocation().addOnSuccessListener` and so on. – CoolMind Jan 20 '21 at 09:37
3

try to active/desactive location from android settings.

1

location == null.

See also LocationAvailability No Location Available. If you call

fusedLocationClient.getLocationAvailability()
    .addOnSuccessListener(this, locationAvailability -> {
    })

you will see that LocationAvailability[isLocationAvailable: false].

Probably it will happen because of an old emulator or

locationRequest = LocationRequest.create();
locationRequest
        .setNumUpdates(1)
        .setFastestInterval(0)
        .setSmallestDisplacement(0)

If you set setNumUpdates(1), it will return coordinate only one time and probably there will be null. I removed these lines and use

@SuppressLint("MissingPermission")
private fun startLocationUpdates() {
    fusedLocationProviderClient?.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
}

to start search location, then

locationCallback = object : LocationCallback() {
    override fun onLocationResult(locationResult: LocationResult?) {
        super.onLocationResult(locationResult)

        if (locationResult?.lastLocation == null) {
            Timber.d("Location missing in callback.")
        } else {
            Timber.d(
                "Location Callback ${locationResult.lastLocation}")
            latitude = locationResult.lastLocation.latitude
            longitude = locationResult.lastLocation.longitude
            stopLocationUpdates()
        }
    }
}

fusedLocationProviderClient?.lastLocation
    ?.addOnSuccessListener { location ->
        Timber.d("lastLocation success $location")
        if (location == null) {
            startLocationUpdates()
        } else {
            latitude = location.latitude
            longitude = location.longitude
        }
    }
    ?.addOnFailureListener { failure ->
        Timber.d("lastLocation failure ${failure.message}")
    }

to receive coordinate.

CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • I also saw my `onLocationResult` callback not being hit sometimes when I used `setNumUpdates`. After removing the call to `setNumUpdates`, my callback is always hit. – Adam Johns Jul 06 '21 at 21:45