Added scanner for qr codes and updated logo
This commit is contained in:
parent
2bc30fd106
commit
77741103b0
@ -15,7 +15,7 @@
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2024-02-24T17:02:56.140502018Z" />
|
||||
<timeTargetWasSelectedWithDropDown value="2024-02-26T15:23:42.854086595Z" />
|
||||
</State>
|
||||
</entry>
|
||||
</value>
|
||||
|
@ -72,4 +72,10 @@ dependencies {
|
||||
ksp("io.github.raamcosta.compose-destinations:ksp:1.0.2-beta")
|
||||
|
||||
implementation("androidx.compose.material:material-icons-extended:1.6.2")
|
||||
|
||||
implementation("com.google.accompanist:accompanist-permissions:0.34.0")
|
||||
implementation("androidx.camera:camera-camera2:1.3.1")
|
||||
implementation("androidx.camera:camera-lifecycle:1.3.1")
|
||||
implementation("androidx.camera:camera-view:1.3.1")
|
||||
implementation("com.google.mlkit:barcode-scanning:17.2.0")
|
||||
}
|
@ -2,6 +2,10 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-feature android:name="android.hardware.camera"/>
|
||||
<uses-feature android:name="android.hardware.camera.autofocus"/>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
@ -15,7 +19,6 @@
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.FlowSchool">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
@ -0,0 +1,56 @@
|
||||
package it.edu.cassandroferminervi.flowschool.screens
|
||||
|
||||
import android.util.Log
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.ImageAnalysis
|
||||
import androidx.camera.core.Preview
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.content.ContextCompat
|
||||
import it.edu.cassandroferminervi.flowschool.util.QrAnalyzer
|
||||
|
||||
@Composable
|
||||
fun CameraScreen() {
|
||||
val localContext = LocalContext.current
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val cameraProviderFuture = remember {
|
||||
ProcessCameraProvider.getInstance(localContext)
|
||||
}
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
factory = { context ->
|
||||
val previewView = PreviewView(context)
|
||||
val preview = Preview.Builder().build()
|
||||
val selector = CameraSelector.Builder()
|
||||
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
|
||||
.build()
|
||||
|
||||
preview.setSurfaceProvider(previewView.surfaceProvider)
|
||||
|
||||
val imageAnalysis = ImageAnalysis.Builder().build()
|
||||
imageAnalysis.setAnalyzer(
|
||||
ContextCompat.getMainExecutor(context),
|
||||
QrAnalyzer(context)
|
||||
)
|
||||
|
||||
runCatching {
|
||||
cameraProviderFuture.get().bindToLifecycle(
|
||||
lifecycleOwner,
|
||||
selector,
|
||||
preview,
|
||||
imageAnalysis
|
||||
)
|
||||
}.onFailure {
|
||||
Log.e("CAMERA", "Camera bind error ${it.localizedMessage}", it)
|
||||
}
|
||||
previewView
|
||||
}
|
||||
)
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package it.edu.cassandroferminervi.flowschool.screens
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.ramcosta.composedestinations.PermissionScreenDestination
|
||||
import com.ramcosta.composedestinations.SearchingScreenDestination
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
|
||||
@Destination
|
||||
@Composable
|
||||
fun HomeScreen(navigator: DestinationsNavigator) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 50.dp)
|
||||
) {
|
||||
Button(onClick = {
|
||||
navigator.navigate(PermissionScreenDestination)
|
||||
}, modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||
Text("Scannerizza codice QR")
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Button(onClick = {
|
||||
navigator.navigate(SearchingScreenDestination)
|
||||
}, modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||
Text("Cerca professore")
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package it.edu.cassandroferminervi.flowschool
|
||||
package it.edu.cassandroferminervi.flowschool.screens
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
@ -25,6 +26,7 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
@ -33,6 +35,7 @@ import androidx.compose.ui.unit.dp
|
||||
import com.ramcosta.composedestinations.HomeScreenDestination
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import it.edu.cassandroferminervi.flowschool.R
|
||||
|
||||
@Destination(start = true)
|
||||
@Composable
|
||||
@ -50,8 +53,10 @@ fun LoginScreen(navigator: DestinationsNavigator) {
|
||||
Image(
|
||||
painterResource(id = R.drawable.logo),
|
||||
contentDescription = "Logo",
|
||||
//alignment = Alignment.Center,
|
||||
Modifier.size(192.dp).align(Alignment.CenterHorizontally)
|
||||
Modifier
|
||||
.size(192.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.clip(CircleShape)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(64.dp))
|
||||
TextField(
|
@ -0,0 +1,39 @@
|
||||
package it.edu.cassandroferminervi.flowschool.screens
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.google.accompanist.permissions.shouldShowRationale
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Destination
|
||||
@Composable
|
||||
fun PermissionScreen() {
|
||||
val cameraPermissionState = rememberPermissionState(android.Manifest.permission.CAMERA)
|
||||
|
||||
if (cameraPermissionState.status.isGranted) {
|
||||
CameraScreen()
|
||||
} else {
|
||||
Box (
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
if (cameraPermissionState.status.shouldShowRationale) {
|
||||
Text("Attiva il permesso per la fotocamera dalle impostazioni")
|
||||
} else {
|
||||
SideEffect {
|
||||
cameraPermissionState.run { launchPermissionRequest() }
|
||||
}
|
||||
Text("Permessi disattivati per la fotocamera")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package it.edu.cassandroferminervi.flowschool
|
||||
package it.edu.cassandroferminervi.flowschool.screens
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
@ -7,15 +7,14 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
|
||||
@Destination
|
||||
@Composable
|
||||
fun HomeScreen(navigator: DestinationsNavigator) {
|
||||
Box(
|
||||
fun SearchingScreen() {
|
||||
Box (
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
Text("Home page")
|
||||
Text("Searching screen")
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package it.edu.cassandroferminervi.flowschool.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import androidx.camera.core.ImageAnalysis
|
||||
import androidx.camera.core.ImageProxy
|
||||
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
|
||||
import com.google.mlkit.vision.barcode.BarcodeScanning
|
||||
import com.google.mlkit.vision.barcode.common.Barcode
|
||||
import com.google.mlkit.vision.common.InputImage
|
||||
|
||||
class QrAnalyzer(private val context: Context) : ImageAnalysis.Analyzer {
|
||||
private val options = BarcodeScannerOptions.Builder()
|
||||
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
|
||||
.build()
|
||||
|
||||
private val scanner = BarcodeScanning.getClient(options)
|
||||
|
||||
@SuppressLint("UnsafeOptInUsageError")
|
||||
override fun analyze(imageProxy: ImageProxy) {
|
||||
imageProxy.image
|
||||
?.let { image ->
|
||||
scanner.process(
|
||||
InputImage.fromMediaImage(
|
||||
image, imageProxy.imageInfo.rotationDegrees
|
||||
)
|
||||
).addOnSuccessListener { barcode ->
|
||||
barcode?.takeIf { it.isNotEmpty() }
|
||||
?.mapNotNull { it.rawValue }
|
||||
?.joinToString(",")
|
||||
?.let { Toast.makeText(context, it, Toast.LENGTH_SHORT).show() }
|
||||
}.addOnCompleteListener {
|
||||
imageProxy.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 465 KiB After Width: | Height: | Size: 56 KiB |
Loading…
Reference in New Issue
Block a user