Saya telah menerapkan api Camera2. Ini berfungsi dengan baik di sebagian besar perangkat, tetapi saya mendapat beberapa laporan dari pengguna bahwa itu tidak akan membiarkan mereka mengambil gambar. Saya mendapat log dari pengguna tersebut. Semuanya mendapatkan kesalahan ERROR_CAMERA_DEVICE dalam metode onError dari CameraDevice.StateCallback yang saya lewati saat membuka kamera yang menghadap ke depan. Kesalahan ini menyatakan bahwa kesalahan fatal telah terjadi pada kamera dan perlu dibuka kembali untuk digunakan. https://developer.android.com/reference/android/ hardware/camera2/CameraDevice.StateCallback#ERROR_CAMERA_DEVICE

Saya menulis kode yang membuka kembali kamera, tetapi setiap kali, kesalahan terjadi lagi.

Adakah yang tahu mengapa ini bisa terjadi dan bagaimana saya bisa memperbaikinya?

Berikut adalah beberapa implementasi yang relevan:

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.
                        this@CameraNew.cameraCaptureSession = 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")
        }

    }
3
Anna Harrison 10 Maret 2020, 18:57

1 menjawab

Jawaban Terbaik

Saya akhirnya mengetahuinya. Tampilan tekstur ukuran buffer default menggunakan ukuran yang terlalu besar. Saya memperbaikinya dengan mengulangi array ukuran output dari peta karakteristik kamera dan menggunakan ukuran terbesar di bawah 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
            }

Dan di sinilah saya menggunakan imageDimension saat memulai pratinjau

imageDimension?.let {
                texture.setDefaultBufferSize(it.width, it.height)
            }
2
Anna Harrison 16 April 2020, 21:58