From daeec25ffd80cd73e0645025d1b4e2afed35f87f Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Wed, 22 Jan 2025 18:32:06 +0530 Subject: [PATCH] Fixed: If storage permission is permanently denied on Android 11 or below, the selected file via the file picker does not open. * The storage permission dialog is now shown when the user clicks the "File Picker" button, prompting them to grant the permission first before selecting a ZIM file via the file picker. * If storage permission is denied or not granted, and the user opens a ZIM file by clicking on it in the file manager, the app will first prompt for permission. Once the permission is granted, the ZIM file will open in the reader. If the permission is not granted, the operation is canceled, and the selected ZIM file will not open. --- .../library/LocalLibraryFragment.kt | 66 ++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt index 51d8875dc..a182bde18 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt @@ -132,6 +132,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal private var fragmentDestinationLibraryBinding: FragmentDestinationLibraryBinding? = null private var permissionDeniedLayoutShowing = false private var fileSelectListState: FileSelectListState? = null + private var zimFileUri: Uri? = null private val zimManageViewModel by lazy { requireActivity().viewModel(viewModelFactory) @@ -371,7 +372,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal fragmentDestinationLibraryBinding?.selectFile?.setOnClickListener { if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) { showManageExternalStoragePermissionDialog() - } else { + } else if (requestExternalStorageWritePermission()) { showFileChooser() } } @@ -435,7 +436,10 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal parentFragmentManager ) } else { - getZimFileFromUri(uri)?.let(::navigateToReaderFragment) + zimFileUri = uri + if (requestExternalStorageWritePermission()) { + getZimFileFromUri(uri)?.let(::navigateToReaderFragment) + } } } } @@ -510,6 +514,9 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal storagePermissionLauncher = null copyMoveFileHandler?.dispose() copyMoveFileHandler = null + readStoragePermissionLauncher?.unregister() + readStoragePermissionLauncher = null + zimFileUri = null } private fun sideEffects() = zimManageViewModel.sideEffects @@ -710,4 +717,59 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal private fun showWarningDialogForSplittedZimFile() { dialogShower.show(KiwixDialog.ShowWarningAboutSplittedZimFile) } + + private var readStoragePermissionLauncher: ActivityResultLauncher>? = + registerForActivityResult( + ActivityResultContracts.RequestMultiplePermissions() + ) { permissionResult -> + val isGranted = + permissionResult.entries.all( + Map.Entry::value + ) + if (isGranted) { + zimFileUri?.let { + // open the selected ZIM file in reader. + lifecycleScope.launch { + getZimFileFromUri(it)?.let(::navigateToReaderFragment) + } + } + } else { + if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + /* shouldShowRequestPermissionRationale() returns false when: + * 1) User has previously checked on "Don't ask me again", and/or + * 2) Permission has been disabled on device + */ + requireActivity().toast(string.request_storage, Toast.LENGTH_LONG) + } else { + dialogShower.show( + KiwixDialog.ReadPermissionRequired, + requireActivity()::navigateToAppSettings + ) + } + } + } + + @Suppress("NestedBlockDepth") + private fun requestExternalStorageWritePermission(): Boolean { + var isPermissionGranted = false + if (!sharedPreferenceUtil.isPlayStoreBuildWithAndroid11OrAbove() && + Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU + ) { + if (requireActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED + ) { + isPermissionGranted = true + } else { + readStoragePermissionLauncher?.launch( + arrayOf( + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + ) + } + } else { + isPermissionGranted = true + } + return isPermissionGranted + } }