I am using fused location api to find the current location in the fragment, sometimes getting a memory leak
How to fix this issue?
com.android.zigmaster.ui.home.FragmentSearch instance
Leaking: YES (ObjectWatcher was watching this because com.android.zigmaster.ui.home.FragmentSearch received
Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
====================================
HEAP ANALYSIS RESULT
====================================
2 APPLICATION LEAKS
References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.
4982 bytes retained by leaking objects
Signature: e3580ed78ace0bf62b73fb0e3e2c66f15be575a
┬───
│ GC Root: Global variable in native code
│
├─ com.google.android.gms.location.zzam instance
│ Leaking: UNKNOWN
│ Retaining 756 B in 13 objects
│ ↓ zzam.zza
│ ~~~
├─ com.google.android.gms.location.zzx instance
│ Leaking: UNKNOWN
│ Retaining 153 B in 7 objects
│ ↓ zzx.zzc
│ ~~~
├─ com.android.zigmaster.ui.home.HomeFragment$proceedAfterPermissionLocation$1 instance
│ Leaking: UNKNOWN
│ Retaining 12 B in 1 objects
│ Anonymous subclass of com.google.android.gms.location.LocationCallback
│ ↓ HomeFragment$proceedAfterPermissionLocation$1.this$0
│ ~~~~~~
╰→ com.android.zigmaster.ui.home.HomeFragment instance
Leaking: YES (ObjectWatcher was watching this because com.android.zigmaster.ui.home.HomeFragment received
Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
Retaining 5.0 kB in 151 objects
key = f6ba5269-d905-4614-ac2b-4ff353b6f154
watchDurationMillis = 5518
retainedDurationMillis = 518
455760 bytes retained by leaking objects
Signature: 9dd9e366fbcb994c88d457524161a4dca4407a85
┬───
│ GC Root: Global variable in native code
│
├─ com.google.android.gms.location.zzam instance
│ Leaking: UNKNOWN
│ Retaining 456.5 kB in 7825 objects
│ ↓ zzam.zza
│ ~~~
├─ com.google.android.gms.location.zzx instance
│ Leaking: UNKNOWN
│ Retaining 455.9 kB in 7819 objects
│ ↓ zzx.zzc
│ ~~~
├─ com.android.zigmaster.ui.home.FragmentSearch$proceedAfterPermissionLocation$1 instance
│ Leaking: UNKNOWN
│ Retaining 455.8 kB in 7813 objects
│ Anonymous subclass of com.google.android.gms.location.LocationCallback
│ ↓ FragmentSearch$proceedAfterPermissionLocation$1.this$0
│ ~~~~~~
╰→ com.android.zigmaster.ui.home.FragmentSearch instance
Leaking: YES (ObjectWatcher was watching this because com.android.zigmaster.ui.home.FragmentSearch received
Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
Retaining 455.8 kB in 7812 objects
key = 48799cd7-6335-4938-a6b2-71fde55e3507
watchDurationMillis = 12318
retainedDurationMillis = 7276
====================================
0 LIBRARY LEAKS
A Library Leak is a leak caused by a known bug in 3rd party code that you do not have control over.
See https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks
====================================
0 UNREACHABLE OBJECTS
An unreachable object is still in memory but LeakCanary could not find a strong reference path
from GC roots.
====================================
METADATA
Please include this in bug reports and Stack Overflow questions.
Build.VERSION.SDK_INT: 29
Build.MANUFACTURER: samsung
LeakCanary version: 2.7
App process name: com.android.zigmaster
Stats: LruCache[maxSize=3000,hits=3853,misses=55804,hitRate=6%]
RandomAccess[bytes=2861728,reads=55804,travel=19994971106,range=16391680,size=20725210]
Heap dump reason: 10 retained objects, app is visible
Analysis duration: 34210 ms
Heap dump file path: /data/user/0/com.android.zigmaster/cache/leakcanary/2021-04-27_12-22-47_274.hprof
Heap dump timestamp: 1619540608205
Heap dump duration: 6203 ms
====================================
Here is my fragment code:
package com.android.zigmaster.ui.home
class FragmentSearch : Fragment() {
private var binding : FragmentSearchBinding ?=null
private lateinit var locationCallback: LocationCallback
private lateinit var fusedLocationClient: FusedLocationProviderClient
val locationRequestApi = LocationRequest.create()
var gpsLatitude: String = "0.0"
var gpsLongitute: String = "0.0"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentSearchBinding.inflate(inflater)
binding!!.featureCurrentLocation.setOnClickListener {
val lm = requireContext().getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (LocationManagerCompat.isLocationEnabled(lm)) {
// check permission first
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// request the permission
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1001)
} else {
proceedAfterPermissionLocation() // has the permission.
}
}
else {
// enable GPS
try{
//https://stackoverflow.com/questions/25175522/how-to-enable-location-access-programmatically-in-android
val locationRequest = LocationRequest.create()
.setInterval(30000)
.setFastestInterval(15000)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
val builder = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest)
LocationServices
.getSettingsClient(requireContext())
.checkLocationSettings(builder.build())
.addOnSuccessListener(requireActivity()) { response: LocationSettingsResponse? -> }
.addOnFailureListener(requireActivity()) { ex ->
if (ex is ResolvableApiException) {
// Location settings are NOT satisfied, but this can be fixed by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(), and check the result in onActivityResult().
val resolvable = ex as ResolvableApiException
resolvable.startResolutionForResult(requireActivity(), 1002)
} catch (sendEx: SendIntentException) {
// Ignore the error.
}
}
}
}
catch (e: Exception){
Log.d("tag06", "setting page catch " + e.message)
}
}
}
//mView =binding!!.root
return binding!!.root
}
private fun proceedAfterPermissionLocation() {
//.......................................start location callback
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult ?: return
for (location in locationResult.locations) {
val currentLocation = locationResult.lastLocation
gpsLatitude = currentLocation.latitude.toString()
gpsLongitute = currentLocation.longitude.toString()
Log.d("danger04", "..............$gpsLatitude, $gpsLongitute")
try{
fusedLocationClient.removeLocationUpdates(locationCallback)
}catch (e: Exception){ }
}
}
}
locationRequestApi.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequestApi.interval = 10000
locationRequestApi.fastestInterval = 5000
//mLocationRequest!!.smallestDisplacement = 10f // 170 m = 0.1 mile => get accuracy whil travel
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext().applicationContext)
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationClient.requestLocationUpdates(locationRequestApi, locationCallback, null)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, @Nullable data: Intent?) {
if (1002 == requestCode) {
if (Activity.RESULT_OK == resultCode) {
//user clicked OK, you can startUpdatingLocation(...);
proceedAfterPermissionLocation()
} else {
//user clicked cancel: informUserImportanceOfLocationAndPresentRequestAgain();
}
}
}
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
Log.d("calendar", "...........onRequestPermissionsResult code : $requestCode")
when (requestCode) {
1001 -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted.
proceedAfterPermissionLocation() // permission was granted.
Log.d("location", "...........onRequestPermissionsResult : granted")
} else {
// permission denied.
Log.d("location", "...........onRequestPermissionsResult : denied")
}
return
}
}
}
override fun onDestroyView() {
super.onDestroyView()
//.......................................stop location
try{
fusedLocationClient.removeLocationUpdates(locationCallback)
}catch (e: Exception){ }
binding=null
}
}
from How to fix memory leak issue in FusedLocationApi Fragment?
No comments:
Post a Comment