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

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!
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.
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
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With