Android CameraX ничего не показывает

Я реализовал новый пример, вот ссылка, которая описывает новый API CameraX из кодов Google, но TextureView ничего не показывает и выдает следующее исключение:

OpenGLRenderer: [SurfaceTexture-0-7609-1] dequeueImage: SurfaceTexture не прикреплен к представлению

Другие образцы камер, такие как Camera2 и приложение родной камеры, работают нормально. Я использовал эмулятор с уровнем API Q beta 3

класс CameraXFragment: Fragment(), TextureView.SurfaceTextureListener {сопутствующий объект {
        fun newInstance(): Fragment = CameraXFragment()
    } частное val REQUEST_CODE_PERMISSIONS = 10 частное val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMER__exmission_Rife_RIFERFIFERGE) onCreateView(inflater: LayoutInflater, контейнер: ViewGroup?, saveInstanceState: Bundle?): Просмотреть? = inflater.inflate(R.layout.fragment_camera, container, false) переопределить веселье onViewCreated(view: View, saveInstanceState: Bundle?) {
        super.onViewCreated(view, saveInstanceState)
        viewFinder.surfaceTextureListener = this
    } личное веселье startCamera() {
        CameraX.unbindAll()

        val previewConfig = PreviewConfig.Builder().apply {
            setTargetAspectRatio(Rational(1, 1))
            setTargetResolution(Size(320, 320))
        }.build()

        val preview = Preview(previewConfig)
        preview.setOnPreviewOutputUpdateListener {
            view, captureButton.setOnClickListener {
            val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "${System.currentTimeMillis()}.jpg")
            imageCapture.takePicture(file,
                    object: ImageCapture.OnImageSavedListener {переопределить fun onError (ошибка: ImageCapture.UseCaseError, message: String, t: Throwable?) {
                            t?.printStackTrace()
                        } переопределить fun onImageSaved(file: File) {
                            val msg = "Снимок успешно завершен: ${file.absolutePath}"
                            Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
                        }
                    })
        }

        CameraX.bindToLifecycle(this, preview, imageCapture)
    } личное увлечение updateTransform() {
        val matrix = Matrix()
        val centerXX = viewFinder.width / 2f
        val centerY = viewFinder.height / 2f
        val вращение Degrees = 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)
    } переопределить fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {
    } переопределить fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
    } переопределить fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {вернуть true
    }

    override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) {
        if (allPermissionsGranted()) {
            viewFinder.post { startCamera() }
        } else {
            requestPermissions(REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }geLay_Clayer_Выглядеть, _, _, _, _, _, _, _ ->
            updateTransform()
        }
    } переопределить забаву onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                viewFinder.post { startCamera() }
            } else {
                Toast.makeText(requireContext(), "Права не предоставлены", Toast.LENGTH_SHORT).show()
            }
        }
    } личное веселье allPermissionsGranted(): Boolean {
        for (разрешение в REQUIRED_PERMISSIONS) {
            if (ContextCompat.checkSelfPermission(requireContext(), разрешение)!= PackageManager.PERMISSION_GRANTED) {
                return false
            }
        } вернуть true
    }
}

5 ответов

TextureView необходимо удалить и повторно добавить из родительского представления для прикрепления SurfaceTexture. Это связано с тем, что TextureView внутренне создает свою собственную SurfaceTexture, как только она присоединена к иерархии представления, и эта внутренняя SurfaceTexture корректно отсоединяется только после удаления родительского TextureView из иерархии представления. Вы должны изменить preview.setOnPreviewOutputUpdateListener чтобы:

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

Похоже, что вы, возможно, скопировали код из кодовой метки, которая теперь была обновлена, чтобы включить повторное вложение представления. Официальный образец также реализует этот вид повторного вложения.

Я столкнулся с той же проблемой, когда следовал codeLabs. Я заблокировал экран, затем снова включил его, и вдруг он заработал нормально, функция захвата тоже сработала. Я понятия не имею об этой ситуации, но вы можете попробовать этот способ в качестве обходного пути. Я использую Q beta 3 в Pixel 3.

PS: Вы можете просто вызвать события onStop и onStart для Activity (например, нажмите home и снова откройте приложение), предварительный просмотр будет работать. На мой взгляд, я думаю, что эта проблема связана с CameraX.bindToLifecycle,

Если кто -то хочет, чтобы этот код на omtinez в Java, то здесь:

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

В дополнение к этому ответу. Я решил свою проблему, удалив уровень приложения hardwareAccelerated="false" строка из файла AndroidManifest.xml.

Этот код работает у меня

  val parent = viewFinder.parent as ViewGroup
  parent.removeView(viewFinder)
  parent.addView(viewFinder, 0)
  val surfaceTexture: SurfaceTexture = it.surfaceTexture
  viewFinder.setSurfaceTexture(surfaceTexture)
Другие вопросы по тегам