Failed to submit capture request
androidx.camera.core.ImageCaptureException: Failed to submit capture request
at androidx.camera.core.imagecapture.TakePictureManager$1.onFailure(TakePictureManager.java:268)
at androidx.camera.core.impl.utils.futures.Futures$CallbackListener.run(Futures.java:345)
at android.os.Handler.handleCallback(Handler.java:959)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loopOnce(Looper.java:232)
at android.os.Looper.loop(Looper.java:317)
at android.app.ActivityThread.main(ActivityThread.java:8592)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)
Caused by: androidx.camera.core.CameraControl$OperationCanceledException: Camera is not active.
at androidx.camera.camera2.internal.Camera2CameraControlImpl.submitStillCaptureRequests(Camera2CameraControlImpl.java:476)
at androidx.camera.core.ImageCapture.submitStillCaptureRequest(ImageCapture.java:1127)
at androidx.camera.core.ImageCapture$1.submitStillCaptureRequests(ImageCapture.java:972)
at androidx.camera.core.imagecapture.TakePictureManager.submitCameraRequest(TakePictureManager.java:249)
at androidx.camera.core.imagecapture.TakePictureManager.issueNextRequest(TakePictureManager.java:214)
at androidx.camera.core.imagecapture.TakePictureManager.offerRequest(TakePictureManager.java:117)
at androidx.camera.core.ImageCapture.takePictureInternal(ImageCapture.java:1044)
at androidx.camera.core.ImageCapture.takePicture(ImageCapture.java:746)
at com.example.smartlagoon.ui.screens.camera.CameraScreenKt.takePhoto(CameraScreen.kt:249)
at com.example.smartlagoon.ui.screens.camera.CameraScreenKt.access$takePhoto(CameraScreen.kt:1)
at com.example.smartlagoon.ui.screens.camera.CameraScreenKt$CameraScreen$1$3$1.invokeSuspend(CameraScreen.kt:155)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.android.kt:57)
at android.os.Handler.handleCallback(Handler.java:959)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loopOnce(Looper.java:232)
at android.os.Looper.loop(Looper.java:317)
at android.app.ActivityThread.main(ActivityThread.java:8592)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)
@Composable
fun CameraScreen(
navController: NavController,
photosDbVm: PhotosDbViewModel,
challengesDbVm: ChallengesDbViewModel,
usersDbVm: UsersDbViewModel,
) {
val ctx = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val cameraProviderFuture = remember { ProcessCameraProvider.getInstance(ctx) }
val previewView = remember { PreviewView(ctx) }
val imageCapture = remember { mutableStateOf<ImageCapture?>(null) }
val cameraSelector = remember { mutableStateOf(CameraSelector.DEFAULT_BACK_CAMERA) }
val cameraControl = remember { mutableStateOf<CameraControl?>(null) }
val isFlashEnabled = remember { mutableStateOf(false) }
var isPressed by remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
val currentChallenge by challengesDbVm.currentChallenge.observeAsState()
Log.d("currentChallengeCamera", currentChallenge.toString())
Box(modifier = Modifier.fillMaxSize()) {
// Anteprima della fotocamera
AndroidView(
factory = { previewView },
modifier = Modifier.fillMaxSize()
)
// Configura CameraX
LaunchedEffect(cameraProviderFuture) {
val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
val imageCaptureConfig = ImageCapture.Builder().build()
imageCapture.value = imageCaptureConfig
try {
// Disattiva tutti i use cases
cameraProvider.unbindAll()
// Associa i use cases alla fotocamera
val camera = cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector.value,
preview,
imageCaptureConfig
)
// Ottieni il controllo della fotocamera per gestire zoom e flash
cameraControl.value = camera.cameraControl
} catch (exc: Exception) {
Log.e("CameraX", "Impossibile associare i use cases alla fotocamera", exc)
}
}
// Pulsante per scattare la foto
Button(
onClick = {
isPressed = true // Cambia lo stato del bottone
// Avvia una coroutine per gestire il delay
coroutineScope.launch {
// Utilizza la funzione takePhoto modificata
takePhoto(ctx, imageCapture.value) { uri ->
if (uri != null) {
photosDbVm.uploadPhoto(uri)
} else {
Log.e(
"CameraScreen",
"Errore: URI della foto è nullo. Foto non caricata."
)
}
}
delay(500L) // Delay di 1 secondo (1000 millisecondi)
isPressed = false // Ripristina lo stato del bottone
}
Log.d("caricamentoFoto","aaa")
if(currentChallenge != null) {
currentChallenge?.let { usersDbVm.addPoints(it.points) }
currentChallenge?.id?.let { challengesDbVm.challengeDone(it) }
photosDbVm.setShowDialog(true)
navController.navigate(SmartlagoonRoute.Photo.route)
}else {
navController.navigateUp() // Torna indietro dopo il delay
}
scheduleNotification(ctx)
},
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 10.dp)
.size(70.dp) // Dimensione per creare una forma tonda
.clip(CircleShape), // Clip a forma circolare
colors = ButtonDefaults.buttonColors(
containerColor = if (isPressed) Color.Red else Color.White, // Colore del bottone basato sullo stato
contentColor = Color.Transparent // Nessun colore del contenuto (per l'icona)
)
) {
}
// Pulsante per commutare la fotocamera
IconButton(
onClick = {
cameraSelector.value = if (cameraSelector.value == CameraSelector.DEFAULT_BACK_CAMERA) {
CameraSelector.DEFAULT_FRONT_CAMERA
} else {
CameraSelector.DEFAULT_BACK_CAMERA
}
},
modifier = Modifier
.align(Alignment.TopStart)
.padding(16.dp)
) {
Icon(
imageVector = Icons.Default.FlipCameraAndroid,
contentDescription = "Cambia Fotocamera",
tint = Color.White
)
}
// Pulsante per abilitare/disabilitare il flash
IconButton(
onClick = {
isFlashEnabled.value = !isFlashEnabled.value
cameraControl.value?.enableTorch(isFlashEnabled.value)
},
modifier = Modifier
.align(Alignment.TopEnd)
.padding(16.dp),
) {
Icon(
imageVector = if (isFlashEnabled.value) Icons.Default.FlashOn else Icons.Default.FlashOff,
contentDescription = "Controllo Flash",
tint = Color.White
)
}
}
}
private fun takePhoto(context: Context, imageCapture: ImageCapture?, onPhotoTaken: (Uri?) -> Unit) {
if (imageCapture == null) {
Log.e("CameraX", "Errore: ImageCapture non è pronto.")
onPhotoTaken(null)
return
}else {
Log.e("CameraX", "NON NULLO")
}
// Crea un file temporaneo per salvare la foto
val photoFile = File(
context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),
"${System.currentTimeMillis()}.jpg"
)
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(context),
object : ImageCapture.OnImageSavedCallback {
override fun onError(exception: ImageCaptureException) {
Log.e("CameraX", "Errore durante lo scatto della foto: ${exception.message}", exception)
onPhotoTaken(null) // Chiamata di callback con URI nullo in caso di errore
}
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
Log.d("CameraX", "Foto salvata con successo: ${photoFile.absolutePath}")
// Verifica se il file esiste prima di procedere
if (photoFile.exists()) {
val uri = photoFile.toUri()
Toast.makeText(context, "Foto caricata!", Toast.LENGTH_SHORT).show()
onPhotoTaken(uri) // Chiamata di callback con URI valido
} else {
Log.e("CameraX", "Il file della foto non esiste!")
onPhotoTaken(null) // Chiamata di callback con URI nullo
}
}
}
)
}
I can se the preview and when I click it become full screen but it’n not working.
imageCapture is not null and there are two cameras available
val availableCameras = cameraProvider.availableCameraInfos
if (availableCameras.isEmpty()) {
Log.e("CameraX", "Nessuna fotocamera disponibile sul dispositivo.")
return // O gestisci l'errore in modo appropriato
}
// Log delle informazioni sulle fotocamere disponibili per il debugging
availableCameras.forEach { cameraInfo ->
Log.d("CameraX", "Camera disponibile: ${cameraInfo.cameraSelector}")
}