返回
Camera2入门:TextureView实现预览和拍照
Android
2023-02-09 09:10:59
使用 Camera2 API 和 TextureView 实现 Android 相机功能
相机预览
在 Android 应用中实现相机预览需要以下步骤:
- 添加 TextureView: TextureView 是一种专门用于处理图像和视频内容的视图控件。在布局文件中添加 TextureView 以显示相机预览:
<TextureView
android:id="@+id/texture_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- 添加监听事件: TextureView 提供了一个监听器,当其 SurfaceTexture 可用时触发。在代码中添加监听器:
TextureView textureView = findViewById(R.id.texture_view);
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
// 当 SurfaceTexture 可用时,设置相机参数并打开相机
}
- 设置相机参数并打开相机: 当 SurfaceTexture 可用时,我们需要设置相机参数并打开相机:
private void setupCamera(int width, int height) {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
String cameraId = cameraManager.getCameraIdList()[0];
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
// 设置预览尺寸
Size previewSize = streamConfigurationMap.getOutputSizes(SurfaceTexture.class)[0];
// 创建相机预览会话
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
Surface surface = new Surface(surfaceTexture);
List<Surface> outputSurfaces = new ArrayList<>();
outputSurfaces.add(surface);
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
// 相机已打开,开始预览
cameraDevice.createCaptureSession(outputSurfaces, new CaptureSession.StateCallback() {
@Override
public void onConfigured(CaptureSession session) {
try {
// 设置预览请求
CaptureRequest.Builder previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(surface);
CaptureRequest previewRequest = previewRequestBuilder.build();
// 开始预览
session.setRepeatingRequest(previewRequest, null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}, null);
}
};
cameraManager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
拍照
要实现拍照,我们需要执行以下步骤:
- 创建 CameraCaptureSession.CaptureCallback: CameraCaptureSession.CaptureCallback 用于处理拍照完成后的操作:
private final CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
// 拍照完成
}
};
- 创建 CaptureRequest.Builder: CaptureRequest.Builder 用于设置拍照参数:
CaptureRequest.Builder captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(imageReader.getSurface());
- 创建 CaptureRequest: CaptureRequest 是最终用于拍照的请求:
CaptureRequest captureRequest = captureRequestBuilder.build();
- 开始拍照: 使用 CaptureSession 发出拍照请求:
cameraSession.capture(captureRequest, captureCallback, null);
常见问题解答
-
如何调整相机分辨率?
- 可以在
StreamConfigurationMap
中找到受支持的分辨率列表,并在createCaptureRequest
中设置所需的尺寸。
- 可以在
-
如何控制对焦和曝光?
- Camera2 API 允许使用
CaptureRequest.Builder
设置对焦和曝光参数,如对焦模式和曝光时间。
- Camera2 API 允许使用
-
如何保存捕获的图像?
- 创建一个
ImageReader
来捕获图像数据,并在onCaptureCompleted
回调中保存图像。
- 创建一个
-
如何实现连拍模式?
- 使用
createBurstCaptureRequestList
方法创建突发请求列表,然后使用setRepeatingBurst
方法设置突发模式。
- 使用
-
如何使用前置和后置摄像头?
- CameraManager 提供了
getCameraIdList
方法,可以用来获取设备上的可用摄像头列表,其中包括前置和后置摄像头。
- CameraManager 提供了