diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 7b8620c..e27fd75 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -15,7 +15,7 @@ - + diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1f03208..1fe83f5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4def73f..9ebabb0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,10 @@ + + + + diff --git a/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/CameraScreen.kt b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/CameraScreen.kt new file mode 100644 index 0000000..edededb --- /dev/null +++ b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/CameraScreen.kt @@ -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 + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/HomeScreen.kt b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/HomeScreen.kt new file mode 100644 index 0000000..4722183 --- /dev/null +++ b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/HomeScreen.kt @@ -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") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/it/edu/cassandroferminervi/flowschool/LoginScreen.kt b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/LoginScreen.kt similarity index 91% rename from app/src/main/java/it/edu/cassandroferminervi/flowschool/LoginScreen.kt rename to app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/LoginScreen.kt index e4e8cf1..4cd9681 100644 --- a/app/src/main/java/it/edu/cassandroferminervi/flowschool/LoginScreen.kt +++ b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/LoginScreen.kt @@ -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( diff --git a/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/PermissionScreen.kt b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/PermissionScreen.kt new file mode 100644 index 0000000..104701d --- /dev/null +++ b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/PermissionScreen.kt @@ -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") + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/it/edu/cassandroferminervi/flowschool/HomeScreen.kt b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/SearchingScreen.kt similarity index 68% rename from app/src/main/java/it/edu/cassandroferminervi/flowschool/HomeScreen.kt rename to app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/SearchingScreen.kt index 75fc322..bf554b2 100644 --- a/app/src/main/java/it/edu/cassandroferminervi/flowschool/HomeScreen.kt +++ b/app/src/main/java/it/edu/cassandroferminervi/flowschool/screens/SearchingScreen.kt @@ -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") } } \ No newline at end of file diff --git a/app/src/main/java/it/edu/cassandroferminervi/flowschool/util/QrAnalyzer.kt b/app/src/main/java/it/edu/cassandroferminervi/flowschool/util/QrAnalyzer.kt new file mode 100644 index 0000000..6b3f67a --- /dev/null +++ b/app/src/main/java/it/edu/cassandroferminervi/flowschool/util/QrAnalyzer.kt @@ -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() + } + } + } + + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/logo.png b/app/src/main/res/drawable/logo.png index e50c7fb..4a4a997 100644 Binary files a/app/src/main/res/drawable/logo.png and b/app/src/main/res/drawable/logo.png differ