为什么在CameraDevice.StateCallback的onError方法中得到ERROR_CAMERA_DEVICE

问题描述 投票:3回答:1

我已经实现了Camera2 api。它在大多数设备上都能很好地运行,但是我收到了一些用户的报告,说它不允许他们拍照。我从那些用户那里获得了日志。当打开前置摄像头时,所有这些都在CameraDevice.StateCallback的onError方法中收到ERROR_CAMERA_DEVICE错误。此错误表明相机发生了致命错误,需要重新打开才能使用。 https://developer.android.com/reference/android/hardware/camera2/CameraDevice.StateCallback#ERROR_CAMERA_DEVICE

我编写了重新打开相机的代码,但每次都会再次发生错误。

有人知道为什么会发生这种情况以及如何解决吗?

以下是一些相关的实现:

override fun open(): Boolean {
        if (hasCamera) {
            try {

                val id = manager.cameraIdList[cameraId]

                val characteristics = manager.getCameraCharacteristics(id)
                val map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)

                map?.let {
                    imageDimension = map.getOutputSizes(SurfaceTexture::class.java)[0]
                }

                if (!isOpen) {
                    manager.openCamera(id, object : CameraDevice.StateCallback() {
                        override fun onOpened(camera: CameraDevice) {
                            isOpen = true
                            openCount++
                            this.cameraDevice = camera
                            startPreview(null)

                        }

                        override fun onDisconnected(camera: CameraDevice) {
                            this.cameraDevice = camera
                            close()
                        }

                        override fun onError(camera: CameraDevice, error: Int) {
                            this.cameraDevice = camera
                            close()
                            this.cameraDevice = null
                            if (openCount < 10) {
                                openCount++
                                open()

                            } 

                        }
                    }, null)
                }
            } catch (e: Exception) {
                Timber.e("open: $e")
            } catch (e: SecurityException) {
                Timber.e("open: $e")
            }
        }

        return hasCamera
    }

override fun startPreview(startPreviewFailCallback: (() -> Unit)?) {
        cameraDevice?.let { cameraDevice ->
            try {
                val texture = textureView.surfaceTexture ?: return
                imageDimension?.let {
                    texture.setDefaultBufferSize(it.width, it.height)
                } ?: kotlin.run {
                    texture.setDefaultBufferSize(640, 480)
                }

                surface = Surface(texture)
                captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
                captureRequestBuilder.addTarget(surface)
                val range = getRange()
                range?.let {
                    captureRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, getRange())
                }
                cameraDevice.createCaptureSession(Arrays.asList(surface), object : CameraCaptureSession.StateCallback() {
                    override fun onConfigured(@NonNull cameraCaptureSession: CameraCaptureSession) {
                        //The camera is already closed
                        if (null == cameraDevice) {
                            return
                        }
                        // When the session is ready, we start displaying the preview.
                        [email protected] = cameraCaptureSession
                        updatePreview()
                    }

                    override fun onConfigureFailed(@NonNull cameraCaptureSession: CameraCaptureSession) {
                        this.cameraCaptureSession = cameraCaptureSession

                    }
                }, null)
            } catch (e: CameraAccessException) {
                e.printStackTrace()
                Timber.e("startPreview: $e")
            } catch (e: SecurityException) {
                Timber.e("startPreview: $e")
            }
        } ?: kotlin.run {
            startPreviewFailCallback?.let {
                it.invoke()
            }
        }


    }

private fun updatePreview() {
        if (null == cameraDevice) {
            return
        }
        captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO)
        try {
            cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler)
        } catch (e: CameraAccessException) {
            e.printStackTrace()
            Timber.e("updatePreview: $e")
        } catch (e: IllegalStateException) {
            Timber.e("updatePreview: $e")
        }

    }
android android-camera2
1个回答
1
投票

我终于明白了。纹理视图默认缓冲区大小使用的大小太大。我通过遍历相机特性图的输出尺寸数组来修复它,并使用了最大尺寸960 x 1200以下的尺寸

val map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
map?.let {
                val sizesArray = map.getOutputSizes(SurfaceTexture::class.java)
                var smallest: Size = Size(0, 0)
                for (item in sizesArray) {
                    Timber.i("jpegSize: width: ${item.width}, height: ${item.height}")
                    if (item.height > smallest.height && item.height < 960 && item.width < 1200) {
                        smallest = item
                    }
                }
                imageDimension = smallest
            }

这里是开始预览时使用imageDimension的位置

imageDimension?.let {
                texture.setDefaultBufferSize(it.width, it.height)
            }
© www.soinside.com 2019 - 2024. All rights reserved.