Android 音视频开发(四) -- CameraX 实现预览、拍照功能
音视频 系列文章
Android 音视频开发(一) – 使用AudioRecord 录制PCM(录音);AudioTrack播放音频
Android 音视频开发(二) – Camera1 实现预览、拍照功能
Android 音视频开发(三) – Camera2 实现预览、拍照功能
Android 音视频开发(四) – CameraX 实现预览、拍照功能
Android 音视频开发(五) – 使用 MediaExtractor 分离音视频,并使用 MediaMuxer合成新视频(音视频同步)
音视频工程
一. Camerax 简介
在前面两章中,我们已经学习了 Camera1 Android 音视频开发(二) – Camera1 实现预览、拍照功能 和 Camera2 Android 音视频开发(三) – Camera2 实现预览、拍照功能,但从上面两章可以看出来,API 的调用还是比较繁琐的,而且像一些最佳尺寸,角度等还得自己算,从 Camera2 的开发流程就可以知道:
真的很难记住这些流程;google 也意识到这个问题,所以推出了 Camerax ,它虽然底层也是利用了 Camera2 的功能,但它的使用却更加简洁,它的主要优势如下:
- 更加简洁的 API 调用,基本十几行代码就能实现预览
- Camerax 为 Jetpack 的支持库,所以也具备感知生命周期的功能,即你无需自己释放 生命周期
- 更好兼容性
- 更多功能,比如图片分析等
注意,Camerax 也只支持 API21 及以上,本次效果如下:
二. Camerax 使用说明
Camerax 的使用非常简单,首先,添加关联库:
def camerax_version = "1.0.0-beta06"
// CameraX 核心库
implementation "androidx.camera:camera-camera2:$camerax_version"
// CameraX 生命周期
implementation "androidx.camera:camera-lifecycle:$camerax_version"
// CameraX view 集合,比如 cameraview,preview等
implementation "androidx.camera:camera-view:1.0.0-alpha10"
权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.any" />
2.1 预览
首先,先通过
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
返回当前可以绑定生命周期的 ProcessCameraProvider,ProcessCameraProvider 它会和宿主绑定生命周期,这样就不用担心打开相机和关闭的问题了。
接着,向 cameraProviderFuture 注册一个监听,第一个参数是一个 runnable,第二个参数是线程池,即runnable 运行在哪个线程中:
cameraProviderFuture.addListener(Runnable {}, ContextCompat.getMainExecutor(this))
上面我们让它运行在主线程的线程池中,这样,在这个 runnable 中,就可以配置我们的 capture 了:
//创建相机进程监听
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(new Runnable() {
@SuppressLint("RestrictedApi")
@Override
public void run() {
try {
//将相机的生命周期和activity的生命周期绑定,camerax 会自己释放,不用担心了
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
//预览的 capture,它里面支持角度换算
Preview preview = new Preview.Builder().build();
//创建图片的 capture
mImageCapture = new ImageCapture.Builder()
.setFlashMode(ImageCapture.FLASH_MODE_AUTO)
.build();
//选择后置摄像头
CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
//预览之前先解绑
cameraProvider.unbindAll();
//将数据绑定到相机的生命周期中
Camera camera = cameraProvider.bindToLifecycle(CameraxActivity.this, cameraSelector, preview, mImageCapture);
//将previewview 的 surface 给相机预览
preview.setSurfaceProvider(mViewFinder.createSurfaceProvider(camera.getCameraInfo()));
} catch (Exception e) {
e.printStackTrace();
}
}
},ContextCompat.getMainExecutor(this));
可以看到,使用 ProcessCameraProvider.getInstance(this) 获取当前的 ProcessCameraProvider 去监听宿主的生命周期。
创建并确认 CameraProvider 后,执行步骤如下
- 创建 Preview,使用 new Preview.Builder().build() 创建Preview,它是相机预览的数据流,图像数据会通过它来输出,比如输出到 Surface 中
- 创建 ImageCapture 用于拍照,这里的 builder 都可以设置参数,比如大小,曝光等
- 指定所需的相机 LensFacing 选项,这里直接使用后置即可
- 将所选相机和任意用例绑定到生命周期,通过 cameraProvider.bindToLifecycle,将宿主的生命周期,与 cameraSelector,preview和mImageCapture判定起来。
- 将 Preview 连接到 PreviewView,preview.setSurfaceProvider() 设置要预览的 surface
上面的的 mViewFinder 其实是一个 PreviewView ,这是一种可以剪裁、缩放和旋转以确保正确显示的 View,即不用你自己去设置预览的角度等问题了。
<androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
2.2. 拍照
上面已经设置了 mImageCapture,拍照呢,在 Camerax 中也很简单,使用 takePicture 即可,如下
public void takePhoto(View view) {
if (mImageCapture != null) {
File dir = new File(Constants.PATH);
if (!dir.exists()) {
dir.mkdirs();
}
//创建文件
File file = new File(Constants.PATH,"testx.jpg");
if (file.exists()) {
file.delete();
}
//创建包文件的数据,比如创建文件
ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build();
//开始拍照
mImageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
// Uri savedUri = outputFileResults.getSavedUri();
Toast.makeText(CameraxActivity.this, "保存成功: ", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
Toast.makeText(CameraxActivity.this, "保存失败", Toast.LENGTH_SHORT).show();
}
});
}
}
注释已经很清楚了,注意我们可以使用 ImageCapture.OutputFileOptions 让 Camerax 去帮我们保存图片文件。
参考:
https://codelabs.developers.google.com/codelabs/camerax-getting-started/#0
相关文章
- Qt Quick 配置android开发环境
- 在Android开发中,定时执行任务的3种实现方法
- 轻松实现语音识别的完整代码在android开发中
- Android车机应用开发实现嵌套显示第三方应用
- 【Android开发必看】系统掌握Android性能优化的机会终于等到了
- 华为Android开发面试后得出的面试秘诀
- android:ellipsize省略文字用法
- Android开发(25)--framebyframe帧动画并实现启动界面到主界面的跳转
- android开发之微信支付功能的实现
- android ndk开发(二)实现一个官方demo
- delphi xe5 android 开发实现手机打电话和发短信
- 无障碍开发(十四)之Android /iOS平台无障碍功能
- 《Android 美颜类相机开发汇总》第五章 Android OpenGLES 美颜定制实现
- 【0】Android开发官方语言-Kotlin学习资源汇总
- android开发之shape详解
- android开发之ExpandableListView的使用,实现类似QQ好友列表
- android开发之AlertDialog点击按钮之后不消失 分类: android 学习笔记 2015-07-15 18:07 89人阅读 评论(0) 收藏
- Android开发之RecyclerView实现流式布局
- android.view.WindowLeaked的解决办法
- Android开发——网络请求
- Android开发之ViewPager(实现滑动切换页面)
- Android开发之Toolbar(实现自定义工具栏)
- Android开发之ProgressBar控件(实现加载动画与条形进度条)
- Flutter Boost 混合开发实践与源码解析(以 Android 为例)
- React Native 集成分享第三方登录功能分享第三方登录模块开发(Android)