Selaa lähdekoodia

permissions pre-implementation

permissions fix
Milan Jurkulak 3 vuotta sitten
vanhempi
sitoutus
83fd7a4a00

+ 0 - 2
app/src/main/kotlin/org/mjdev/tvapp/base/activity/ComposableActivity.kt

@@ -58,8 +58,6 @@ open class ComposableActivity : ComponentActivity() {
     @CallSuper
     open fun Compose() {
 
-//        val permissionState = rememberPermissionState(permission = Manifest.permission.READ_SMS)
-
         val navController = rememberNavControllerEx()
 
         TVAppTheme {

+ 29 - 0
app/src/main/kotlin/org/mjdev/tvapp/base/extensions/GlobalExt.kt

@@ -8,6 +8,10 @@
 
 package org.mjdev.tvapp.base.extensions
 
+import android.os.Handler
+import timber.log.Timber
+
+@Suppress("unused")
 object GlobalExt {
 
     fun <E> runSafe(what: () -> E): Result<E> = try {
@@ -18,4 +22,29 @@ object GlobalExt {
         Result.failure(e)
     }
 
+    @Suppress("DEPRECATION")
+    @Throws(Exception::class)
+    fun retry(
+        retryCnt: Int = 8,
+        retryDelay: Long = 500L,
+        onError: (error: Throwable) -> Unit = { e -> throw (e) },
+        block: () -> Unit
+    ) {
+        var retryStep = retryCnt
+        try {
+            block.invoke()
+        } catch (e: Throwable) {
+            Timber.e(e)
+            retryStep -= 1
+            if (retryStep > 0) {
+                Timber.e("Retrying run again.")
+                Handler().postDelayed({
+                    retry(retryStep, retryDelay, onError, block)
+                }, retryDelay)
+            } else {
+                onError(e)
+            }
+        }
+    }
+
 }

+ 83 - 0
app/src/main/kotlin/org/mjdev/tvapp/base/permission/PermissonManager.kt

@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) Milan Jurkulák 2023.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+@file:Suppress("MemberVisibilityCanBePrivate")
+
+package org.mjdev.tvapp.base.permission
+
+import android.annotation.SuppressLint
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import com.google.accompanist.permissions.ExperimentalPermissionsApi
+import com.google.accompanist.permissions.MultiplePermissionsState
+import com.google.accompanist.permissions.rememberMultiplePermissionsState
+import org.mjdev.tvapp.BuildConfig
+
+@Composable
+fun manifestPermissions(): List<String> {
+    val context = LocalContext.current
+    return rememberSaveable {
+        val packageManager = context.packageManager
+        arrayListOf<String>().apply {
+            val pkgInfo: PackageInfo = packageManager.getPackageInfo(
+                BuildConfig.APPLICATION_ID,
+                PackageManager.GET_PERMISSIONS
+            )
+            pkgInfo.requestedPermissions.forEach { p -> add(p) }
+        }
+    }
+}
+
+@Suppress("LocalVariableName")
+@SuppressLint("ComposableNaming")
+@OptIn(ExperimentalPermissionsApi::class)
+@Composable
+fun rememberPermissionManager(
+    permissions: List<String> = manifestPermissions(),
+    onNeedToGrant: MultiplePermissionsState.(permissions: List<String>) -> Unit = {}
+) {
+    var _ps: MultiplePermissionsState? = null
+    val lifecycleOwner = LocalLifecycleOwner.current
+    val onPermissionsResult: (Map<String, Boolean>) -> Unit = { map ->
+        map.filter { p ->
+            !p.value
+        }.filter { p ->
+            permissions.contains(p.key)
+        }.also { ps ->
+            _ps?.also { mps ->
+                onNeedToGrant(mps, ps.map { p -> p.key })
+            }
+        }
+    }
+    val permissionsState = rememberMultiplePermissionsState(
+        permissions = permissions,
+        onPermissionsResult = onPermissionsResult
+    )
+    _ps = permissionsState
+    DisposableEffect(
+        key1 = lifecycleOwner,
+        effect = {
+            val observer = LifecycleEventObserver { _, event ->
+                if (event == Lifecycle.Event.ON_RESUME) {
+                    permissionsState.launchMultiplePermissionRequest()
+                }
+            }
+            lifecycleOwner.lifecycle.addObserver(observer)
+            onDispose {
+                lifecycleOwner.lifecycle.removeObserver(observer)
+            }
+        }
+    )
+}

+ 5 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/SplashScreen.kt

@@ -26,27 +26,32 @@ import androidx.compose.ui.graphics.RectangleShape
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import com.google.accompanist.permissions.ExperimentalPermissionsApi
 import kotlinx.coroutines.delay
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.base.annotations.TvPreview
 import org.mjdev.tvapp.base.extensions.ComposeExt.isEditMode
 import org.mjdev.tvapp.base.extensions.NavControllerExt.openAsTop
+import org.mjdev.tvapp.base.permission.rememberPermissionManager
 import org.mjdev.tvapp.base.screen.Screen
 import org.mjdev.tvapp.base.ui.components.text.TextAny
 import org.mjdev.tvapp.base.ui.components.tv.Title
 
+@Suppress("UNUSED_VARIABLE")
 class SplashScreen : Screen() {
 
     override val showOnce: Boolean = true
     override val backgroundColor: Color = Color.Black
     override val immersive: Boolean = true
 
+    @OptIn(ExperimentalPermissionsApi::class)
     @TvPreview
     @Composable
     override fun ComposeScreen() {
 
         val isEdit = isEditMode()
         val scale = remember { Animatable(if (isEdit) 1f else 0f) }
+        val permissionManager = rememberPermissionManager()
 
         Box(
             modifier = Modifier