Camera2打开相机,建立会话,并监听相机流(以拍照为例)
- 获取 CameraManager
- 通过 CameraManager.openCamera() 方法打开相机,监听回调,获取 CameraDevice
- 通过 CameraDevice.createCaptureSession() 方法,建立会话,监听回调,获取 CameraCaptureSession
- 创建 CaptureRequest
- CameraCaptureSession 通过 setRepeatingRequest 或 capture 方法,进行会话,通过捕获相机流,对相机流进行处理
- 细节
-
获取 CameraManager
(CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
-
通过 CameraManager.openCamera() 方法打开相机,监听回调,获取 CameraDevice
/**
* 参数
* cameraId 前置或后置摄像头ID,前置 1 后置 0
* callback
* handler 表示 openCamera 代码运行所在的线程,传null,表示运行在当前线程
*/
mCameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
}
}, null);
-
通过 CameraDevice.createCaptureSession() 方法,建立会话,监听回调,获取 CameraCaptureSession
// width 和 height 与 surfaceview 的相同
//ImageReader 用于接收处理(拍照、录像)的相机流
//SurfaceView 用于接收预览的相机流
ImageReader mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
List<Surface> surfaces = new ArrayList<>();
surfaces.add(surfaceView.getHolder().getSurface());
surfaces.add(mImageReader.getSurface());
/**
* 参数
* outputs 相机流输出的地方
* callback
* handler 表示 createCaptureSession 代码运行所在的线程,传null,表示运行在当前线程
*/
mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mCameraCaptureSession = session;
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
}
}, null);
-
创建 CaptureRequest
// 创建用于预览的CaptureRequest
CaptureRequest.Builder captureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
//相机流输出的位置
captureRequest.addTarget(surfaceViewSurface);
CaptureRequest build = captureRequest.build();
// 创建用于处理照片的CaptureRequest
CaptureRequest.Builder captureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
//相机流输出的位置
captureRequest.addTarget(mImageReader.getSurface());
CaptureRequest build = captureRequest.build();
-
CameraCaptureSession 通过 setRepeatingRequest 或 capture 方法,进行会话,通过捕获相机流,对相机流进行处理
//连续通信,用于预览
mCameraCaptureSession.setRepeatingRequest(captureRequest.build(), null, null);
//一次通讯,用于拍照
//先将 mImageReader 中的内容清空
while (mImageReader.acquireNextImage() != null){
}
// mImageReader 捕获相机流中的信息
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
// 转成 Bitmap
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] b = new byte[buffer.capacity()];
buffer.get(b, 0 , b.length);
Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
// 释放 Image,否则,不能进行下次捕获,因为定义时,设置的只能捕获一张图片
image.close();
}
}, null);
CaptureRequest.Builder captureRequest = mCameraCaptureSession.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequest.addTarget(mImageReader.getSurface());
//进行通信
mCameraCaptureSession.capture(captureRequest.build(), null, null);
-
细节
- SurfaceView 使用时,必须已经在界面中显示,否则,获取 surface 时,会异常
- ImageReader 捕获照片时,Image 处理完后,必须执行 image.close()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)