You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中使用CameraX仅显示黑屏问题求助(Kotlin)

CameraX预览黑屏问题解决方案

核心问题分析

你的代码存在两个关键错误导致预览黑屏:

  1. 变量类型不匹配:pv_camera被声明为View,但布局里实际是androidx.camera.view.PreviewView,类型不兼容导致无法正确传递相机预览的Surface。
  2. SurfaceProvider设置错误:手动创建Preview.SurfaceProvider并传入View的方式不符合CameraX规范,正确做法是直接使用PreviewView自带的surfaceProvider。

修正后的代码

MainActivity.kt

package com.example.testcamerax

import android.Manifest
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class MainActivity : AppCompatActivity() {

    private lateinit var cameraExecutor: ExecutorService
    private lateinit var pv_camera: PreviewView // 修正为PreviewView类型

    companion object {
        private const val TAG = "CameraX"
        private const val FILE_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
        private const val PERMISSION_CODE = 10
        private val PERMISSION = arrayOf(Manifest.permission.CAMERA)
    }

    private fun allPermissionGranted() = PERMISSION.all {
        ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        pv_camera = findViewById(R.id.pv_camera) // 提前初始化View

        if (allPermissionGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(this, PERMISSION, PERMISSION_CODE)
        }

        cameraExecutor = Executors.newSingleThreadExecutor()
    }

    override fun onDestroy() {
        super.onDestroy()
        cameraExecutor.shutdown()
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if (requestCode == PERMISSION_CODE) {
            if (allPermissionGranted()) {
                startCamera()
            } else {
                Toast.makeText(this, "Permission error", Toast.LENGTH_SHORT).show()
                finish()
            }
        }
    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()
            val preview = Preview.Builder().build()
                .also {
                    // 直接使用PreviewView自带的surfaceProvider
                    it.setSurfaceProvider(pv_camera.surfaceProvider)
                }
            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

            try {
                cameraProvider.unbindAll()
                cameraProvider.bindToLifecycle(
                    this, cameraSelector, preview
                )
            } catch (e: Exception) {
                Log.e(TAG, "Bind error: ${e.message}", e) // 打印具体错误便于排查
            }

        }, ContextCompat.getMainExecutor(this))
    }
}

额外注意事项

  • 确保build.gradle中添加了正确的CameraX依赖(建议使用最新稳定版):
    dependencies {
        def camerax_version = "1.3.0"
        implementation "androidx.camera:camera-core:$camerax_version"
        implementation "androidx.camera:camera-camera2:$camerax_version"
        implementation "androidx.camera:camera-view:$camerax_version"
        implementation "androidx.camera:camera-lifecycle:$camerax_version"
    }
    
  • 权限申请逻辑正常,但可在权限拒绝时补充更友好的引导提示。

内容的提问来源于stack exchange,提问作者user21830153

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:05:30