Added scanner for qr codes and updated logo
This commit is contained in:
parent
2bc30fd106
commit
77741103b0
@ -15,7 +15,7 @@
|
|||||||
</deviceKey>
|
</deviceKey>
|
||||||
</Target>
|
</Target>
|
||||||
</targetSelectedWithDropDown>
|
</targetSelectedWithDropDown>
|
||||||
<timeTargetWasSelectedWithDropDown value="2024-02-24T17:02:56.140502018Z" />
|
<timeTargetWasSelectedWithDropDown value="2024-02-26T15:23:42.854086595Z" />
|
||||||
</State>
|
</State>
|
||||||
</entry>
|
</entry>
|
||||||
</value>
|
</value>
|
||||||
|
@ -72,4 +72,10 @@ dependencies {
|
|||||||
ksp("io.github.raamcosta.compose-destinations:ksp:1.0.2-beta")
|
ksp("io.github.raamcosta.compose-destinations:ksp:1.0.2-beta")
|
||||||
|
|
||||||
implementation("androidx.compose.material:material-icons-extended:1.6.2")
|
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"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
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
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
@ -15,7 +19,6 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
|
||||||
android:theme="@style/Theme.FlowSchool">
|
android:theme="@style/Theme.FlowSchool">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<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.Image
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
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.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Visibility
|
import androidx.compose.material.icons.filled.Visibility
|
||||||
@ -25,6 +26,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
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.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
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.HomeScreenDestination
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
|
import it.edu.cassandroferminervi.flowschool.R
|
||||||
|
|
||||||
@Destination(start = true)
|
@Destination(start = true)
|
||||||
@Composable
|
@Composable
|
||||||
@ -50,8 +53,10 @@ fun LoginScreen(navigator: DestinationsNavigator) {
|
|||||||
Image(
|
Image(
|
||||||
painterResource(id = R.drawable.logo),
|
painterResource(id = R.drawable.logo),
|
||||||
contentDescription = "Logo",
|
contentDescription = "Logo",
|
||||||
//alignment = Alignment.Center,
|
Modifier
|
||||||
Modifier.size(192.dp).align(Alignment.CenterHorizontally)
|
.size(192.dp)
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
|
.clip(CircleShape)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(64.dp))
|
Spacer(modifier = Modifier.height(64.dp))
|
||||||
TextField(
|
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.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@ -7,15 +7,14 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
|
||||||
|
|
||||||
@Destination
|
@Destination
|
||||||
@Composable
|
@Composable
|
||||||
fun HomeScreen(navigator: DestinationsNavigator) {
|
fun SearchingScreen() {
|
||||||
Box (
|
Box (
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
modifier = Modifier.fillMaxSize()
|
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