Implemented asking for Camera permission
This commit is contained in:
parent
316a0027f7
commit
e1bb7722ff
|
@ -106,6 +106,7 @@ kotlin {
|
||||||
androidMain.dependencies {
|
androidMain.dependencies {
|
||||||
implementation(compose.preview)
|
implementation(compose.preview)
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
|
implementation(libs.androidx.fragment) // to fix bug IllegalArgumentException: Can only use lower 16 bits for requestCode
|
||||||
implementation(libs.androidx.biometric)
|
implementation(libs.androidx.biometric)
|
||||||
|
|
||||||
implementation(libs.favre.bcrypt)
|
implementation(libs.favre.bcrypt)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.codinux.banking.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
@ -11,6 +12,11 @@ import net.codinux.banking.ui.service.BiometricAuthenticationService
|
||||||
import net.codinux.banking.ui.service.ImageService
|
import net.codinux.banking.ui.service.ImageService
|
||||||
|
|
||||||
class MainActivity : FragmentActivity() {
|
class MainActivity : FragmentActivity() {
|
||||||
|
|
||||||
|
private val request = ActivityResultContracts.RequestMultiplePermissions()
|
||||||
|
|
||||||
|
private val activityResultLauncher = registerForActivityResult(request) { }
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
@ -23,8 +29,29 @@ class MainActivity : FragmentActivity() {
|
||||||
App()
|
App()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun requestPermissions(requiredPermissions: List<String>): Boolean {
|
||||||
|
val requiredPermissionsArray = requiredPermissions.toTypedArray()
|
||||||
|
|
||||||
|
activityResultLauncher.launch(requiredPermissionsArray)
|
||||||
|
|
||||||
|
var result = request.getSynchronousResult(baseContext, requiredPermissionsArray)
|
||||||
|
while (result == null) {
|
||||||
|
result = request.getSynchronousResult(baseContext, requiredPermissionsArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return if (result.value != null) {
|
||||||
|
val allPermissionsGranted = result.value.entries.filter { it.key in requiredPermissions }.all { it.value == true }
|
||||||
|
allPermissionsGranted
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun AppAndroidPreview() {
|
fun AppAndroidPreview() {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package net.codinux.banking.ui.service
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
|
||||||
|
object PermissionsService {
|
||||||
|
|
||||||
|
fun allPermissionsGranted(baseContext: Context, permissions: List<String>) = permissions.all {
|
||||||
|
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package net.codinux.banking.ui.service
|
package net.codinux.banking.ui.service
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import androidx.camera.core.*
|
import androidx.camera.core.*
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
|
@ -7,15 +8,14 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.FragmentActivity
|
|
||||||
import com.google.zxing.*
|
import com.google.zxing.*
|
||||||
import com.google.zxing.common.HybridBinarizer
|
import com.google.zxing.common.HybridBinarizer
|
||||||
import com.google.zxing.qrcode.QRCodeReader
|
import com.google.zxing.qrcode.QRCodeReader
|
||||||
import net.codinux.banking.persistence.AndroidContext
|
import net.codinux.banking.persistence.AndroidContext
|
||||||
|
import net.codinux.banking.ui.MainActivity
|
||||||
import net.codinux.banking.ui.config.DI
|
import net.codinux.banking.ui.config.DI
|
||||||
import net.codinux.log.logger
|
import net.codinux.log.logger
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
@ -23,6 +23,8 @@ import java.util.concurrent.Executors
|
||||||
|
|
||||||
actual object QrCodeService {
|
actual object QrCodeService {
|
||||||
|
|
||||||
|
private val RequiredPermissions = listOf(Manifest.permission.CAMERA)
|
||||||
|
|
||||||
private val cameraExecutor = Executors.newCachedThreadPool()
|
private val cameraExecutor = Executors.newCachedThreadPool()
|
||||||
|
|
||||||
private val log by logger()
|
private val log by logger()
|
||||||
|
@ -32,16 +34,17 @@ actual object QrCodeService {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun readQrCodeFromCamera(resultCallback: (QrCodeReadResult) -> Unit) {
|
actual fun readQrCodeFromCamera(resultCallback: (QrCodeReadResult) -> Unit) {
|
||||||
val context = AndroidContext.mainActivity
|
val mainActivity = LocalLifecycleOwner.current as MainActivity // we only have MainActivity, so we can be sure that LocalLifecycleOwner.current is MainActivity
|
||||||
val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
|
|
||||||
|
|
||||||
val localContext = LocalContext.current
|
if (PermissionsService.allPermissionsGranted(AndroidContext.applicationContext, RequiredPermissions) == false &&
|
||||||
log.info { "LocalContext.current = ${localContext.javaClass} ${localContext}" }
|
mainActivity.requestPermissions(RequiredPermissions) == false) {
|
||||||
|
return // we don't have the permission to start the camera
|
||||||
|
}
|
||||||
|
|
||||||
|
val cameraProviderFuture = ProcessCameraProvider.getInstance(mainActivity)
|
||||||
|
|
||||||
val lifecycleOwner = LocalLifecycleOwner.current
|
|
||||||
// val context = LocalContext.current
|
|
||||||
val previewView = remember {
|
val previewView = remember {
|
||||||
PreviewView(context)
|
PreviewView(mainActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
cameraProviderFuture.addListener({
|
cameraProviderFuture.addListener({
|
||||||
|
@ -69,13 +72,13 @@ actual object QrCodeService {
|
||||||
cameraProvider.unbindAll()
|
cameraProvider.unbindAll()
|
||||||
|
|
||||||
// Bind use cases to camera
|
// Bind use cases to camera
|
||||||
cameraProvider.bindToLifecycle(context as FragmentActivity, cameraSelector, preview, imageAnalyzer)
|
cameraProvider.bindToLifecycle(mainActivity, cameraSelector, preview, imageAnalyzer)
|
||||||
|
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
log.error(e) { "Use case binding failed" }
|
log.error(e) { "Use case binding failed" }
|
||||||
}
|
}
|
||||||
|
|
||||||
}, ContextCompat.getMainExecutor(context))
|
}, ContextCompat.getMainExecutor(mainActivity))
|
||||||
|
|
||||||
|
|
||||||
AndroidView(factory = { previewView }, modifier = Modifier.fillMaxSize())
|
AndroidView(factory = { previewView }, modifier = Modifier.fillMaxSize())
|
||||||
|
|
|
@ -24,6 +24,7 @@ android-targetSdk = "34"
|
||||||
|
|
||||||
androidx-activityCompose = "1.9.2"
|
androidx-activityCompose = "1.9.2"
|
||||||
androidx-lifecycle = "2.8.2"
|
androidx-lifecycle = "2.8.2"
|
||||||
|
androidx-fragment = "1.8.3"
|
||||||
androidx-biometric = "1.1.0"
|
androidx-biometric = "1.1.0"
|
||||||
compose-plugin = "1.6.11"
|
compose-plugin = "1.6.11"
|
||||||
|
|
||||||
|
@ -57,6 +58,7 @@ sqldelight-native-driver = { module = "app.cash.sqldelight:native-driver", versi
|
||||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
|
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
|
||||||
androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
|
androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
|
||||||
androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
|
androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
|
||||||
|
androidx-fragment = { group = "androidx.fragment", name = "fragment", version.ref = "androidx-fragment" }
|
||||||
androidx-biometric = { group = "androidx.biometric", name = "biometric", version.ref = "androidx-biometric" }
|
androidx-biometric = { group = "androidx.biometric", name = "biometric", version.ref = "androidx-biometric" }
|
||||||
kotlinx-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue