背景
Android开发工作过程中,经常需要用到camera相关能力,比如:人脸识别,ai识别,拍照预览,摄像头录制等等需求。都需要使用到camera,且需要拿到camera的预览数据。但是每次开发这块代码都比较繁琐,一大堆的接口(尤其是camera2),用错一个就容易出现意想不到的结果。所以这里我们将Android的camera做一次简单易用的封装,再也不用担心API用错了。
一、Camera的历史
在封装之前,我们先简单了解下camera的发展历史。目前Android有camera1和camera2两个不同版本的API。且camera1已经逐渐被抛弃了。那她两到底啥区别?
- Camera1(2010年推出) :
- 简单但僵化 :采用同步阻塞模型 ,调用
takePicture()
时整个相机管线阻塞,导致延迟高、功耗大。 - 有限控制 :参数调整(如曝光、对焦)通过
Camera.Parameters
实现,仅支持基础设置,无法精细控制。 - 高延迟:拍照后需等待图像处理完成才能继续操作。
- 资源浪费:预览和拍照无法并行,导致CPU/GPU利用率低。
- 硬件抽象层(HAL)简单:无法适配多摄像头、高帧率传感器(>30fps)或RAW格式。
- 功能缺失:不支持HDR+、人像模式等计算摄影需求。
- 独占式访问:仅允许单应用占用相机,其他应用需等待释放(如扫码时无法同时视频通话)。
- 简单但僵化 :采用同步阻塞模型 ,调用
- Camera2(2014年推出,Android 5.0+) :
- 异步管道模型 :引入
CaptureRequest
和CaptureSession
,支持非阻塞操作(如连拍、实时预览并行处理)。 - 精准控制:可独立配置传感器、闪光灯、处理算法(如手动调节ISO、快门速度)。
- 零复制流水线 :图像数据直接传递到
Surface
(如TextureView),减少内存拷贝。 - 批处理请求 :单次提交多个
CaptureRequest
(如同时预览+对焦+测光),提升帧率和能效比。 - 标准化HAL接口:统一控制不同厂商的相机硬件(如双摄、TOF传感器)。
- 高级功能支持:原生实现RAW拍摄、手动对焦轨迹、逻辑多摄像头(融合多个传感器数据)。
- 并发共享机制 :通过
CameraManager
协调多应用访问(如后台AR应用与前台相机APP共存)。
- 异步管道模型 :引入
特性 | Camera1 | Camera2 |
---|---|---|
架构模型 | 同步阻塞 | 异步非阻塞管道 |
性能 | 高延迟、低吞吐量 | 低延迟、高吞吐量(支持4K/60fps) |
硬件适配 | 仅基础单摄 | 多摄/RAW/高帧率传感器 |
功能扩展 | 基础拍照/录像 | HDR+/手动模式/计算摄影 |
多应用支持 | 独占访问 | 并发共享 |
二、封装核心能力
工作场景下对camera最常用的核心能力:开启摄像头,切换摄像头,预览,关闭摄像头,获取摄像头预览数据。
所以我们要封装的话就直接将这几个能力抽象成对应的接口。
Kotlin
package com.qt.camera.base
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.util.Range
import com.qt.camera.FUCameraConstants
import com.qt.camera.enumeration.FUCameraFacingEnum
import com.qt.camera.listener.OnFUCameraListener
/**
*
* DESC:Camera抽象类
* Created on 2021/10/22
* @author Jason Lu
*/
abstract class FUAbstractCamera {
/**
* 前置相机id
*/
@Volatile
var mFrontCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT
/**
* 后置相机id
*/
@Volatile
var mBackCameraId = Camera.CameraInfo.CAMERA_FACING_BACK
/**
* 曝光补偿
*/
@Volatile
var mExposureCompensation = FUCameraConstants.EXPOSURE_COMPENSATION
/**
* 相机采集帧率模式
* true:最大帧率输出 false:最大可选范围区间输出
*/
@Volatile
var mIsHighestRate = false
/**
* 相机后置角度
*/
@Volatile
var mBackCameraOrientation = FUCameraConstants.BACK_CAMERA_ORIENTATION
/**
* 当前相机前置角度
*/
@Volatile
var mFrontCameraOrientation = FUCameraConstants.FRONT_CAMERA_ORIENTATION
/**
* 当前相机朝向
*/
@Volatile
var mCameraFacing = FUCameraFacingEnum.CAMERA_FRONT
/**
* 当前相机输出分辨率-宽
*/
@Volatile
var mCameraWidth: Int = 1280
/**
* 当前相机输出分辨率-高
*/
@Volatile
var mCameraHeight: Int = 720
/**
* 当前相机角度
*/
@Volatile
var mCameraOrientation = mFrontCameraOrientation
/**
* 当前相机绑定纹理 Id
*/
@Volatile
var mCameraTexId = 100
/**
* 当前相机绑定 SurfaceTexture
*/
@Volatile
var mSurfaceTexture: SurfaceTexture? = null
/**
* 用户设置的相机绑定 SurfaceTexture
*/
@Volatile
var mCustomSurfaceTexture: SurfaceTexture? = null
/**
* 是否正在预览状态
*/
@Volatile
protected var mIsPreviewing = false
/**
* 是否只读ImageReader流
*/
@Volatile
var onlyReadImage = false
/**
* 是否需要停止预览
*/
@Volatile
protected var mIsNeedStopPreviewing = false
/**
* 事件回调
*/
@Volatile
protected var mCameraListener: OnFUCameraListener? = null
/**
* 自定义摄像头帧率范围
* 针对camera2
*/
var mRangeFps: Range<Int>? = null
/**
* 绑定数据回调
* @param listener OnFUCameraListener
*/
fun bindCameraListener(listener: OnFUCameraListener?) {
this.mCameraListener = listener
}
/**
* 资源释放
*/
open fun release() {
if (mIsPreviewing) {
closeCamera()
}
mCameraListener = null
}
/**
* 初始化相机
*/
abstract fun initCameraInfo()
/**
* 打开相机
*/
abstract fun openCamera()
/**
* 开启预览
*/
abstract fun startPreview()
/**
* 对焦
* @param viewWidth Int
* @param viewHeight Int
* @param rawX Float
* @param rawY Float
* @param areaSize Int
*/
abstract fun handleFocus(viewWidth: Int, viewHeight: Int, rawX: Float, rawY: Float, areaSize: Int)
/**
* 获取亮度
* @return Float
*/
abstract fun getExposureCompensation(): Float
/**
* 设置亮度
* @param value Float
*/
abstract fun setExposureCompensation(value: Float)
/**
* 分辨率变更处理
* @param cameraWidth Int
* @param cameraHeight Int
*/
abstract fun changeResolution(cameraWidth: Int, cameraHeight: Int)
/**
* 关闭相机
* @param releaseSurface 是否释放SurfaceTexture资源
*/
abstract fun closeCamera(releaseSurface:Boolean = true)
/**
* 切换相机前后置
*/
fun switchCamera(surfaceTexture: SurfaceTexture?) {
closeCamera(mCustomSurfaceTexture == null || surfaceTexture !=null)//如果使用用户自定义的surfaceTexture或者之前设置过surfaceTexture就release
mCameraFacing = if (mCameraFacing == FUCameraFacingEnum.CAMERA_FRONT) FUCameraFacingEnum.CAMERA_BACK else FUCameraFacingEnum.CAMERA_FRONT
mCameraOrientation = if (mCameraFacing == FUCameraFacingEnum.CAMERA_FRONT) mFrontCameraOrientation else mBackCameraOrientation
if(surfaceTexture!= null){
mCustomSurfaceTexture = surfaceTexture
}
openCamera()
}
/**
* 设置相机放大等级
*/
abstract fun setZoomRatio(zoomRatio: Float)
}
核心能力抽象出来后,剩下要做的就是camera1和camera2分别实现了。具体的实现这里就不贴代码了,给个github链接,各位自己下载直接用吧:GitHub - 279154451/Camera: Camera工具