Android Studio如何打开相机仅显示实时预览不触发拍照
Android 实现无拍照功能的相机实时预览+自定义叠加层
优先使用Jetpack CameraX实现,这是官方目前推荐的相机开发组件,已经封装了绝大多数设备的兼容逻辑,不需要自己处理预览尺寸适配、角度旋转、生命周期绑定等琐碎问题,且可以自由选择只启用预览能力,不会自带默认拍照UI。
1. 配置权限与依赖
首先在AndroidManifest.xml中添加必要的权限和特性声明:
<!-- 相机权限,仅预览不需要存储权限 --> <uses-permission android:name="android.permission.CAMERA" /> <!-- 声明应用依赖相机硬件,应用市场会自动过滤无相机的设备 --> <uses-feature android:name="android.hardware.camera" android:required="true" />
在模块级的build.gradle依赖块中添加CameraX相关依赖,版本号可选择当前最新的稳定版:
def camerax_version = "1.3.1" implementation "androidx.camera:camera-core:${camerax_version}" implementation "androidx.camera:camera-camera2:${camerax_version}" implementation "androidx.camera:camera-lifecycle:${camerax_version}" implementation "androidx.camera:camera-view:${camerax_version}"
Android 6.0及以上版本需要动态申请相机危险权限,在初始化相机前先校验权限状态,未授权时弹出系统权限申请弹窗,拿到权限后再执行相机初始化逻辑。
2. 编写布局实现叠加层
使用ConstraintLayout或者FrameLayout作为根布局,底层放置相机预览控件,上层直接放置任意你需要的叠加层控件即可——布局层级更高的View会自动悬浮在预览画面之上,不需要对相机做任何特殊配置。
示例布局代码:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 底层:相机预览控件,默认占满全屏 --> <androidx.camera.view.PreviewView android:id="@+id/previewView" android:layout_width="match_parent" android:layout_height="match_parent" app:scaleType="fillCenter" /> <!-- 上层:自定义叠加层,可自由添加任意View --> <!-- 示例:中间的识别框 --> <View android:id="@+id/recognize_frame" android:layout_width="240dp" android:layout_height="240dp" android:background="@drawable/frame_border" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> <!-- 示例:顶部提示文字 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="请将目标对准识别框" android:textColor="#FFFFFF" android:textSize="16sp" android:layout_marginTop="48dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
叠加层的View和普通页面View没有任何区别,可自由设置点击事件、动画、自定义绘制逻辑,不会影响底层相机预览。
3. 初始化相机,仅绑定预览用例
CameraX通过绑定不同用例实现不同功能:绑定ImageCapture对应拍照能力,绑定ImageAnalysis对应帧分析能力。如果只需要预览,仅绑定Preview预览用例即可,不会存在任何拍照相关的触发逻辑。
示例实现代码(Kotlin):
class CameraPreviewActivity : AppCompatActivity() { private lateinit var previewView: PreviewView private val cameraExecutor = Executors.newSingleThreadExecutor() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_camera_preview) previewView = findViewById(R.id.previewView) // 校验相机权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { startCameraPreview() } else { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQ_CAMERA_PERMISSION) } } private fun startCameraPreview() { val cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ val cameraProvider = cameraProviderFuture.get() // 仅配置预览用例 val preview = Preview.Builder() .build() .apply { surfaceProvider = previewView.surfaceProvider } // 选择默认后置摄像头,需要前置可替换为CameraSelector.DEFAULT_FRONT_CAMERA val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA try { cameraProvider.unbindAll() // 核心:仅绑定preview用例,不添加任何拍照、分析相关用例 cameraProvider.bindToLifecycle(this, cameraSelector, preview) } catch (e: Exception) { // 处理相机打开失败场景:相机被占用、设备不支持等 e.printStackTrace() Toast.makeText(this, "相机启动失败", Toast.LENGTH_SHORT).show() } }, ContextCompat.getMainExecutor(this)) } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQ_CAMERA_PERMISSION) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { startCameraPreview() } else { Toast.makeText(this, "需要相机权限才能使用预览功能", Toast.LENGTH_SHORT).show() finish() } } } override fun onDestroy() { super.onDestroy() cameraExecutor.shutdown() } companion object { private const val REQ_CAMERA_PERMISSION = 1001 } }
注意事项
- 不要通过系统相机Intent调用相机,这种方式会跳转到系统自带相机应用,你无法在其界面上添加自定义叠加层。
- 非必要不直接使用原生Camera2 API开发,Camera2需要自行处理数十种设备兼容问题、预览尺寸匹配、角度旋转、生命周期释放等逻辑,代码量是CameraX的5倍以上,容易出现兼容性bug。
- 如果需要在叠加层上做自定义绘制(比如人脸框、区域标记),直接自定义View重写
onDraw方法放在预览上层即可,不需要修改相机预览逻辑,也不需要获取预览帧数据。 - 叠加层的触摸事件不会被预览拦截,直接给上层View设置对应监听即可正常响应。
- PreviewView已经自动处理了横竖屏预览角度适配,你只需要自行处理叠加层在不同屏幕方向的布局适配即可。
内容的提问来源于stack exchange,提问作者Phantom37
相关产品推荐
相关产品推荐

