feat: Add permission request

This commit is contained in:
Myzel394 2023-08-05 21:56:11 +02:00
parent b5afcc80ac
commit 591352a604
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
5 changed files with 152 additions and 45 deletions

View File

@ -10,6 +10,7 @@ import kotlinx.serialization.json.decodeFromStream
@Serializable @Serializable
data class AppSettings( data class AppSettings(
val audioRecorderSettings: AudioRecorderSettings = AudioRecorderSettings(), val audioRecorderSettings: AudioRecorderSettings = AudioRecorderSettings(),
val hasSeenOnboarding: Boolean = false,
val showAdvancedSettings: Boolean = false, val showAdvancedSettings: Boolean = false,
) { ) {
fun setShowAdvancedSettings(showAdvancedSettings: Boolean): AppSettings { fun setShowAdvancedSettings(showAdvancedSettings: Boolean): AppSettings {
@ -20,6 +21,10 @@ data class AppSettings(
return copy(audioRecorderSettings = audioRecorderSettings) return copy(audioRecorderSettings = audioRecorderSettings)
} }
fun setHasSeenOnboarding(hasSeenOnboarding: Boolean): AppSettings {
return copy(hasSeenOnboarding = hasSeenOnboarding)
}
companion object { companion object {
fun getDefaultInstance(): AppSettings = AppSettings() fun getDefaultInstance(): AppSettings = AppSettings()
} }

View File

@ -1,5 +1,6 @@
package app.myzel394.locationtest.ui.components.AudioRecorder.atoms package app.myzel394.locationtest.ui.components.AudioRecorder.molecules
import android.Manifest
import android.content.ServiceConnection import android.content.ServiceConnection
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -29,6 +30,8 @@ import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import app.myzel394.locationtest.services.RecorderService import app.myzel394.locationtest.services.RecorderService
import app.myzel394.locationtest.ui.BIG_PRIMARY_BUTTON_SIZE import app.myzel394.locationtest.ui.BIG_PRIMARY_BUTTON_SIZE
import app.myzel394.locationtest.ui.components.AudioRecorder.atoms.AudioVisualizer
import app.myzel394.locationtest.ui.components.atoms.PermissionRequester
import app.myzel394.locationtest.ui.utils.rememberFileSaverDialog import app.myzel394.locationtest.ui.utils.rememberFileSaverDialog
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
@ -51,9 +54,21 @@ fun StartRecording(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
PermissionRequester(
permission = arrayOf(Manifest.permission.RECORD_AUDIO),
icon = {
Icon(
Icons.Default.Mic,
contentDescription = null,
)
},
onPermissionAvailable = {
RecorderService.startService(context, connection)
},
) { trigger ->
Button( Button(
onClick = { onClick = {
RecorderService.startService(context, connection) trigger()
}, },
modifier = Modifier modifier = Modifier
.semantics { .semantics {
@ -79,6 +94,7 @@ fun StartRecording(
) )
} }
} }
}
if (service?.recordingStart != null) if (service?.recordingStart != null)
Column( Column(
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),

View File

@ -0,0 +1,96 @@
package app.myzel394.locationtest.ui.components.atoms
import android.graphics.drawable.Icon
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Cancel
import androidx.compose.material.icons.filled.OpenInBrowser
import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.PermissionChecker
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import app.myzel394.locationtest.ui.utils.PermissionHelper
import app.myzel394.locationtest.ui.utils.openAppSystemSettings
import kotlinx.serialization.json.JsonNull.content
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PermissionRequester(
permission: Array<String>,
icon: (@Composable () -> Unit)? = null,
onPermissionAvailable: () -> Unit,
content: @Composable (trigger: () -> Unit) -> Unit
) {
val context = LocalContext.current
var showPermissionDenied by remember { mutableStateOf(false) }
val callback = {
if (PermissionHelper.checkPermissions(context, permission)) {
onPermissionAvailable()
} else {
showPermissionDenied = true
}
}
if (showPermissionDenied) {
AlertDialog(
onDismissRequest = {
showPermissionDenied = false
},
icon = icon,
title = {
Text("Permission denied")
},
text = {
Text("Please grant the permission to continue. You will be redirected to the app settings to grant the permission there.")
},
confirmButton = {
Button(
onClick = {
showPermissionDenied = false
context.openAppSystemSettings()
}
) {
Icon(
Icons.Default.OpenInNew,
contentDescription = null,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
Text("OK")
}
},
dismissButton = {
Button(
onClick = {
showPermissionDenied = false
},
colors = ButtonDefaults.textButtonColors(),
) {
Icon(
Icons.Default.Cancel,
contentDescription = null,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
Text("Cancel")
}
}
)
}
content(callback)
}

View File

@ -1,49 +1,29 @@
package app.myzel394.locationtest.ui.screens package app.myzel394.locationtest.ui.screens
import android.Manifest
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.media.MediaPlayer
import android.os.IBinder import android.os.IBinder
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Mic
import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import androidx.navigation.NavController import androidx.navigation.NavController
import app.myzel394.locationtest.services.RecorderService import app.myzel394.locationtest.services.RecorderService
import app.myzel394.locationtest.ui.components.AudioRecorder.atoms.RecordingStatus import app.myzel394.locationtest.ui.components.AudioRecorder.molecules.RecordingStatus
import app.myzel394.locationtest.ui.components.AudioRecorder.atoms.StartRecording import app.myzel394.locationtest.ui.components.AudioRecorder.molecules.StartRecording
import app.myzel394.locationtest.ui.enums.Screen import app.myzel394.locationtest.ui.enums.Screen
import app.myzel394.locationtest.ui.utils.rememberFileSaverDialog import app.myzel394.locationtest.ui.utils.rememberFileSaverDialog

View File

@ -2,9 +2,19 @@ package app.myzel394.locationtest.ui.utils
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri
import android.provider.Settings
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
fun Context.openAppSystemSettings() {
startActivity(Intent().apply {
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
data = Uri.fromParts("package", packageName, null)
})
}
// From @Bnyro // From @Bnyro
object PermissionHelper { object PermissionHelper {
fun checkPermissions(context: Context, permissions: Array<String>): Boolean { fun checkPermissions(context: Context, permissions: Array<String>): Boolean {