本篇介绍
Camera2相比Camera1,使用起来要复杂一些,不过也节省了一些逻辑,比如可以自动处理角度问题。本篇就按照流程介绍下Camera2的简单使用,更多细节会后续介绍。
使用Camera2
- 申请权限
静态申请:
<uses-permission android:name="android.permission.CAMERA" />
动态申请:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
return;
}
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE);
- 获取目标Camera
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
String[] ids = manager.getCameraIdList();
for (String id : ids) {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
if (characteristics == null) {
continue;
}
if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
mCameraId = id;
break;
}
}
if (mCameraId == null) {
return;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
- 打开Camera:
if (mCameraId == null) {
return;
}
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
return;
}
manager.openCamera(mCameraId, new StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraOpenCloseLock.release();
mCamera = camera;
createCameraPreviewSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
mCameraOpenCloseLock.release();
camera.close();
mCamera = null;
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
mCameraOpenCloseLock.release();
camera.close();
mCamera = null;
}}, handler);
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
这儿可以看到打开Camera是一个异步操作,因此添加了一个信号量mCameraOpenCloseLock,用来间接让操作变成同步。这样就可以避免打开Camera还没完成,就关闭Camera时出现的不可预料的问题。
在Camera打开的回调中,就可以发送预览请求了。
- 请求预览
private void createCameraPreviewSession() {
try {
mCaptureRequestBuilder = mCamera.createCaptureRequest(TEMPLATE_PREVIEW);
mCaptureRequestBuilder.addTarget(mSurfaceView.getHolder().getSurface());
mCamera.createCaptureSession(Arrays.asList(mSurfaceView.getHolder().getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
mCaptureSession = cameraCaptureSession;
if (mCaptureSession != null) {
try {
mCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(), null, null); // 连续请求
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
- 关闭Camera:
try {
mCameraOpenCloseLock.acquire();
mCaptureSession.stopRepeating();
mCamera.close();
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mCameraOpenCloseLock.release();
}