3

When I first boot my app, it takes FusedLocationProviderClient up to 30 seconds to start providing location updates (i.e. up to 30 seconds before the blue dot shows up). I have a FusedLocationProvider that encapsulated in a LiveData as seen below and I'm trying to figure out what's wrong but can't.

public class LocationLiveData extends LiveData<Location> {

    private final static int LOCATION_REQUEST_INTERVAL_SECONDS = 5;
    private final static int MIN_DISPLACEMENT_REQUEST_METRES = 0;
    private final String TAG = this.getClass().getName();

    private final Context context;

    private FusedLocationProviderClient fusedLocationProviderClient = null;
    private LocationCallback locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            setValue(locationResult.getLastLocation());
        }
    };

    public LocationLiveData(Context context) {
        this.context = context;
    }

    @Override
    protected void onActive() {
        super.onActive();
        FusedLocationProviderClient locationProviderClient = getFusedLocationProviderClient();
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(TimeUnit.SECONDS.toMillis(LOCATION_REQUEST_INTERVAL_SECONDS));
        locationRequest.setSmallestDisplacement(MIN_DISPLACEMENT_REQUEST_METRES);
        locationProviderClient.requestLocationUpdates(locationRequest, locationCallback, null);
        Log.d(TAG, "Getting location...");
    }

    @NonNull
    private FusedLocationProviderClient getFusedLocationProviderClient() {
        if (fusedLocationProviderClient == null) {
            fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
        }
        return fusedLocationProviderClient;
    }

    @Override
    protected void onInactive() {
        if (fusedLocationProviderClient != null) {
            fusedLocationProviderClient.removeLocationUpdates(locationCallback);
        }
    }
}

Here is my fragment that holds another MapFragment and calls getMapAsync() on it. Here is the pertaining code:

  @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_map, viewGroup, false);

        mBinding.setView(this);

        mBinding.setViewModel(ViewModelProviders.of(this).get(MapsViewModel.class));

        FragmentManager fragmentManager = getChildFragmentManager();
        SupportMapFragment mapFragment = (SupportMapFragment) fragmentManager
                .findFragmentById(R.id.map_fragment);
        mapFragment.getMapAsync(this);

        return mBinding.getRoot();
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setMyLocationEnabled(true);
        mMap.getUiSettings().setMyLocationButtonEnabled(false);
        mMap.setInfoWindowAdapter(new InfoWindowAdapter(getLayoutInflater()));
        animateCameraToUserLocation();
    }
BeardMagician
  • 647
  • 13
  • 26
  • What is the value of `LOCATION_REQUEST_INTERVAL_SECONDS`. Is it 30? if yes then it may take 30 seconds to get your first location. TO get it sooner you can use `setFastestInterval` to lower than `LOCATION_REQUEST_INTERVAL_SECONDS` – NinjaCoder Nov 01 '17 at 20:06
  • Did you ever solve this? – Sunkas Apr 13 '22 at 11:19

2 Answers2

0

What you can do is before the gps location is retrieved you could used the cached location with getLastLocation() , this will give you the last known location and will be faster than waiting for gps signal and get the updated location, you can always put a timer and if in 5 seconds the location has not been fetched with the gps, you can use getLastLocation()

https://developer.android.com/training/location/retrieve-current.html#GetLocation

Gastón Saillén
  • 12,319
  • 5
  • 67
  • 77
0

An option could be retrying the operation, this was useful to me to get the location in background.

private suspend fun getLocation(context: Context): Location? {
    return suspendCoroutine { continuation ->
        try {
            if (!isLocationPermissionGranted(context)) {
                return@suspendCoroutine continuation.resume(null)
            }
            LocationServices.getFusedLocationProviderClient(context).run {
                var remainingTries = MAX_RETRIES_PER_LECTURE
                var location: Location? = null
                while (remainingTries > 0 && location == null) {
                    val locationTask = getCurrentLocation(priority, cancellationTokenSource.token)
                    location = Tasks.await(locationTask, 60, TimeUnit.SECONDS)
                    remainingTries--
                }
                continuation.resume(location)
            }
        } catch (e: Exception) {
            continuation.resumeWithException(e)
        }
    }
}
Jesús Barrera
  • 400
  • 1
  • 5
  • 15