如何解决您如何使用 camerax 拍照?
我仍在练习 Kotlin 和 Android 开发。据我了解,Camera 类已被弃用,Android 邀请使用 Camerax,因为此高级类与设备无关,并且它们简化了在应用上实现相机的过程。
我曾尝试阅读文档 (https://developer.android.com/training/camerax),但它写得非常糟糕,我几乎不明白他们要解释的内容。 所以我去阅读了文档本身中给出的整个示例代码(https://github.com/android/camera-samples/tree/main/CameraXBasic)。 CameraFragment 代码大约有 500 行(忽略导入和各种注释)。
我真的需要写 500 行代码来简单地拍照吗? 这怎么会被认为是“比以前更简单”?
我的意思是,在 Android 编程中,我只需要编写 4 行代码来要求用户从他的存储中选择一个图像并检索它并在 ImageView 中显示它。 有没有一种真正简单的拍照方法,或者我真的需要停下来浪费一整天的工作来编写所有这些代码行吗?
编辑: 以文档的这一页为例: https://developer.android.com/training/camerax/architecture#kotlin 从这段代码开始。
val preview = Preview.Builder().build()
val viewFinder: PreviewView = findViewById(R.id.previewView)
// The use case is bound to an Android Lifecycle with the following code
val camera = cameraProvider.bindToLifecycle(lifecycleOwner,cameraSelector,preview)
cameraProvider 无处不在。这应该是什么?我发现它是一个 ProcessCameraProvider,但我应该如何初始化它?
它应该是一个 lateinit var 还是它已经在其他地方初始化了?
因为如果我尝试写 val cameraProvider = ProcessCameraProvider()
会出错,那我该怎么办?
什么是cameraSelector参数?之前没有定义。我发现它是前置或后置摄像头的选择器,但是我怎么知道它阅读文档的那一页?
这份文件怎么能在这些缺乏的情况下发布?
一个人应该如何轻松学习?
解决方法
在您可以使用 CameraX 与设备的相机交互之前,您需要初始化库。初始化过程是异步的,涉及加载有关设备摄像头的信息。
您使用 ProcessCameraProvider
与设备的摄像头进行交互。这是一个单例,所以当你第一次得到一个 if 实例时,CameraX 会执行它的初始化。
val cameraProviderFuture: ListenableFuture<ProcessCameraProvider> = ProcessCameraProvider.getInstance(context)
获取 ProcessCameraProvider
单例会返回 Future
,因为它可能需要异步初始化库。第一次获得它可能需要一些时间(通常不到一秒),但后续调用会立即返回,因为初始化已经执行。
手持 ProcessCameraProvider
,您可以开始与设备的摄像头进行交互。您可以使用 CameraSelector
选择要与之交互的相机,它为您要使用的相机包装了一组过滤器。通常,如果您只是想使用主后置或前置摄像头,则可以使用 CameraSelector.DEFAULT_BACK_CAMERA
或 CameraSelector.DEFAULT_FRONT_CAMERA
。
既然您已经定义了要使用的相机,您就可以构建您需要的用例。例如,您想拍摄一张照片,因此您将使用 ImageCapture
用例。它允许使用相机拍摄单个捕获帧(通常是高质量的),并将其作为原始缓冲区提供,或将其存储在文件中。要使用它,您可以根据需要对其进行配置,或者您可以让 CameraX 使用默认配置。
val imageCapture = ImageCapture.Builder().build()
在 CameraX 中,摄像头的生命周期由 LifecycleOwner
控制,这意味着当 LifecycleOwner
的生命周期开始时,摄像头打开,停止时,摄像头关闭。所以你需要选择一个生命周期来控制相机。如果您使用的是 Activity
,您通常希望相机在 Activity
开始时启动,并在它停止时停止,因此您可以使用 Activity
实例本身作为LifecycleOwner
,如果您使用的是 Fragment
,您可能希望使用其视图生命周期 (Fragment.getViewLifecycleOwner()
)。
最后,您需要将拼图的各个部分拼在一起。
processCameraProvider.bindToLifecycle(
lifecycleOwner,cameraSelector,imageCapture
)
应用通常包含一个显示相机预览的取景器,因此您可以使用 Preview
用例,并将其与 ImageCapture
用例绑定。 Preview
用例允许将相机帧流式传输到 Surface
。由于设置 Surface
并在其上正确绘制预览可能很复杂,因此 CameraX 提供了 PreviewView
,这是一个 View
,可与 Preview
用例一起使用以显示相机预览。您可以查看如何使用它们 here。
// Just like ImageCapture,you can configure the Preview use case if you'd wish.
val preview = Preview.Builder().build()
// Provide PreviewView's Surface to CameraX. The preview will be drawn on it.
val previewView: PreviewView = findViewById(...)
preview.setSurfaceProvider(previewView.surfaceProvider)
// Bind both the Preview and ImageCapture use cases
processCameraProvider.bindToLifecycle(
lifecycleOwner,imageCapture,preview
)
现在要实际拍照,您可以使用 ImageCapture
的 takePicture
方法之一。一个提供捕获图像的 JPEG 原始缓冲区,另一个将其保存在您提供的文件中(如果需要,请确保您拥有必要的存储权限)。
imageCapture.takePicture(
ContextCompat.getMainExecutor(context),// Defines where the callbacks are run
object : ImageCapture.OnImageCapturedCallback() {
override fun onCaptureSuccess(imageProxy: ImageProxy) {
val image: Image = imageProxy.image // Do what you want with the image
imageProxy.close() // Make sure to close the image
}
override fun onError(exception: ImageCaptureException) {
// Handle exception
}
}
)
val imageFile = File("somePath/someName.jpg") // You can store the image in the cache for example using `cacheDir.absolutePath` as a path.
val outputFileOptions = ImageCapture.OutputFileOptions
.Builder(imageFile)
.build()
takePicture(
outputFileOptions,CameraXExecutors.mainThreadExecutor(),object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
}
override fun onError(exception: ImageCaptureException) {
}
}
)
我真的需要写 500 行代码来简单地拍照吗? 这怎么会被认为是“比以前更简单”?
CameraXBasic 并不像其名称所暗示的那样“基本” x) 它更像是 CameraX 3 个用例的完整示例。尽管 CameraFragment
很长,但它很好地解释了事情,因此每个人都更容易理解。
CameraX“比以前更简单”,之前主要指的是Camera2,至少上手难度更大一些。 CameraX 通过其使用用例的方法提供了对开发人员更友好的 API。它还处理兼容性,这在以前是一个大问题。确保您的相机应用在大多数 Android 设备上可靠运行非常具有挑战性。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。