从Android 5.0开始,Google 引入了一套全新的相机框架 Camera2(android.hardware.camera2)并且废弃了旧的相机框架 Camera1(android.hardware.Camera)。在API架构方面, Camera2和之前的Camera有很大区别, APP和底层Camera之前可以想象成用管道方式连接,接下来先了解下Camera2的相关类。

CameraManager类:摄像头的管理类,主要是用于检测、打开系统的摄像头;

CameraCharacteristics类:相机的特征类,例如是否可以支持自动调焦,是否支持闪光灯等等;(一般包含以下几种常用的参数:LENS_FACING:拿到摄像头的方向(LENS_FACING_FRONT是前摄像头,LENS_FACING_BACK是后摄像头)
SENSOR_ORIENTATION:获取摄像头拍照的方向位置
SCALER_AVAILABLE_MAX_DIGITAL_ZOOM:获取最大的数字调焦值(Zoom的最大值)
FLASH_INFO_AVAILABLE:支不支持闪光灯
LENS_INFO_MINIMUM_FOCUS_DISTANCE:获取最小的调焦距离)

CameraDevice类:相机设备,类似以往的Camera类,可以使用reateCaptureRequest (int templateType)方法创建CaptureRequest.Builder,一般templateType的常见参数如下:TEMPLATE_PREVIEW :预览
TEMPLATE_RECORD:拍摄视频
TEMPLATE_STILL_CAPTURE:拍照
TEMPLATE_VIDEO_SNAPSHOT:创建视视频录制时截屏的请求

CameraCaptureSession类:用于创建预览、拍照的Session类,程序中通过创造一个CameraCaptureSession,在安卓端和相机硬件端建立管道,从而可以获取拍摄的图片信息,可以通过它的setRepeatingRequest()方法来控制预览界面。在创造一个会议时,会回调两个接口——StateCallback:处理session建立成功和失败的情况,通常在这里会进行预览的一些初始化设置。CaptureCallback:捕获图像成功、失败、进行时等情况的处理;

CameraRequest类:用于控制预览和拍照参数,例如:对焦模式,曝光模式,zoom参数等等。从图像传感器捕获单个图像的结果的子集。包含捕获硬件(传感器,镜头,闪存),处理流水线,控制算法和输出缓冲区的最终配置的一个子集。

了解完了Camera2的相关类,接下来了解一个Camera开发过程中必不可少的控件----TextureView
TextureView是在Android 4.0引入的,主要用于承载显示数据流的View, 如本地Camera采集的预览数据流和视频通话模块从网络包里解出实时视频数据流。TextureView还有个比较好的特性就是可以当做普通的View控件使用,在布局、动画和变换(平移、缩放、旋转等)中非常方便。

总的来说,就是我们只要抓住一条会话通道,就可以通过这条通道传送CameraRequest请求预览、拍照和录像了。流程大致如下:在调用onCamera方法后会回调CameraDevice.StateCallback这个方法,在这个方法里面重写onOpend函数,在onOpend方法中调用createCaptureSession,该方法又回调CameraCaptureSession.StateCallback方法,在该方法中重写onConfigured方法,设置setRepeatingRequest方法(即开始图兰图像),setRepeatingRequest又会回调CameraCaptureSession.CaptureCallback方法,重写CameraCaptureSession.CaptureCallback方法中的onCaptureCompleted方法,最后result就是未经过处理的原始数据了。

接下来就来使用Camera2来实现采集手机摄像头图像的一个小Demo吧。

