如何在compose中拍照

How to take a picture in compose

我想在 compose 中使用 camerax,在 previewView 中拍照。

// activity
class MainActivity : AppCompatActivity() {
    private lateinit var outputDirectory: File
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        outputDirectory = getOutputDirectory()
        setContent {
            MyTheme {
                Main(
                    viewModel = viewModel,
                    backDispatcher = onBackPressedDispatcher,
                    outputDirectory = outputDirectory
                )
            }
        }
    }
    private fun getOutputDirectory(): File {
        val mediaDir = externalMediaDirs.firstOrNull()?.let {
            File(it, resources.getString(R.string.app_name)).apply { mkdirs() } }
        return if (mediaDir != null && mediaDir.exists())
            mediaDir else filesDir
    }
}

// compose function
@Composable
fun CameraPreviewScreen(
    outputDirectory: File,
    pressOnBack: () -> Unit,
    modifier: Modifier
) {
    val context = ContextAmbient.current
    val lifecycleOwner = LifecycleOwnerAmbient.current
    val previewView = remember { PreviewView(context) }
    var imageCapture: ImageCapture? = null
    Box {
        AndroidView(viewBlock = { previewView }) {
            val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
            cameraProviderFuture.addListener(Runnable {
                val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
                val preview = Preview.Builder().build()
                preview.setSurfaceProvider(previewView.surfaceProvider)
                val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
                try {
                    cameraProvider.unbindAll()
                    cameraProvider.bindToLifecycle(
                        lifecycleOwner, cameraSelector, preview)
                } catch(exc: Exception) {
                    Log.e("SB", "Use case binding failed", exc)
                }
            }, ContextCompat.getMainExecutor(context))
        }
        Button(
            border = BorderStroke(5.dp, Color.White),
            shape = RoundedCornerShape(50),
            onClick = {
                val imageCapture = imageCapture ?: return@Button
                val photoFile = File(
                    outputDirectory,
                    SimpleDateFormat(
                        "yyyy-MM-dd-HH-mm-ss-SSS", Locale.US
                    ).format(System.currentTimeMillis()) + ".jpg")
                val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
                imageCapture.takePicture(
                    outputOptions, ContextCompat.getMainExecutor(context), object : ImageCapture.OnImageSavedCallback {
                        override fun onError(exc: ImageCaptureException) {
                            Log.e("TEST", "Photo capture failed: ${exc.message}", exc)
                        }
                        override fun onImageSaved(output: ImageCapture.OutputFileResults) {
                            val savedUri = Uri.fromFile(photoFile)
                            val msg = "Photo capture succeeded: $savedUri"
                            Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
                            Log.d("TEST", msg)
                        }
                    })
            },
            modifier = Modifier
                .width(50.dp)
                .height(50.dp)
                .align(Alignment.BottomCenter)
        ) {

        }
    }
}

但是当我点击按钮时,它没有用照片回应我。我已经开启了摄像头权限,还需要再添加权限吗?

您在初始化相机时没有设置图像捕获用例。

使用:

imageCapture = ImageCapture.Builder().build()

并在cameraProvider.bindToLifecycle()中使用:

cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageCapture)