前面两篇介绍了Camera1和Camera2的使用,发现Camera API从1到2的变化非常大,Camera2的复杂度提升了不少,官方为了让我们更容易使用Camera,出了个一个官方的库cameraview。不过这个库已经Deprecated,官方建议使用Jetpack CameraX 替代。本篇文章就介绍下CameraView和CameraX的使用

CameraView

CameraView的目的就是帮助开发者能够快速集成Camera1和Camera2的特性,可以用下面这张表来说明:

API Level

Camera API

Preview View

9-13

Camera1

SurfaceView

14-20

Camera1

TextureView

21-23

Camera2

TextureView

24

Camera2

SurfaceView

开发流程

CameraView定义

xml中定义

android:id="@+id/camera"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:keepScreenOn="true"

android:adjustViewBounds="true"

app:autoFocus="true"

app:aspectRatio="4:3"

app:facing="back"

app:flash="auto"/>

xml中可以配置:

autoFocus:是否自动对焦

aspectRatio:预览画面比例

facing:前后摄像头

flash:闪光灯模式

增加生命周期

@Override

protected void onResume() {

super.onResume();

mCameraView.start();

}

@Override

protected void onPause() {

mCameraView.stop();

super.onPause();

}

这样声明后,就可以完成预览的工作了

相机状态回调

在xml声明CameraView后,增加回调

if (mCameraView != null) {

mCameraView.addCallback(mCallback);

}

...

private CameraView.Callback mCallback

= new CameraView.Callback() {

@Override

public void onCameraOpened(CameraView cameraView) {

Log.d(TAG, "onCameraOpened");

}

@Override

public void onCameraClosed(CameraView cameraView) {

Log.d(TAG, "onCameraClosed");

}

@Override

public void onPictureTaken(CameraView cameraView, final byte[] data) {

Log.d(TAG, "onPictureTaken " + data.length);

Toast.makeText(cameraView.getContext(), R.string.picture_taken, Toast.LENGTH_SHORT)

.show();

getBackgroundHandler().post(new Runnable() {

@Override

public void run() {

File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),

"picture.jpg");

Log.d(TAG, "onPictureTaken file path: " + file.getPath());

OutputStream os = null;

try {

os = new FileOutputStream(file);

os.write(data);

os.close();

} catch (IOException e) {

Log.w(TAG, "Cannot write to " + file, e);

} finally {

if (os != null) {

try {

os.close();

} catch (IOException e) {

// Ignore

}

}

}

}

});

}

};

有三个回调方法,相机打开,相机关闭,和拍照。

拍照

mCameraView.takePicture();

就是这么简单,点击后拍照,然后回调中处理图像数据

CameraX

CameraX 是一个 Jetpack 支持库,目的是简化Camera的开发工作,它是基于Camera2 API的基础,向后兼容至 Android 5.0(API 级别 21)。

它有以下几个特性:

易用性,只需要几行代码就可以实现预览和拍照

保持设备的一致性,在不同相机设备上,对宽高比、屏幕方向、旋转、预览大小和高分辨率图片大小,做到都可以正常使用

相机特性的扩展,增加人像、HDR、夜间模式和美颜等功能

开发流程

库引用

目前CameraX最新版本是1.0.0-alpha06,在app的build.gradle引用:

dependencies {

// CameraX core library.

def camerax_version = "1.0.0-alpha06"

implementation "androidx.camera:camera-core:${camerax_version}"

// If you want to use Camera2 extensions.

implementation "androidx.camera:camera-camera2:${camerax_version}"

def camerax_view_version = "1.0.0-alpha03"

def camerax_ext_version = "1.0.0-alpha03"

//other

// If you to use the Camera View class

implementation "androidx.camera:camera-view:$camerax_view_version"

// If you to use Camera Extensions

implementation "androidx.camera:camera-extensions:$camerax_ext_version"

}

因为CameraX是一个 Jetpack 支持库,相机的打开和释放都是使用了Jetpack的Lifecycle来进行处理。

预览

预览参数设置,使用PreviewConfig.Builder()实现:

PreviewConfig config = new PreviewConfig.Builder()

.setLensFacing(CameraX.LensFacing.BACK)

.setTargetRotation(mTextureView.getDisplay().getRotation())

.setTargetResolution(new Size(640, 480))

.build();

Preview preview = new Preview(config);

preview.setOnPreviewOutputUpdateListener(new Preview.OnPreviewOutputUpdateListener() {

@Override

public void onUpdated(@NonNull Preview.PreviewOutput output) {

if (mTextureView.getParent() instanceof ViewGroup) {

ViewGroup viewGroup = (ViewGroup) mTextureView.getParent();

viewGroup.removeView(mTextureView);

viewGroup.addView(mTextureView, 0);

mTextureView.setSurfaceTexture(output.getSurfaceTexture());

updateTransform();

}

}

});

//lifecycle

CameraX.bindToLifecycle(this, preview);

PreivewConfig.Builder可以设置的属性很多,这里只设置了摄像头、旋转方向、预览分辨率,还有很多其他方法,大家可以自行试验。

在preview回调监听中,把output的SurfaceTexture设置到mTextureView中,实现图像预览,最后增加Lifecycle的绑定。

拍照

ImageCaptureConfig captureConfig = new ImageCaptureConfig.Builder()

.setTargetAspectRatio(AspectRatio.RATIO_16_9)

.setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)

.setTargetRotation(getWindowManager().getDefaultDisplay().getRotation())

.build();

ImageCapture imageCapture = new ImageCapture(captureConfig);

mTakePicture.setOnClickListener((view) -> {

final File file = new File(getExternalMediaDirs()[0], System.currentTimeMillis() + ".jpg");

Log.d("DEBUG", "##### file path: " + file.getPath());

imageCapture.takePicture(file, ContextCompat.getMainExecutor(getApplicationContext()), new ImageCapture.OnImageSavedListener() {

@Override

public void onImageSaved(@NonNull File file) {

Log.d("DEBUG", "##### onImageSaved: " + file.getPath());

}

@Override

public void onError(@NonNull ImageCapture.ImageCaptureError imageCaptureError, @NonNull String message, @Nullable Throwable cause) {

Log.d("DEBUG", "##### onError: " + message);

}

});

});

CameraX.bindToLifecycle(this, preview, imageCapture);

拍照的参数通过ImageCaptureConfig.Builder设置,这里只设置了图片宽高比、拍摄模式和旋转方向,还有很多其他方法,大家可以自行试验。

真正调用拍照的方法:

takePicture(OnImageCapturedListener):此方法为拍摄的图片提供内存缓冲区。

takePicture(File, OnImageSavedListener):此方法将拍摄的图片保存到提供的文件位置。

takePicture(File, OnImageSavedListener, Metadata):此方法可用于指定要嵌入已保存文件的 Exif 中的元数据。

例子调用的是takePicture(File, OnImageSavedListener),直接存为文件。最后再增加Lifecycle的绑定。

图片分析

ImageAnalysisConfig analysisConfig = new ImageAnalysisConfig.Builder()

.setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)

.build();

ImageAnalysis imageAnalysis = new ImageAnalysis(analysisConfig);

imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(getApplicationContext()),

new LuminosityAnalyzer());

CameraX.bindToLifecycle(this, preview, imageCapture, imageAnalysis);

...

private class LuminosityAnalyzer implements ImageAnalysis.Analyzer {

private long lastAnalyzedTimestamp = 0L;

@Override

public void analyze(ImageProxy image, int rotationDegrees) {

final Image img = image.getImage();

if (img != null) {

Log.d("DEBUG", img.getWidth() + "," + img.getHeight());

}

}

}

图片分析,不是必要的步骤,但是ImageAnalysis,可以对每帧图像进行分析。

设置参数通过ImageAnalysisConfig.Builder(),这里只设置了ImageReaderMode,它有两种模式:

阻止模式(ImageReaderMode.ACQUIRE_NEXT_IMAGE):就是Camera2中的acquireNextImage(),获取下一个最新的可用Image

非阻止模式(ImageReaderMode.ACQUIRE_LATEST_IMAGE):Camera2中的acquireLatestImage(),获得图像队列中最新的图片,并且会清空队列,删除已有的旧的图像

最后还是增加Lifecycle的绑定。CameraX的使用也非常简单,把Camera2中复杂的API封装到统一的config中,只需要几行代码,就实现需要的功能。

文章中涉及到的代码

参考

camerax 自动聚焦_Android Camera-CameraView和CameraX使用相关推荐

  1. camerax 自动聚焦_Android实现手机摄像头的自动对焦

    如何实现Android相机的自动对焦,而且是连续自动对焦的.当然直接调用系统相机就不用说了,那个很简单的.下面我们主要来看看如如何自己实现一个相机,并且实现自动连续对焦. 代码如下: public c ...

  2. camerax 自动聚焦_手机是如何实现自动对焦的?

    以下是科学长文,如果仅想了解自动聚焦原理的,第一二点够了啦~ 一.话不多说,我们首先来看看相机聚焦的原理是什么?然后再让它自动 这个图我们都熟悉,中学时候的凸透镜成像的原理 物距u跟像距v的共轭关系为 ...

  3. android yuv加水印_Android Camera添加预览水印

    前言 在SurfaceView初步以及Camera初步中我介绍了如何使用SurfaceView以及如何使用SurfaceView来预览Camera画面,接下来我就来介绍下如何给Camera添加水印效果 ...

  4. android 内存分析工具_Android Camera内存问题剖析

    本文通过一类 Android 机型上相机拍摄过程中的 native 内存 OOM 的问题展开,借助内存快照裁剪回捞和 Native 内存监控工具的赋能,来深入剖析此类问题. 背景 Raphael 是西 ...

  5. java对焦_Android camera摄像头对焦,zoom的通知事件回调,告诉java应用层已经对焦完成...

    在vendor/sec/sec_proprietary/smdkc110/libcamera/SecCameraHWInterface.cpp中,当对硬件设置完毕后,通知packages/apps/C ...

  6. android yuv加水印_Android Camera录制视频添加水印

    通常用Camera 采集视频 得到预览数据,使用mediaCodec获取视频数据,用mediaMuxer进行音视频的混流, 如果想要添加水印很简单: 1.拿到相机预览的帧数据 2.将帧数据转为Bitm ...

  7. android camera移动方向_Android Camera开发系列:调整Camera预览方向

    有时候我们想根据自己的需要调整下Camera的预览方向,那么是调用哪个API可以达到我们的目的呢? 我们看下下图拍的几张小可爱的照片,分别是正常方向.旋转180度.90度拍的照片. ​ 正常方向 旋转 ...

  8. 安卓获取摄像头帧率_Android Camera预览时输出的帧率控制

    Android Camera预览时输出的帧率控制 2016年08月16日 14:24:28 阅读数:13250 如果使用MediaCodec硬编码H264,可以使用下面的方法控制编码输出的帧率: Me ...

  9. Android JetPack组件-CameraX初探

    CameraX 又是一个 Google 推出的 JetPack 组件 ,是一个新鲜玩意儿,故给大家分享下我在项目中的使用过程心得.. CameraX 是什么? Google 开发者文档 对 Camer ...

最新文章

  1. 队列(常用数据结构之一)
  2. SDUTOJ 【1166】打印直角三角形
  3. 数据库笔记02:查询与统计数据
  4. JAVA环境变量JAVA_HOME、CLASSPATH、PATH设置详解
  5. Linq To Sql进阶系列(二)M:M关系
  6. linux ulimit知识
  7. sandboxie游戏不能运行在虚拟环境中如何解决_火爆全球的游戏专业,你还不来莫道克大学亲身感受一下?...
  8. Linux7(CentOs7.5)安装ssh、和修改ssh端口号
  9. php微信消息通知,企业微信实现消息通知功能
  10. macd ema java源码_[转载]彩色MACD指标源码
  11. [渝粤教育] 西南科技大学 英语(B)1 在线考试复习资料
  12. python怎么循环合并数组_python数组循环合并python执行系统命令四种方法比较
  13. 以下哪些是微型计算机,2017版计算机试题及答案
  14. 国四网络工程笔记(究极错题)
  15. 你是王者荣耀里的哪种程序员?来看看你的属性,是貂蝉还是吕布!
  16. Matlab——图形绘制——三维立体图形 剔透玲珑球 动态图——彗星状轨迹图
  17. 8*8点阵引脚图 行列定义
  18. AutoCAD帮助文档下载
  19. android动态壁纸的制作
  20. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A

热门文章

  1. python---线程与进程
  2. URAL1519 Formula 1 —— 插头DP
  3. javascript this指针指向?
  4. overfitting(过度拟合)的概念
  5. SerialPort comstat is being used without defining
  6. [译] RNN 循环神经网络系列 2:文本分类
  7. 1001种玩法 | 1001种玩法--数据存储(2)
  8. 【BZOJ 3098】 Hash Killer II
  9. Firemonkey Android IOS 图标
  10. 服务端配置实现AJAX跨域请求