From 464aff4d646337b8137b92c746cf3cecf11e5462 Mon Sep 17 00:00:00 2001 From: Rahul Patel Date: Sat, 27 Jul 2024 14:40:04 +0530 Subject: [PATCH] Redo Permissions [2/2] --- app/src/main/java/com/aurora/store/Aliases.kt | 5 +- .../data/providers/PermissionProvider.kt | 71 ++++++++++++++----- .../view/ui/details/AppDetailsFragment.kt | 4 +- .../view/ui/onboarding/PermissionsFragment.kt | 4 +- .../store/view/ui/sheets/DozeWarningSheet.kt | 48 ++++++------- .../store/view/ui/updates/UpdatesFragment.kt | 4 +- 6 files changed, 83 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/com/aurora/store/Aliases.kt b/app/src/main/java/com/aurora/store/Aliases.kt index 0e3d8b894..5dbdf03e9 100644 --- a/app/src/main/java/com/aurora/store/Aliases.kt +++ b/app/src/main/java/com/aurora/store/Aliases.kt @@ -1,5 +1,6 @@ package com.aurora.store +import androidx.activity.result.ActivityResult import com.aurora.gplayapi.data.models.Category import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.models.StreamCluster @@ -9,4 +10,6 @@ import com.aurora.gplayapi.helpers.contracts.TopChartsContract typealias TopChartStash = MutableMap> typealias HomeStash = MutableMap typealias CategoryStash = MutableMap> -typealias AppStreamStash = MutableMap \ No newline at end of file +typealias AppStreamStash = MutableMap + +typealias PermissionCallback = (ActivityResult) -> Unit diff --git a/app/src/main/java/com/aurora/store/data/providers/PermissionProvider.kt b/app/src/main/java/com/aurora/store/data/providers/PermissionProvider.kt index 2658d644b..365727fec 100644 --- a/app/src/main/java/com/aurora/store/data/providers/PermissionProvider.kt +++ b/app/src/main/java/com/aurora/store/data/providers/PermissionProvider.kt @@ -2,6 +2,7 @@ package com.aurora.store.data.providers import android.Manifest import android.annotation.SuppressLint +import android.app.Activity import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent @@ -20,8 +21,11 @@ import com.aurora.extensions.isDomainVerified import com.aurora.extensions.isExternalStorageAccessible import com.aurora.extensions.isMAndAbove import com.aurora.extensions.isOAndAbove +import com.aurora.extensions.toast import com.aurora.store.BuildConfig +import com.aurora.store.PermissionCallback import com.aurora.store.PermissionType +import com.aurora.store.R import com.aurora.store.util.Log import com.aurora.store.util.PackageUtil @@ -31,33 +35,47 @@ class PermissionProvider : ActivityResultCallback { private var intentLauncher: ActivityResultLauncher private var permissionLauncher: ActivityResultLauncher - constructor(activity: AppCompatActivity) { - context = activity + private var permissionCallback: PermissionCallback? = null + + constructor(activity: AppCompatActivity, callback: PermissionCallback? = null) { + this.context = activity + permissionCallback = callback intentLauncher = activity.registerForActivityResult( ActivityResultContracts.StartActivityForResult(), this ) + permissionLauncher = - activity.registerForActivityResult(ActivityResultContracts.RequestPermission()) {} + activity.registerForActivityResult(ActivityResultContracts.RequestPermission()) { + permissionCallback?.invoke( + ActivityResult( + if (it) Activity.RESULT_OK else Activity.RESULT_CANCELED, + null + ) + ) + } } - constructor(fragment: Fragment) { - context = fragment.requireContext() + constructor(fragment: Fragment, callback: PermissionCallback? = null) { + this.context = fragment.requireContext() + permissionCallback = callback intentLauncher = fragment.registerForActivityResult( ActivityResultContracts.StartActivityForResult(), this ) permissionLauncher = - fragment.registerForActivityResult(ActivityResultContracts.RequestPermission()) {} - } - - fun unregister() { - intentLauncher.unregister() - permissionLauncher.unregister() + fragment.registerForActivityResult(ActivityResultContracts.RequestPermission()) { + permissionCallback?.invoke( + ActivityResult( + if (it) Activity.RESULT_OK else Activity.RESULT_CANCELED, + null + ) + ) + } } private val permissionMap: Map = mapOf( - PermissionType.STORAGE_MANAGER to PackageUtil.getStorageManagerIntent(safe = true), + PermissionType.STORAGE_MANAGER to PackageUtil.getStorageManagerIntent(safe = false), PermissionType.INSTALL_UNKNOWN_APPS to Intent( Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:${BuildConfig.APPLICATION_ID}") @@ -72,32 +90,42 @@ class PermissionProvider : ActivityResultCallback { ) ) - fun requestPermission(permissionType: PermissionType) { + fun request(permissionType: PermissionType) { try { when (permissionType) { PermissionType.EXTERNAL_STORAGE -> permissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) PermissionType.POST_NOTIFICATIONS -> permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) else -> { val intent = permissionMap[permissionType] ?: return - intentLauncher.launch(intent) + + if (permissionType == PermissionType.STORAGE_MANAGER + && !isGranted(PermissionType.INSTALL_UNKNOWN_APPS) + ) { + context.toast(R.string.toast_permission_installer_required) + } else { + intentLauncher.launch(intent) + } } } } catch (e: ActivityNotFoundException) { - Log.e("PermissionProvider", "Activity not found for $permissionType") + Log.e("PermissionProvider", "Activity not found for $permissionType: ${e.message}") + } catch (e: Exception) { + Log.e("PermissionProvider", "Error requesting permission: ${e.message}") } } - fun isPermissionGranted(permissionType: PermissionType): Boolean { + fun isGranted(permissionType: PermissionType): Boolean { return when (permissionType) { PermissionType.EXTERNAL_STORAGE, PermissionType.STORAGE_MANAGER -> context.isExternalStorageAccessible() PermissionType.POST_NOTIFICATIONS -> context.checkManifestPermission(Manifest.permission.POST_NOTIFICATIONS) PermissionType.INSTALL_UNKNOWN_APPS -> { - if (isOAndAbove()) + if (isOAndAbove()) { context.packageManager.canRequestPackageInstalls() - else + } else { true + } } PermissionType.DOZE_WHITELIST -> { @@ -116,7 +144,12 @@ class PermissionProvider : ActivityResultCallback { } } + fun unregister() { + intentLauncher.unregister() + permissionLauncher.unregister() + } + override fun onActivityResult(result: ActivityResult) { - // We don't need to do anything here, as we anyway do permission re-checks using @isPermissionGranted + permissionCallback?.invoke(result) } } diff --git a/app/src/main/java/com/aurora/store/view/ui/details/AppDetailsFragment.kt b/app/src/main/java/com/aurora/store/view/ui/details/AppDetailsFragment.kt index cf5f82235..cbc9bac01 100644 --- a/app/src/main/java/com/aurora/store/view/ui/details/AppDetailsFragment.kt +++ b/app/src/main/java/com/aurora/store/view/ui/details/AppDetailsFragment.kt @@ -550,10 +550,10 @@ class AppDetailsFragment : BaseFragment() { updateActionState(State.PROGRESS) if (PathUtil.needsStorageManagerPerm(app.fileList)) { - if (permissionProvider.isPermissionGranted(PermissionType.STORAGE_MANAGER)) { + if (permissionProvider.isGranted(PermissionType.STORAGE_MANAGER)) { viewModel.download(app) } else { - permissionProvider.requestPermission(PermissionType.STORAGE_MANAGER) + permissionProvider.request(PermissionType.STORAGE_MANAGER) } } else { viewModel.download(app) diff --git a/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt b/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt index f87bcf1e5..50af50775 100644 --- a/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt +++ b/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt @@ -156,7 +156,7 @@ class PermissionsFragment : BaseFragment() return PermissionViewModel_() .id(permission.type.name) .permission(permission) - .isGranted(permissionProvider.isPermissionGranted(permission.type)) - .click { _ -> permissionProvider.requestPermission(permission.type) } + .isGranted(permissionProvider.isGranted(permission.type)) + .click { _ -> permissionProvider.request(permission.type) } } } diff --git a/app/src/main/java/com/aurora/store/view/ui/sheets/DozeWarningSheet.kt b/app/src/main/java/com/aurora/store/view/ui/sheets/DozeWarningSheet.kt index 568f2c414..2b756b852 100644 --- a/app/src/main/java/com/aurora/store/view/ui/sheets/DozeWarningSheet.kt +++ b/app/src/main/java/com/aurora/store/view/ui/sheets/DozeWarningSheet.kt @@ -1,16 +1,13 @@ package com.aurora.store.view.ui.sheets -import android.content.Intent -import android.net.Uri import android.os.Bundle -import android.provider.Settings import android.view.View -import androidx.activity.result.contract.ActivityResultContracts import androidx.navigation.fragment.navArgs import com.aurora.extensions.isIgnoringBatteryOptimizations -import com.aurora.extensions.isMAndAbove import com.aurora.extensions.toast +import com.aurora.store.PermissionType import com.aurora.store.R +import com.aurora.store.data.providers.PermissionProvider import com.aurora.store.data.work.UpdateWorker import com.aurora.store.databinding.SheetDozeWarningBinding import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_AUTO @@ -20,34 +17,31 @@ class DozeWarningSheet : BaseDialogSheet() { private val args: DozeWarningSheetArgs by navArgs() - private val startForDozeResult = - registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { - context?.let { - if (it.isIgnoringBatteryOptimizations()) { - if (args.enableAutoUpdate) { - requireContext().save(PREFERENCE_UPDATES_AUTO, 2) - UpdateWorker.scheduleAutomatedCheck(requireContext()) - } - toast(R.string.toast_permission_granted) - activity?.recreate() - } else { - toast(R.string.permissions_denied) - } - dismissAllowingStateLoss() - } - } + private lateinit var permissionProvider: PermissionProvider override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.btnSecondary.setOnClickListener { dismissAllowingStateLoss() } - binding.btnPrimary.setOnClickListener { - if (isMAndAbove()) { - val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply { - data = Uri.parse("package:${requireContext().packageName}") + permissionProvider = PermissionProvider(this) { + if (requireContext().isIgnoringBatteryOptimizations()) { + if (args.enableAutoUpdate) { + requireContext().save(PREFERENCE_UPDATES_AUTO, 2) + UpdateWorker.scheduleAutomatedCheck(requireContext()) } - startForDozeResult.launch(intent) + toast(R.string.toast_permission_granted) + activity?.recreate() + } else { + toast(R.string.permissions_denied) } + dismissAllowingStateLoss() } + + binding.btnSecondary.setOnClickListener { dismissAllowingStateLoss() } + binding.btnPrimary.setOnClickListener { permissionProvider.request(PermissionType.DOZE_WHITELIST) } + } + + override fun onDestroy() { + permissionProvider.unregister() + super.onDestroy() } } diff --git a/app/src/main/java/com/aurora/store/view/ui/updates/UpdatesFragment.kt b/app/src/main/java/com/aurora/store/view/ui/updates/UpdatesFragment.kt index e62b8ffe3..5779e25ea 100644 --- a/app/src/main/java/com/aurora/store/view/ui/updates/UpdatesFragment.kt +++ b/app/src/main/java/com/aurora/store/view/ui/updates/UpdatesFragment.kt @@ -194,10 +194,10 @@ class UpdatesFragment : BaseFragment() { viewModel.updateAllEnqueued = updateAll if (PathUtil.needsStorageManagerPerm(update.fileList)) { - if (permissionProvider.isPermissionGranted(PermissionType.STORAGE_MANAGER)) { + if (permissionProvider.isGranted(PermissionType.STORAGE_MANAGER)) { viewModel.download(update) } else { - permissionProvider.requestPermission(PermissionType.STORAGE_MANAGER) + permissionProvider.request(PermissionType.STORAGE_MANAGER) } } else { viewModel.download(update)