From c3049a6a597919368f5364e5983c84e3dae1fbd1 Mon Sep 17 00:00:00 2001 From: MohitMali Date: Mon, 16 Oct 2023 12:48:56 +0530 Subject: [PATCH] Fixed memory leak on API level 24. * When the application goes in the background from `ZimHostFragment`, `KiwixReaderFragment/ZimHostFragment` without starting the Service then the `ReadAloudService`, and `HotspotService` variables are not used and GC try to clear those objects but we are not clearing those objects, that's why memory leak is happening. So now we have free those objects if they are not in use. --- .../core/main/CoreReaderFragment.kt | 18 +++++++++++++--- .../core/webserver/ZimHostFragment.kt | 21 ++++++++++++++++--- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt index bb4d7774e..a579544d0 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt @@ -333,6 +333,7 @@ abstract class CoreReaderFragment : private var readAloudService: ReadAloudService? = null private var navigationHistoryList: MutableList = ArrayList() private var isReadSelection = false + private var isReadAloudServiceRunning = false private var storagePermissionForNotesLauncher: ActivityResultLauncher? = registerForActivityResult( @@ -1047,8 +1048,7 @@ abstract class CoreReaderFragment : } catch (ignore: IllegalArgumentException) { // to handle if service is already unbounded } - readAloudService?.registerCallBack(null) - readAloudService = null + unRegisterReadAloudService() storagePermissionForNotesLauncher?.unregister() storagePermissionForNotesLauncher = null } @@ -2074,9 +2074,17 @@ abstract class CoreReaderFragment : private fun unbindService() { readAloudService?.let { requireActivity().unbindService(serviceConnection) + if (!isReadAloudServiceRunning) { + unRegisterReadAloudService() + } } } + private fun unRegisterReadAloudService() { + readAloudService?.registerCallBack(null) + readAloudService = null + } + private fun createReadAloudIntent(action: String, isPauseTTS: Boolean): Intent = Intent(requireActivity(), ReadAloudService::class.java).apply { setAction(action) @@ -2086,7 +2094,11 @@ abstract class CoreReaderFragment : } private fun setActionAndStartTTSService(action: String, isPauseTTS: Boolean = false) { - requireActivity().startService(createReadAloudIntent(action, isPauseTTS)) + requireActivity().startService( + createReadAloudIntent(action, isPauseTTS) + ).also { + isReadAloudServiceRunning = action == ACTION_PAUSE_OR_RESUME_TTS + } } protected abstract fun restoreViewStateOnValidJSON( diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt index 58bb5b0ed..d9f0052cc 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt @@ -94,6 +94,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { private lateinit var serviceConnection: ServiceConnection private var dialog: Dialog? = null private var activityZimHostBinding: ActivityZimHostBinding? = null + private var isHotspotServiceRunning = false override val fragmentTitle: String? by lazy { getString(R.string.menu_wifi_hotspot) } @@ -304,7 +305,11 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { } private fun stopServer() { - requireActivity().startService(createHotspotIntent(ACTION_STOP_SERVER)) + requireActivity().startService( + createHotspotIntent(ACTION_STOP_SERVER) + ).also { + isHotspotServiceRunning = false + } } private fun select(bookOnDisk: BooksOnDiskListItem.BookOnDisk) { @@ -341,6 +346,9 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { private fun unbindService() { hotspotService?.let { requireActivity().unbindService(serviceConnection) + if (!isHotspotServiceRunning) { + unRegisterHotspotService() + } } } @@ -406,11 +414,16 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { override fun onDestroyView() { super.onDestroyView() activityZimHostBinding?.recyclerViewZimHost?.adapter = null - hotspotService?.registerCallBack(null) + unRegisterHotspotService() presenter.detachView() activityZimHostBinding = null } + private fun unRegisterHotspotService() { + hotspotService?.registerCallBack(null) + hotspotService = null + } + // Advice user to turn on hotspot manually for API<26 private fun startHotspotManuallyDialog() { @@ -495,7 +508,9 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { createHotspotIntent(ACTION_START_SERVER).putStringArrayListExtra( SELECTED_ZIM_PATHS_KEY, selectedBooksPath ).putExtra(RESTART_SERVER, restartServer) - ) + ).also { + isHotspotServiceRunning = true + } } override fun onIpAddressValid() {