CameraDevice
是一个连接的相机设备代表,你可以把它看作为相机设备在 java 代码中的表现。类比于旧 API 中的 Camera
类。
官方文档链接:https://developer.android.google.cn/reference/android/hardware/camera2/CameraDevice
通过 CameraManager
的 openCamera()
方法打开相机,在 CameraDevice.StateCallback
的 onOpened(CameraDevice camera)
方法中可获得 CameraDevice 的实例。
示例:
private int mCameraId = CameraCharacteristics.LENS_FACING_FRONT;
private CameraManager mCameraManager; // 相机管理者
private CameraDevice mCameraDevice; // 相机对象
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera; // 获取到可用的 CameraDevice 实例
// 当相机成功打开时回调该方法,接下来可以执行创建预览的操作
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
// 当相机断开连接时回调该方法,应该在此执行释放相机的操作
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
// 当相机打开失败时,应该在此执行释放相机的操作
}
@Override
public void onClosed(@NonNull CameraDevice camera) {
// 当相机关闭时回调该方法,这个方法可以不用实现
}
};
public void openCamera() {
try {
// 前处理
mCameraManager.openCamera(Integer.toString(mCameraId), mStateCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
只有一个 CameraDevice.StateCallback
的内部类,当相机状态发生变化时,会调用该类相应的回调方法。
相应的回调方法介绍在上面的示例中已经说明了,下面介绍一下 onError
回调方法中相应的错误码把:
错误码 | 描述 |
---|---|
CameraDevice.StateCallback.ERROR_CAMERA_IN_USE | 当前相机设备已经在一个更高优先级的地方打开了 |
CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE | 已打开相机数量到上限了,无法再打开新的相机了 |
CameraDevice.StateCallback.ERROR_CAMERA_DISABLED | 由于相关设备策略该相机设备无法打开,详细可见 DevicePolicyManager 的 setCameraDisabled(ComponentName, boolean) 方法 |
CameraDevice.StateCallback.ERROR_CAMERA_DEVICE | 相机设备发生了一个致命错误 |
CameraDevice.StateCallback.ERROR_CAMERA_SERVICE | 相机服务发生了一个致命错误 |
关闭对应的相机设备。
使用指定模板创建一个 CaptureRequest.Builder
用于新的捕获请求构建。
templateType | 描述 | 适用性 |
---|---|---|
TEMPLATE_PREVIEW | 用于创建一个相机预览请求。相机会优先保证高帧率而不是高画质 | 所有相机设备 |
TEMPLATE_STILL_CAPTURE | 用于创建一个拍照请求。相机会优先保证高画质而不是高帧率 | 所有相机设备 |
TEMPLATE_RECORD | 用于创建一个录像请求。相机会使用标准帧率,并设置录像级别的画质 | 所有相机设备 |
TEMPLATE_VIDEO_SNAPSHOT | 用于创建一个录像时拍照的请求。相机会尽可能的保证照片质量的同时不破坏正在录制的视频质量 | 硬件支持级别高于 LEGACY 的相机设备 |
TEMPLATE_ZERO_SHUTTER_LAG | 用于创建一个零延迟拍照的请求。相机会尽可能的保证照片质量的同时不损失预览图像的帧率,3A(自动曝光、自动聚焦、自动白平衡)都为 auto 模式 | 支持 PRIVATE_REPROCESSING 和 YUV_REPROCESSING 的相机设备 |
TEMPLATE_MANUAL | 用于创建一个手动控制相机参数的请求。相机所有自动控制将被禁用,后期处理参数为预览质量,手动控制参数被设置为合适的默认值,需要用户自己根据需求来调整各参数 | 支持 MANUAL_SENSOR 的相机设备 |
使用一个指定的 Surface 输出列表创建一个相机捕捉会话。
参数说明:
onConfigured(CameraCaptureSession session)
方法。获得当前相机设备的 id。
针对第二条和第三条,简单的使用如下:
try {
// templateType 使用 TEMPLATE_PREVIEW,即创建一个相机预览请求
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mCaptureRequestBuilder.addTarget(mPreviewSurface); // 设置预览输出的 Surface
// mPreviewSurface 是用于预览输出的 Surface
// mImageReader.getSurface() 是用于拍照输出的 Surface
mCameraDevice.createCaptureSession(Arrays.asList(mPreviewSurface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
if (mCameraDevice == null) {
return;
}
mCaptureSession = session;
try {
// 设置连续自动对焦
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// 设置关闭闪光灯
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.FLASH_MODE_OFF);
// 生成一个预览的请求
mPreviewRequest = mPreviewRequestBuilder.build();
// 开始预览,即设置反复请求
mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Log.e(TAG, "ConfigureFailed.");
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
上面介绍适用性时提到了硬件支持级别。在 Camera2 中,相机设备支持的硬件等级有
LEVEL_3 > FULL > LIMIT > LEGACY
对于大多数的手机而言,都会支持到 FULL
或 LIMIT
。当支持到 FULL
等级的相机设备,将拥有比旧 API 强大的新特性,如 30fps 全高清连拍,帧之间的手动设置,RAW 格式的图片拍摄,快门零延迟以及视频速拍等,否则和旧 API 功能差别不大。
通过 CameraCharacteristics
类获取相机设备的特性,包括硬件等级的支持等级.
CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(mCameraId);
int hardwareLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);