前段时间,突然看到一篇文章说CameraX,了解了一番,发现这功能真好,能帮我们节省好多工作量,以前我们写Camera功能需要使用Camera2,要处理SufraceView相关的一堆东西,还有旋转、预览尺寸跟画面尺寸的选择,各品牌手机设备上的兼容性,搞不好就变形了,没上百行甚至几千行代码绝对搞不定,Google也意识到了这个问题,CameraX 正是为解决这个痛点而诞生的。
先看看官方对CameraX的定义:
更多说明可去参考官方文档:https://developer.android.google.cn/training/camerax
开始使用:
官方DEMO:camera-samples/CameraXBasic at main · android/camera-samples · GitHub
注意:CameraX最低支持API21,也就是5.0及以上,最新版对targetSdkVersion要求也比较高,最好能保持在31,支持AndroidX。
1 导入依赖
可查看CameraX的最新的版本
api "androidx.camera:camera-core:1.1.0-alpha12"
api "androidx.camera:camera-camera2:1.1.0-alpha12"
implementation "androidx.camera:camera-view:1.0.0-alpha32"
implementation "androidx.camera:camera-lifecycle:1.1.0-alpha12"
2 创建main.xml布局,引入PreviewView
<androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
3 初始化相机
/**
* 开始打开相机预览
*/
public void buildUseCameraCases() {
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(getContext());
cameraProviderFuture.addListener(new Runnable() {
@Override
public void run() {
try {
mCameraProvider = cameraProviderFuture.get();
bindCameraUseCases();
} catch (Exception e) {
e.printStackTrace();
}
}
}, ContextCompat.getMainExecutor(getContext()));
}
4 绑定拍照设置,获取ImageCapture对象
private void bindCameraImageUseCases() {
try {
int screenAspectRatio = aspectRatio(DensityUtil.getScreenWidth(getContext()), DensityUtil.getScreenHeight(getContext()));
int rotation = mCameraPreviewView.getDisplay().getRotation();
CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(lensFacing).build();
// Preview
Preview preview = new Preview.Builder()
.setTargetAspectRatio(screenAspectRatio)
.setTargetRotation(rotation)
.build();
// ImageCapture
mImageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.setTargetAspectRatio(screenAspectRatio)
.setTargetRotation(rotation)
.build();
// ImageAnalysis
mImageAnalyzer = new ImageAnalysis.Builder()
.setTargetAspectRatio(screenAspectRatio)
.setTargetRotation(rotation)
.build();
// Must unbind the use-cases before rebinding them
mCameraProvider.unbindAll();
// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
mCameraProvider.bindToLifecycle((LifecycleOwner) getContext(), cameraSelector, preview, mImageCapture, mImageAnalyzer);
// Attach the viewfinder's surface provider to preview use case
preview.setSurfaceProvider(mCameraPreviewView.getSurfaceProvider());
// setFlashMode
setFlashMode();
} catch (Exception e) {
e.printStackTrace();
}
}
5 执行拍照的方法
ImageCapture.OutputFileOptions outputFileOptions =
new ImageCapture.OutputFileOptions.Builder(new File(...)).build();
imageCapture.takePicture(outputFileOptions, cameraExecutor,
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
// insert your code here.
}
@Override
public void onError(ImageCaptureException error) {
// insert your code here.
}
}
);
6 视频录制
和拍照一样,绑定录制设置,获取VideoCapture对象,执行录制方法
private void bindCameraVideoUseCases() {
try {
CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(lensFacing).build();
// Preview
int rotation = mCameraPreviewView.getDisplay().getRotation();
Preview preview = new Preview.Builder()
.setTargetRotation(rotation)
.build();
// VideoCapture
VideoCapture.Builder builder = new VideoCapture.Builder();
builder.setTargetRotation(rotation);
if (videoFrameRate > 0) {
builder.setVideoFrameRate(videoFrameRate);
}
if (videoBitRate > 0) {
builder.setBitRate(videoBitRate);
}
mVideoCapture = builder.build();
// Must unbind the use-cases before rebinding them
mCameraProvider.unbindAll();
// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
mCameraProvider.bindToLifecycle((LifecycleOwner) getContext(), cameraSelector, preview, mVideoCapture);
// Attach the viewfinder's surface provider to preview use case
preview.setSurfaceProvider(mCameraPreviewView.getSurfaceProvider());
} catch (Exception e) {
e.printStackTrace();
}
}
mVideoCapture.startRecording(fileOptions, ContextCompat.getMainExecutor(getContext()),
new VideoCapture.OnVideoSavedCallback() {
@Override
public void onVideoSaved(@NonNull @NotNull VideoCapture.OutputFileResults outputFileResults) {
long minSecond = recordVideoMinSecond <= 0 ? CustomCameraConfig.DEFAULT_MIN_RECORD_VIDEO : recordVideoMinSecond;
if (recordTime < minSecond || outputFileResults.getSavedUri() == null) {
return;
}
Uri savedUri = outputFileResults.getSavedUri();
}
@Override
public void onError(int videoCaptureError, @NonNull @NotNull String message,
@Nullable @org.jetbrains.annotations.Nullable Throwable cause) {
}
});
关于特效方面,CameraX 提供了一个 Extensions API,用于使用制造商在各种 Android 设备(手机、平板电脑等)上实现的特效,但因为国内各厂商的定制,有一些特效还是不能通用的。
好了关于CameraX的介绍就到此为止,还有更多的功能细节需要自己去开发研究,学无止境。