mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2026-02-06 15:24:29 +01:00
Removed unused directory
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
plugins {
|
||||
alias(libs.plugins.nordic.feature)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "no.nordicsemi.android.permissions_ranging"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.accompanist.permissions)
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.RANGING" />
|
||||
|
||||
</manifest>
|
||||
@@ -1,42 +0,0 @@
|
||||
package no.nordicsemi.android.permissions_ranging
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import no.nordicsemi.android.permissions_ranging.utils.RangingNotAvailableReason
|
||||
import no.nordicsemi.android.permissions_ranging.utils.RangingPermissionState
|
||||
import no.nordicsemi.android.permissions_ranging.view.RangingPermissionRequestView
|
||||
import no.nordicsemi.android.permissions_ranging.viewmodel.RangingPermissionViewModel
|
||||
|
||||
@Composable
|
||||
fun RequestRangingPermission(
|
||||
onChanged: (Boolean) -> Unit = {},
|
||||
content: @Composable (Boolean) -> Unit,
|
||||
) {
|
||||
val permissionViewModel = hiltViewModel<RangingPermissionViewModel>()
|
||||
val context = LocalContext.current
|
||||
val activity = context as? Activity
|
||||
|
||||
val state by activity?.let { permissionViewModel.requestRangingPermission(it) }!!
|
||||
.collectAsStateWithLifecycle()
|
||||
|
||||
|
||||
LaunchedEffect(state) {
|
||||
onChanged(state is RangingPermissionState.Available)
|
||||
}
|
||||
|
||||
when (val s = state) {
|
||||
is RangingPermissionState.Available -> content(true)
|
||||
is RangingPermissionState.NotAvailable -> {
|
||||
when (s.reason) {
|
||||
RangingNotAvailableReason.NOT_AVAILABLE -> RangingPermissionRequestView(content)
|
||||
RangingNotAvailableReason.PERMISSION_DENIED -> content(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package no.nordicsemi.android.permissions_ranging.repository
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import no.nordicsemi.android.permissions_ranging.utils.LocalDataProvider
|
||||
import no.nordicsemi.android.permissions_ranging.utils.RangingNotAvailableReason
|
||||
import no.nordicsemi.android.permissions_ranging.utils.RangingPermissionState
|
||||
import no.nordicsemi.android.permissions_ranging.utils.RangingPermissionUtils
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
private const val REFRESH_PERMISSIONS =
|
||||
"no.nordicsemi.android.permissions_ranging.repository.REFRESH_RANGING_PERMISSIONS"
|
||||
private const val RANGING_PERMISSION_REQUEST_CODE = 1001
|
||||
|
||||
@Singleton
|
||||
internal class RangingStateManager @Inject constructor(
|
||||
@param:ApplicationContext private val context: Context,
|
||||
) {
|
||||
private val dataProvider = LocalDataProvider(context)
|
||||
private val utils = RangingPermissionUtils(context, dataProvider)
|
||||
|
||||
fun rangingPermissionState(activity: Activity) = callbackFlow {
|
||||
trySend(getRangingPermissionState())
|
||||
|
||||
val rangingStateChangeHandler = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
trySend(getRangingPermissionState())
|
||||
}
|
||||
}
|
||||
ContextCompat.registerReceiver(
|
||||
context,
|
||||
rangingStateChangeHandler,
|
||||
IntentFilter(),
|
||||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
ActivityCompat.requestPermissions(
|
||||
activity,
|
||||
arrayOf("android.permission.RANGING"),
|
||||
RANGING_PERMISSION_REQUEST_CODE
|
||||
)
|
||||
|
||||
awaitClose {
|
||||
|
||||
context.unregisterReceiver(rangingStateChangeHandler)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun refreshRangingPermissionState() {
|
||||
val intent = Intent(REFRESH_PERMISSIONS)
|
||||
context.sendBroadcast(intent)
|
||||
}
|
||||
|
||||
fun markRangingPermissionAsRequested() {
|
||||
dataProvider.isRangingPermissionRequested = true
|
||||
}
|
||||
|
||||
fun isRangingPermissionDenied(): Boolean {
|
||||
return try {
|
||||
utils.isRangingPermissionDenied()
|
||||
} catch (_: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRangingPermissionState(): RangingPermissionState {
|
||||
return when {
|
||||
!utils.isRangingPermissionAvailable -> RangingPermissionState.NotAvailable(
|
||||
RangingNotAvailableReason.NOT_AVAILABLE
|
||||
)
|
||||
|
||||
utils.isRangingPermissionAvailable && !utils.isRangingPermissionGranted -> RangingPermissionState.NotAvailable(
|
||||
RangingNotAvailableReason.PERMISSION_DENIED
|
||||
)
|
||||
|
||||
else -> RangingPermissionState.Available
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package no.nordicsemi.android.permissions_ranging.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Build
|
||||
import androidx.annotation.ChecksSdkIntAtLeast
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.edit
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
private const val SHARED_PREFS_NAME = "SHARED_PREFS_RANGING"
|
||||
private const val PREFS_PERMISSION_REQUESTED = "ranging_permission_requested"
|
||||
|
||||
@Singleton
|
||||
internal class LocalDataProvider @Inject constructor(
|
||||
private val context: Context,
|
||||
) {
|
||||
private val sharedPrefs: SharedPreferences
|
||||
get() = context.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
|
||||
|
||||
val isBaklavaOrAbove: Boolean
|
||||
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.BAKLAVA)
|
||||
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA
|
||||
|
||||
/**
|
||||
* The first time an app requests a permission there is no 'Don't Allow' checkbox and
|
||||
* [ActivityCompat.shouldShowRequestPermissionRationale] returns false.
|
||||
*/
|
||||
var isRangingPermissionRequested: Boolean
|
||||
get() = sharedPrefs.getBoolean(PREFS_PERMISSION_REQUESTED, false)
|
||||
set(value) {
|
||||
sharedPrefs.edit { putBoolean(PREFS_PERMISSION_REQUESTED, value) }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package no.nordicsemi.android.permissions_ranging.utils
|
||||
|
||||
internal sealed class RangingPermissionState {
|
||||
/**
|
||||
* Ranging is available and the app has the required permissions.
|
||||
*/
|
||||
data object Available : RangingPermissionState()
|
||||
|
||||
/**
|
||||
* Ranging is not available.
|
||||
*/
|
||||
data class NotAvailable(
|
||||
val reason: RangingNotAvailableReason,
|
||||
) : RangingPermissionState()
|
||||
}
|
||||
|
||||
internal enum class RangingNotAvailableReason {
|
||||
/** Ranging is not available on this device. */
|
||||
NOT_AVAILABLE,
|
||||
|
||||
/** The app does not have the required permissions. */
|
||||
PERMISSION_DENIED,
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package no.nordicsemi.android.permissions_ranging.utils
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import androidx.annotation.ChecksSdkIntAtLeast
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
internal class RangingPermissionUtils(
|
||||
private val context: Context,
|
||||
private val dataProvider: LocalDataProvider,
|
||||
) {
|
||||
val isRangingPermissionAvailable: Boolean
|
||||
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.BAKLAVA)
|
||||
get() = Build.VERSION.SDK_INT >= 36
|
||||
|
||||
|
||||
val isRangingPermissionGranted: Boolean
|
||||
get() = isRangingPermissionAvailable &&
|
||||
ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.RANGING
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
|
||||
fun isRangingPermissionDenied(): Boolean {
|
||||
return dataProvider.isBaklavaOrAbove &&
|
||||
dataProvider.isRangingPermissionRequested && // Ranging permission was requested.
|
||||
!isRangingPermissionGranted // Ranging permission is not granted
|
||||
&& !context.findActivity()
|
||||
?.shouldShowRequestPermissionRationale(Manifest.permission.RANGING)!!
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the activity from the given context.
|
||||
*
|
||||
* https://github.com/google/accompanist/blob/6611ebda55eb2948eca9e1c89c2519e80300855a/permissions/src/main/java/com/google/accompanist/permissions/PermissionsUtil.kt#L99
|
||||
*
|
||||
* @throws IllegalStateException if no activity was found.
|
||||
* @return the activity.
|
||||
*/
|
||||
private fun Context.findActivity(): Activity? {
|
||||
return try {
|
||||
var context = this
|
||||
while (context is ContextWrapper) {
|
||||
if (context is Activity) return context
|
||||
context = context.baseContext
|
||||
}
|
||||
null // no activity found
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package no.nordicsemi.android.permissions_ranging.view
|
||||
|
||||
import android.Manifest
|
||||
import android.os.Build
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.PermissionStatus
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import no.nordicsemi.android.permissions_ranging.viewmodel.RangingPermissionViewModel
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
internal fun RangingPermissionRequestView(
|
||||
content: @Composable (Boolean) -> Unit,
|
||||
) {
|
||||
val rangingPermissionViewModel = hiltViewModel<RangingPermissionViewModel>()
|
||||
|
||||
val permission = if (Build.VERSION.SDK_INT >= 36)
|
||||
Manifest.permission.RANGING else null
|
||||
|
||||
val rangingPermission = permission?.let {
|
||||
rememberPermissionState(it)
|
||||
}
|
||||
|
||||
if (rangingPermission != null) {
|
||||
when (rangingPermission.status) {
|
||||
is PermissionStatus.Denied -> {
|
||||
LaunchedEffect(!rangingPermission.status.isGranted) {
|
||||
rangingPermissionViewModel.markRangingPermissionRequested()
|
||||
rangingPermission.launchPermissionRequest()
|
||||
if (!rangingPermission.status.isGranted) {
|
||||
rangingPermissionViewModel.markRangingPermissionDenied()
|
||||
}
|
||||
rangingPermissionViewModel.refreshRangingPermissionState()
|
||||
}
|
||||
content(rangingPermission.status.isGranted)
|
||||
}
|
||||
|
||||
PermissionStatus.Granted -> content(true)
|
||||
}
|
||||
} else {
|
||||
rangingPermissionViewModel.refreshRangingPermissionState()
|
||||
content(true)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package no.nordicsemi.android.permissions_ranging.viewmodel
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import no.nordicsemi.android.permissions_ranging.repository.RangingStateManager
|
||||
import no.nordicsemi.android.permissions_ranging.utils.RangingNotAvailableReason
|
||||
import no.nordicsemi.android.permissions_ranging.utils.RangingPermissionState
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class RangingPermissionViewModel @Inject constructor(
|
||||
private val rangingStateManager: RangingStateManager,
|
||||
) : ViewModel() {
|
||||
fun requestRangingPermission(activity: Activity) =
|
||||
rangingStateManager.rangingPermissionState(activity)
|
||||
.stateIn(
|
||||
viewModelScope,
|
||||
SharingStarted.Lazily,
|
||||
RangingPermissionState.NotAvailable(RangingNotAvailableReason.NOT_AVAILABLE),
|
||||
)
|
||||
|
||||
fun refreshRangingPermissionState() {
|
||||
rangingStateManager.refreshRangingPermissionState()
|
||||
}
|
||||
|
||||
fun markRangingPermissionRequested() {
|
||||
rangingStateManager.markRangingPermissionAsRequested()
|
||||
}
|
||||
|
||||
fun markRangingPermissionDenied() {
|
||||
rangingStateManager.isRangingPermissionDenied()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user