Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does FusedLocationProviderClient leak memory?

in one of my activity, I am using the FusedLocationProviderClient to get constant location update. My codes are based on this method: https://developer.android.com/training/location/receive-location-updates

In my onCreate, I setup the provider and callbacks

// setup fused location provider
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);

    // build location request
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(30000);
    mLocationRequest.setFastestInterval(10000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setSmallestDisplacement(50);

    // Setup the callback function.
    mLocationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            if (locationResult == null) {
                return;
            }
            for (Location location : locationResult.getLocations()) {
                // Update UI with location data
                // ...

                mCurrentLocation = location;
            }
        }
    };

In onResume

mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest,
                                mLocationCallback,
                                Looper.myLooper());

In onPause

mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback);

Yet for some reason, leak canary is still indicating that there's memory leak. Leak canary log shown below enter image description here

Browsing around stack overflow, there are posts that seems to suggest that the leak is due to google play service. But those post were talking about fusedLocationApi, while I'm using the fusedLocationProviderClient, so I'm not sure if its the same thing as what I am using here. Can some one confirm for me ? Thank you!

like image 331
Chao Li Avatar asked Nov 05 '25 13:11

Chao Li


2 Answers

I have fixed the leaks reported by LeakCanary by passing SoftReference of the LocationCallback to the FusedLocationProvider.

public class LocationCallbackReference extends LocationCallback {

    private final SoftReference<LocationCallback> mLocationCallbackRef;

    public LocationCallbackReference(LocationCallback locationCallback) {
        mLocationCallbackRef = new SoftReference<>(locationCallback);
    }

    @Override
    public void onLocationResult(LocationResult locationResult) {
        super.onLocationResult(locationResult);
        if (mLocationCallbackRef.get() != null) {
            mLocationCallbackRef.get().onLocationResult(locationResult);
        }
    }

    @Override
    public void onLocationAvailability(LocationAvailability locationAvailability) {
        super.onLocationAvailability(locationAvailability);
        if (mLocationCallbackRef.get() != null) {
            mLocationCallbackRef.get().onLocationAvailability(locationAvailability);
        }
    }
}

I hope that helps.

like image 103
Marcin Sielski Avatar answered Nov 07 '25 01:11

Marcin Sielski


For me, I was using LocationCallback as an inner anonymous object (because I have to update/access the enclosing class data) & FusedLocationProviderClient was causing the memory leak.

Then I refactor the inner class to static(non-inner) class & update the enclosing class data via live data passed to static LocationCallback object.

import android.app.Activity
import androidx.lifecycle.MutableLiveData
import com.google.android.gms.location.*


class LocationUtility constructor(private val activity: Activity) {


private var mLocationRequest: LocationRequest? = null
private var fusedLocationProviderClient: FusedLocationProviderClient? = null

var currentLocation = MutableLiveData<Pair<Double?, Double?>>()

private var myLocationCallback: MyLocationCallback? = null


init {
    fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity)
    myLocationCallback = MyLocationCallback(currentLocation)
}



// Location call back
private class MyLocationCallback(val liveData: MutableLiveData<Pair<Double?, Double?>>) :
    LocationCallback() {

    override fun onLocationResult(locationResult: LocationResult?) {
        super.onLocationResult(locationResult)

        val latitude = locationResult?.locations?.get(0)?.latitude
        val longitude = locationResult?.locations?.get(0)?.longitude

        val locationInfo = Pair(latitude, longitude)
        liveData.value = locationInfo
    }
}

}

like image 28
Muhammad Maqsood Avatar answered Nov 07 '25 02:11

Muhammad Maqsood



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!