【问题标题】:Android CameraX doesn't show anythingAndroid CameraX 不显示任何内容
【发布时间】:2019-09-27 13:47:53
【问题描述】:

我已经实现了一个新示例,这里是 a link,它描述了来自 Google codelabs 的新 CameraX api,但 TextureView 没有显示任何内容并抛出下一个异常:

OpenGLRenderer:[SurfaceTexture-0-7609-1] dequeueImage:SurfaceTexture 未附加到视图

作为 Camera2 和本机相机应用程序的另一个相机示例工作正常 我使用了 api level Q beta 3 的模拟器

类 CameraXFragment : Fragment(), TextureView.SurfaceTextureListener { 伴随对象{ 有趣的 newInstance(): Fragment = CameraXFragment() } 私人 val REQUEST_CODE_PERMISSIONS = 10 私有 val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE) 覆盖 fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.fragment_camera,容器,假) 覆盖乐趣 onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewFinder.surfaceTextureListener = 这个 } 私人乐趣 startCamera() { CameraX.unbindAll() val previewConfig = PreviewConfig.Builder().apply { setTargetAspectRatio(Rational(1, 1)) setTargetResolution(大小(320, 320)) }。建造() val 预览 = 预览(previewConfig) preview.setOnPreviewOutputUpdateListener { viewFinder.surfaceTexture = it.surfaceTexture 更新转换() } val imageCaptureConfig = ImageCaptureConfig.Builder() 。申请 { setTargetAspectRatio(Rational(1, 1)) setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY) }。建造() val imageCapture = ImageCapture(imageCaptureConfig) captureButton.setOnClickListener { val 文件 = 文件(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),“${System.currentTimeMillis()}.jpg”) imageCapture.takePicture(文件, 对象:ImageCapture.OnImageSavedListener { 覆盖 fun onError(error: ImageCapture.UseCaseError, message: String, t: Throwable?) { t?.printStackTrace() } 覆盖乐趣 onImageSaved(file: File) { val msg = "照片拍摄成功:${file.absolutePath}" Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show() } }) } CameraX.bindToLifecycle(this, preview, imageCapture) } 私人乐趣 updateTransform() { val 矩阵 = 矩阵() 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 否则->返回 } matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY) viewFinder.setTransform(矩阵) } 覆盖乐趣 onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) { } 覆盖乐趣 onSurfaceTextureUpdated(surface: SurfaceTexture) { } 覆盖乐趣 onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean { 返回真 } 覆盖乐趣 onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) { if (allPermissionsGranted()) { viewFinder.post { startCamera() } } 别的 { 请求权限(REQUIRED_PERMISSIONS,REQUEST_CODE_PERMISSIONS) } viewFinder.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> 更新转换() } } 覆盖乐趣 onRequestPermissionsResult(requestCode: Int, 权限: Array, grantResults: IntArray) { if (requestCode == REQUEST_CODE_PERMISSIONS) { if (allPermissionsGranted()) { viewFinder.post { startCamera() } } 别的 { Toast.makeText(requireContext(), "权限未授予", Toast.LENGTH_SHORT).show() } } } 私人乐趣 allPermissionsGranted(): Boolean { for(REQUIRED_PERMISSIONS 中的权限){ if (ContextCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED) { 返回假 } } 返回真 } }

【问题讨论】:

  • 嘿,我将图像向右旋转,你有这个问题吗??
  • 这是由于无效元数据导致的库中的错误!但仅适用于前置镜头!希望这将通过 beta 修复!
  • 这个问题解决了吗?我面临同样的问题。当我将生命周期绑定到 preview 时,它工作正常,但绑定到 imageCapture 时出现黑屏

标签: android android-camerax


【解决方案1】:

TextureView 需要从父视图中移除并重新添加,才能附加 SurfaceTexture。这是因为 TextureView 一旦附加到视图层次结构,就会在内部创建自己的 SurfaceTexture,并且只有在从视图层次结构中删除父 TextureView 时,内部 SurfaceTexture 才会正确分离。您应该将preview.setOnPreviewOutputUpdateListener 更改为:

preview.setOnPreviewOutputUpdateListener {
    val parent = viewFinder.parent as ViewGroup
    parent.removeView(viewFinder)
    viewFinder.surfaceTexture = it.surfaceTexture
    parent.addView(viewFinder, 0)
    updateTransform()
}

看起来您可能从 codelab 复制了代码,该代码现已更新以包含视图重新附加。 official sample 也实现了这个视图重新附加。

【讨论】:

  • 这应该是公认的答案。它为我解决了问题。
  • 我同意@Mauro Banze
  • 这绝对解决了我的问题。尽管它看起来更像是 Vodoo 糟糕的设计,而不是定义明确的 API。
  • setOnPreviewOutputUpdateListener 不再存在!!
【解决方案2】:

Java 中 Oscar Wahltinez 的 Kotlin code

ViewGroup parent = (ViewGroup) textureView.getParent();
parent.removeView(textureView);
parent.addView(textureView, 0);
SurfaceTexture surfaceTexture = previewOutput.getSurfaceTexture();
textureView.setSurfaceTexture(surfaceTexture);

【讨论】:

    【解决方案3】:

    我在关注 codeLabs 时遇到了同样的问题。我锁定屏幕然后再次打开它,突然它可以正常工作了,捕获功能也可以正常工作。 我对这种情况一无所知,但您可以尝试这种方式作为解决方法。我在 Pixel 3 中使用 Q beta 3。

    PS:您可以只触发 Activity 的 onStop 和 onStart 事件(例如:按 home 并再次打开应用程序),实时预览将起作用。在我看来,我认为这个问题与CameraX.bindToLifecycle有关。

    【讨论】:

    • 您的解决方案效果很好!肯定是bindToLifecycle()方法里面的问题,注释掉这个方法的时候,Logcat中没有出现异常,但是预览也没有效果
    • 因为bindToLifeCycle()是CameraX流程的一部分,根据activity/fragment生命周期检测预览应该何时开始或停止,所以我们绝对需要它。您可以参考 cameraX 文档或观看 Google IO 2019 中的 CameraX 会话:youtu.be/kuv8uK-5CLY 以获取更多信息。除了等待 Google 解决此问题外,我们无事可做 :)。
    【解决方案4】:

    除了this回答。我通过从 AndroidManifest.xml 文件中删除应用程序级别 hardwareAccelerated="false" 行解决了我的问题。

    【讨论】:

      【解决方案5】:

      这段代码对我有用

        val parent = viewFinder.parent as ViewGroup
        parent.removeView(viewFinder)
        parent.addView(viewFinder, 0)
        val surfaceTexture: SurfaceTexture = it.surfaceTexture
        viewFinder.setSurfaceTexture(surfaceTexture)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多