在布局中添加一个TextureView控件,用来采集摄像头的预览数据,在打开摄像头之前,一定要记得申请权限,一定要记得申请权限,一定要记得申请权限,重要的事情说三遍,如果不知道如何动态申请权限的,可以查看我之前的博客Android 6.0动态申请权限
其次是定义一个TextureView作为一个预览的界面,然后一定要实现它的监听事件

        TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {//当SurefaceTexture可用的时候,设置相机参数并打开相机setupCamera(width, height);configureTransform(width, height);openCamera();}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {//当SurefaceTexture状态改变时调用此方法}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {//当SurefaceTexture销毁时调用此方法return false;}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surface) {//当SurefaceTexture状态更新时调用此方法}};textureView.setSurfaceTextureListener(textureListener);

setupCamera这个方法主要是根据TextureView来设定相对于的尺寸大小,Camera2中使用CameraManager来管理摄像头,代码如下:

    private void setupCamera(int width, int height) {// 获取摄像头的管理者CameraManagerCameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);try {// 遍历所有摄像头for (String cameraId : manager.getCameraIdList()) {CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);// 默认打开后置摄像头 - 忽略前置摄像头if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT){continue;}// 获取StreamConfigurationMap,它是管理摄像头支持的所有输出格式和尺寸StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);cameraID = cameraId;break;}} catch (CameraAccessException e) {e.printStackTrace();}}

接着是打开摄像头,也是需要用到CameraManager管理类,manager.openCamera()这个方法的第三个参数是指在哪个线程执行,null就是为主线程

 private void openCamera() {CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);//检查权限try {if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {Toast.makeText(MainActivity.this,"请检查权限是否打开",Toast.LENGTH_LONG).show();return;}//打开相机,第一个参数指示打开哪个摄像头,第二个参数stateCallback为相机的状态回调接口,第三个参数用来确定Callback在哪个线程执行,为null的话就在当前线程执行manager.openCamera(cameraID, stateCallback, null);} catch (CameraAccessException e) {e.printStackTrace();}}

当相机打开之后会回调接口StateCallback里面的方法

 //实现StateCallback 接口,当相机打开后会回调onOpened方法private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {@Overridepublic void onOpened(@NonNull CameraDevice camera) {//打开摄像头mCameraDevice = camera;//开启预览startPreview();}@Overridepublic void onDisconnected(@NonNull CameraDevice camera) {//关闭摄像头}@Overridepublic void onError(@NonNull CameraDevice camera, int error) {//发生错误}};

接着就是摄像头的图像预览了

    private void startPreview() {setupImageReader();SurfaceTexture mSurfaceTexture = textureView.getSurfaceTexture();//设置TextureView的缓冲区大小mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());//获取Surface显示预览数据mPreviewSurface = new Surface(mSurfaceTexture);try {getPreviewRequestBuilder();//创建相机捕获会话,第一个参数是捕获数据的输出Surface列表,第二个参数是CameraCaptureSession的状态回调接口,当它创建好后会回调onConfigured方法,第三个参数用来确定Callback在哪个线程执行,为null的话就在当前线程执行mCameraDevice.createCaptureSession(Arrays.asList(mPreviewSurface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(CameraCaptureSession session) {mCaptureSession = session;repeatPreview();}@Overridepublic void onConfigureFailed(CameraCaptureSession session) {}}, null);} catch (CameraAccessException e) {e.printStackTrace();}}

创建预览请求的Builder

    // 创建预览请求的Builder(TEMPLATE_PREVIEW表示预览请求)private void getPreviewRequestBuilder() {try {mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);} catch (CameraAccessException e) {e.printStackTrace();}//设置预览的显示界面mPreviewRequestBuilder.addTarget(mPreviewSurface);MeteringRectangle[] meteringRectangles = mPreviewRequestBuilder.get(CaptureRequest.CONTROL_AF_REGIONS);if (meteringRectangles != null && meteringRectangles.length > 0) {Log.e("LEE", "PreviewRequestBuilder: AF_REGIONS=" + meteringRectangles[0].getRect().toString());}mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);}

设置反复捕获数据的请求,这样预览界面就会一直有数据显示

    private void repeatPreview() {mPreviewRequestBuilder.setTag(TAG_PREVIEW);mPreviewRequest = mPreviewRequestBuilder.build();//设置反复捕获数据的请求,这样预览界面就会一直有数据显示try {mCaptureSession.setRepeatingRequest(mPreviewRequest, captureCallback, null);} catch (CameraAccessException e) {e.printStackTrace();}}

这些就是Camera2中使用到的比较重要的一些方法了,剩下的一些代码我就不贴出来了,有需要的话可以到github上下载一下源码就可以跑起来啦Git传送门

Android 之 Camera2相关推荐

  1. Android平台Camera2数据如何对接RTMP推流到服务器

    1. Camera2架构 在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2), 之前使用 ...

  2. android之camera2预览

    前面研究过了camera1,但是新的android sdk支持camera2,所以必须也要掌握camera2. 先参考资料: https://blog.csdn.net/afei__/article/ ...

  3. Android OpenGL+Camera2渲染(3) —— 大眼,贴纸功能实现

    Android OpenGL+Camera2渲染(1) -- OpenGL简单介绍 Android OpenGL+Camera2渲染(2) -- OpenGL实现Camera2图像预览 Android ...

  4. 问题单-CtsCameraTestCases模块下android.hardware.camera2.cts.CaptureRequestTest#testAeModeAndLock[1]测试fail

    问题单-CtsCameraTestCases模块下android.hardware.camera2.cts.CaptureRequestTest#testAeModeAndLock[1]测试fail ...

  5. android.hardware.camera2详解

    看到有些读者对博客提出的疑问,在此真诚说一句实在抱歉,本人是一名在校非科班出身大学生,之前 由于是期末季,所以非常忙,没有空更新,一月二十几号才放假,非常抱歉,评论所诉内容应该都已解决,只是我没有更新 ...

  6. Android L Camera2 API sample ver1 - startPreview

    1. Manifest : <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:an ...

  7. Android OpenGL+Camera2渲染(2) —— OpenGL实现Camera2图像预览

    Android OpenGL+Camera2渲染(1) -- OpenGL简单介绍 Android OpenGL+Camera2渲染(2) -- OpenGL实现Camera2图像预览 Android ...

  8. Android使用Camera2 替代过时的Camera API

    因为考虑到想要新增新的5.0以上的Camera2 API,发现变得太多,有重构的意思,还好先发现了这篇文章,目前对5.0以下的版本都没有兼容包和支持,所以建议按照文中最后一条做一下API版本判断 以下 ...

  9. Android自定义Camera2相机

    转载请标明出处:https://blog.csdn.net/ZhijunHong/article/details/115730693,谢谢~ 写在前面 Google从Android 5.0 L(API ...

最新文章

  1. Go 语言编程 — reflect 反射机制
  2. python中一个范围怎么表示_我应该如何处理Python中的包含范围?
  3. ffmpeg参数中文详细解释
  4. 看人家如何拿到腾讯阿里的offer
  5. mvn打包并部署本地tomcat_maven项目自动打包部署到tomcat中
  6. matlab 小波 cdd,[Matlab] 单导联心电数据的小波(包)消噪及压缩
  7. c语言如何扩大字体,C语言图形汉字及放大显示程序
  8. php curl登录,php curl保存登录信息 模拟登录
  9. 6. XML Schema
  10. 推荐几款程序员值得拥有的写文档工具
  11. 使用BASIC语言控制ESP8266
  12. 期刊论文发表会有证书吗
  13. 接口测试平台代码实现11: 用户管理模块设计和开发
  14. 怎么调节台式计算机字体大小,电脑上怎么调整字体大小
  15. 软件测试周刊(第32期):沙漠中藏着一口井
  16. 任职母校!C9,迎来新副校长!
  17. Python+request 将获取的url和接口响应时间(timeout)写入到Excel中《八》
  18. Blinker+小爱同学+四路继电器+(RFID+舵机模拟开门)代码
  19. Qt扫盲- QTcpSocket 理论总结
  20. 基于JAVA网上专家门诊预约系统计算机毕业设计源码+数据库+lw文档+系统+部署

热门文章

  1. 循环遍历获取table中的td,tr
  2. 2020全国计算机考试ps版本,2020年3月计算机等级Photoshop备考题及答案
  3. 网络加速_电狐H1Z1加速器轻松解决网络难题,低延迟吃鸡
  4. 深度学习 --- CNN的变体在图像分类、图像检测、目标跟踪、语义分割和实例分割的简介(附论文链接)
  5. linux下面安装geant4,ubuntu环境安装geant4
  6. BWA,Bowtie,Bowtie2的比对算法推导
  7. docker使用GPU(nvidia-docker)
  8. 四种数据类型转换字符串类型的 三种方法
  9. ASP:LinkButton控件(按钮类型控件)
  10. Python集合与题目练习