Android CameraX没有显示任何内容 [英] Android CameraX doesn't show anything
问题描述
我已经实现了一个新示例,这里是链接描述了Google代码实验室中的新CameraX api,但TextureView没有显示任何内容并抛出下一个异常:
I've implemented a new sample, here is a link which describes new CameraX api from Google codelabs, but TextureView doesn't show anything and throw next exception:
OpenGLRenderer:[SurfaceTexture-0-7609 -1] dequeueImage:SurfaceTexture未附加到View
作为Camera2和本机照相机应用程序的另一个照相机示例可以正常工作
我使用的模拟器api级为Q beta 3
Another camera samples as a Camera2 and native camera app work fine I used emulator with api level Q beta 3
class CameraXFragment : Fragment(), TextureView.SurfaceTextureListener {
companion object {
fun newInstance(): Fragment = CameraXFragment()
}
private val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.fragment_camera, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewFinder.surfaceTextureListener = this
}
private fun startCamera() {
CameraX.unbindAll()
val previewConfig = PreviewConfig.Builder().apply {
setTargetAspectRatio(Rational(1, 1))
setTargetResolution(Size(320, 320))
}.build()
val preview = Preview(previewConfig)
preview.setOnPreviewOutputUpdateListener {
viewFinder.surfaceTexture = it.surfaceTexture
updateTransform()
}
val imageCaptureConfig = ImageCaptureConfig.Builder()
.apply {
setTargetAspectRatio(Rational(1, 1))
setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
}.build()
val imageCapture = ImageCapture(imageCaptureConfig)
captureButton.setOnClickListener {
val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "${System.currentTimeMillis()}.jpg")
imageCapture.takePicture(file,
object : ImageCapture.OnImageSavedListener {
override fun onError(error: ImageCapture.UseCaseError, message: String, t: Throwable?) {
t?.printStackTrace()
}
override fun onImageSaved(file: File) {
val msg = "Photo capture succeeded: ${file.absolutePath}"
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
}
})
}
CameraX.bindToLifecycle(this, preview, imageCapture)
}
private fun updateTransform() {
val matrix = Matrix()
val centerX = viewFinder.width / 2f
val centerY = viewFinder.height / 2f
val rotationDegrees = when (viewFinder.display.rotation) {
Surface.ROTATION_0 -> 0
Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270
else -> return
}
matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)
viewFinder.setTransform(matrix)
}
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {
}
override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
}
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
return true
}
override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) {
if (allPermissionsGranted()) {
viewFinder.post { startCamera() }
} else {
requestPermissions(REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
viewFinder.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
updateTransform()
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
viewFinder.post { startCamera() }
} else {
Toast.makeText(requireContext(), "Permissions are not granted", Toast.LENGTH_SHORT).show()
}
}
}
private fun allPermissionsGranted(): Boolean {
for (permission in REQUIRED_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED) {
return false
}
}
return true
}
}
推荐答案
需要删除TextureView并从父视图重新添加以附加SurfaceTexture。这是因为一旦将TextureView附加到视图层次结构,它就会在内部创建自己的SurfaceTexture,并且只有从视图层次结构中删除了父TextureView之后,内部SurfaceTexture才能正确分离。您应该将 preview.setOnPreviewOutputUpdateListener
更改为:
The TextureView needs to be removed and re-added from the parent view for the SurfaceTexture to be attached. This is because TextureView internally creates its own SurfaceTexture once it is attached to the view hierarchy, and that internal SurfaceTexture only gets correctly detached once the parent TextureView is removed from the view hierarchy. You should change preview.setOnPreviewOutputUpdateListener
to:
preview.setOnPreviewOutputUpdateListener {
val parent = viewFinder.parent as ViewGroup
parent.removeView(viewFinder)
viewFinder.surfaceTexture = it.surfaceTexture
parent.addView(viewFinder, 0)
updateTransform()
}
似乎您已经从代码实验室复制了代码,现在已更新,包括视图重新连接。 官方示例也实现了该视图的重新附加。
It looks like you may have copied the code from the codelab, which has now been updated to include the view re-attachment. The official sample also implements this view re-attachment.
这篇关于Android CameraX没有显示任何内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!