重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

android系统相机,安卓系统单反相机

Android进阶——你所知道的Camera2和你所不知道的Camera2完全解析

一切源于在项目过程中的一个Bug:我的需求是在MainActivity 实现自动预览,也可以点击跳到签到SignedActivity去实现拍照签到,第一次进入界面的时候都是正常的,但是有时候返回来的时候预览失败,即从MainActivity跳转到SignedActivity偶尔预览失败和从SignedActivity返回MainActivity偶尔失败,都是报(CAMERA_IN_USE)ERRO=1的错误,奇怪的是的的确确做了完全释放操作,加上以前用的更多的是Camera api 对于Camer2 的机制没有完整去研究过,一下子懵了,于是乎先去找了Stack Overflow,查到一个解决方案是:"我弃用了新API,换回旧API",ORZ,找了其他的也没有答案,可是我不服呀,我就把官方的文档全部啃了一遍,于是乎便有了以下的理解,我想如果你不懂得怎么使用Camera2的话,这篇绝对值得你去阅读,你会发现Camera2 并非像大多数说得那样使用起来很复杂。

庄浪网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设公司等网站项目制作,到程序开发,运营维护。创新互联于2013年开始到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联。

全新的android.hardware.Camera2 。Android 5.0对拍照API进行了全新的设计,新增了全新设计的Camera 2 API,这些API不仅大幅提高了Android系统拍照的功能,还能支持RAW照片输出,甚至允许程序调整相机的对焦模式、曝光模式、快门等。

在Camera2 架构在核心参与类角色有: CameraManager 、 CameraDevice 、 CameraCharacteristics 、 CameraRequest与CameraRequest.Builder 、 CameraCaptureSession 以及 CaptureResult 。

位于android.hardware.camera2.CameraManager下,也是Android 21(5.0)添加的,和其他系统服务一样通过 Context.getSystemService(CameraManager.class ) 或者 Context.getSystemService(Context.CAMERA_SERVICE) 来完成初始化,主要用于管理系统摄像头:

CameraDevice是Camera2中抽象出来的一个对象,直接与系统硬件摄像头相联系。因为不可能所有的摄像头都会支持高级功能(即摄像头功能可被分为limit 和full 两个级别),当摄像头处于limited 级别时候,此时Camera2和早期的Camera功能差不多,除此之外在Camera2架构中,CameraDevice还承担其他两项重要任务:

正如前面所说, 系统向摄像头发送 Capture 请求,而摄像头会返回 CameraMetadata,这一切都是在由对应的CameraDevice创建的CameraCaptureSession 会话完成 ,当程序需要预览、拍照、再次预览时,都需要先通过会话。(A configured capture session for a CameraDevice , used for capturing images from the camera or reprocessing images captured from the camera in the same session previously.A CameraCaptureSession is created by providing a set of target output surfaces to createCaptureSession , or by providing an InputConfiguration and a set of target output surfaces to createReprocessableCaptureSession for a reprocessable capture session . Once created, the session is active until a new session is created by the camera device, or the camera device is closed.)CameraCaptureSession一旦被创建,直到对应的CameraDevice关闭才会死掉。虽然CameraCaptureSession会话用于从摄像头中捕获图像,但是只有同一个会话才能再次从同一摄像头中捕获图像。另外, 创建会话是一项耗时的异步操作,可能需要几百毫秒 ,因为它需要配置相机设备的内部管道并分配内存缓冲区以将图像发送到所需的目标,因而createCaptureSession和createReprocessableCaptureSession会将随时可用的CameraCaptureSession发送到提供的监听器的onConfigured回调中。如果 无法完成配置,则触发onConfigureFailed回调 ,并且会话将不会变为活动状态。最后需要注意的是,如果 摄像头设备创建了一个新的会话,那么上一个会话是被关闭的,并且会回调与其关联的onClosed ,如果不处理好,当会话关闭之后再次调用会话的对应方法那么所有方法将会跑出IllegalStateException异常。关闭的会话清除任何重复的请求(和调用了stopRepeating()方法类似),但是在新创建的会话接管并重新配置摄像机设备之前,关闭的会话仍然会正常完成所有正在进行的捕获请求。简而言之,在Camera2中CameraCaptureSession承担很重要的角色:

描述Cameradevice属性的对象,可以使用CameraManager通过getCameraCharacteristics(String cameraId)进行查询。

CameraRequest代表了一次捕获请求, 而CameraRequest.Builder用于描述捕获图片的各种参数设置,包含捕获硬件(传感器,镜头,闪存),对焦模式、曝光模式,处理流水线,控制算法和输出缓冲区的配置。 ,然后传递到对应的会话中进行设置, CameraRequest.Builder则负责生成CameraRequest对象 。当程序调用setRepeatingRequest()方法进行预览时,或调用capture()方法进行拍照时,都需要传入CameraRequest参数。CameraRequest可以通过CameraRequest.Builder来进行初始化,通过调用createCaptureRequest来获得。

CaptureRequest描述是从图像传感器捕获单个图像的结果的子集的对象。(CaptureResults are produced by a CameraDevice after processing a CaptureRequest)当CaptureRequest被处理之后由CameraDevice生成。

CameraManager 处于顶层管理位置负责 检测获取所有摄像头及其特性 和 传入指定的CameraDevice.StateCallback回调打开指定摄像头 , CameraDevice 是负责管理抽象对象,包括 监听Camera 的状态回调CameraDevice.StateCallback 、 创建CameraCaptureSession和CameraRequest , CameraCaptureSession 用于描述一次图像捕获操作,主要负责 监听自己会话的状态回调CameraCaptureSession.StateCallback 和 CameraCaptureSession.CaptureCallback捕获回调 ,还有 发送处理CameraRequest ; CameraRequest 则可以看成是一个"JavaBean"的作用用于描述希望什么样的配置来处理这次请求;最后三个回调用于监听对应的状态。

CameraManager 处于顶层管理位置负责检测 检测获取所有摄像头并设置输出参数,传入指定的CameraDevice.StateCallback回调,然后打开指定摄像头,并触发CameraDevice.StateCallback中的onOpened方法,并在onOpened方法里开始通过调用创建预览会话, ,CameraDevice负责创建请求 CameraCharacteristics 、 CameraRequest与CameraRequest.Builder 、 CameraCaptureSession 以及 CaptureResult 则可以看成是一个JavaBean的作用用于描述以什么样的配置来处理这次请求。

Camera2Helper类只是简单的封装了下,为了让Camera2的初始化和Activity 高度分离,这个类只是Demo 阶段部分有待优化,另外结合我具体的业务,对于图片大小有限制,所以我都是默认采用采样压缩率方式对图片进行压缩

Android 系统原生相机API角度原理与适配

虽然Camera作为第一代原生android所提供的相机类一直被开发者甚至Google官方开发人员所诟病,但为了兼容和适配Android版本5.0以下的App应用,我们别无选择。因此,有了本篇文档详细阐述1.0版的Camera 是如何使用的。本篇使用的是SurfaceView与Camera类。

文档下文会在拍照流程中的不同的阶段应用到上述四个角度,而“终端自然方向”贯穿整个流程当中。这一个方向、四个角度非常重要,缺一不可,是支撑相机Camera 系列API的关键。在设计NXDesign的相机项目中,经过对官方文档的研读和各路资料的调研之后发现,我们在网络上查到的博客类相关资料有80%的实现方式是存在问题的,当然,这也可以归咎于该API其本身确实不好用,如果不对源码注释进行仔细研究,很容易对开发者产生误导。

更加准确的说,相机的生命周期是依托于SurfaceView的创建和销毁来完成的。SurfaceView的作用是提供相机内容的实时预览。我们需要在surfaceview创建好之后打开相机使用相机资源,在surfaceview被销毁后释放相机资源。

surfaceview 提供了holder机制向调用方通知surfaceview的变化时机,为了在不同的时机对相机资源做不同的事情,需要调用SurfaceHolder.addCallback()方法。

现在的Android手机一般会有多个摄像头,但根据其方向可以归为两类: CAMERA_FACING_BACK 和 CAMERA_FACING_FRONT 。在打开摄像头之前,首先需要获取相机资源,判断相机个数 Camera.getNumberOfCameras() 。每个相机对应一个CameraInfo,它的定义如下:

这里涉及到一个重要概念:相机图像传感器(camera sensor),想要理解上述注释的含义,就需要先理解下图内容。

左图是通常情况下,我们对view的x y方向的认知,以屏幕的左上角为原点向右为x正方向,向下为y正方向;但是,右图描述的是绝大多数情况下, 相机图像传感器 的起始位置和方向判定。与view不同的是,传感器以手机屏幕在自然方向上的右上角为原点,向下为x正方向,向左为y正方向。因此,我们理解上述注释就不难了。如果相机自带的传感器顶部与终端自然方向(手机屏幕的硬件方向,一般手机都是竖直方向,也就是文档中说的naturally tall screen)的右边缘一致,则这个值就是90度。如果前置摄像头传感器的顶部与手机自然方向一致,则这个值就是270度。

当我们定义startCamera()方法时,要做5件事情,1.遍历摄像头cameraId,找到想要打开的摄像头(前置还是后置);2.获取摄像头信息,主要获取orientation;3. 设置相机DisplayOrientation 4.设置相机参数,主要是宽高比、对焦模式、图片格式、setRotation等。5. 向camera设置surfaceview.viewholder,并且startPreview。主要逻辑如下:

拿到cameraInfo.orientation之后,要调用camera.setDisplayOrientation设置进去,保证通过surfaceview预览到的取景跟当前的手机方向保持一致,但是,setDisplayOrientation设置的其实是经过两个角度计算之后的复合角度,而并不单纯是cameraInfo.orientation。正确的做法是这样的:先获取手机屏幕的旋转方向,然后与cameraInfo.orientation加和得到最终角度。通常情况下,如果我们设置相机为portrait,则不用考虑rotation。这也是为什么绝大部分网络资料中都会粗暴的写入一个90度完事儿而并没有解释这么做的道理。

调用camera.takePicture(null, null, pictureCallback)

这里需要做的仅仅是将callback中返回的data存储为File。需要注意的是,data中会包含setRotation()方法中的角度信息,因此如果直接使用Bitmap工具类生成bitmap,再进行存储或者展示,生成出来的图像其实是缺失了旋转角度的原始方向,这十有八九会发生图像展示角度错误的情况。因此,需要直接保存,再通过Exif工具类读取File中的角度信息(当然Exif工具类就是为了读取File中的各种信息而生的,比如拍照时间、经纬度等等)。

基于Camera API,

surfaceview的预览需要setDisplayOrientation(),入参角度与CameraInfo.orientation(传感器偏角)和WindowManager.default.displayOrientation(屏幕旋转角度)两个角度有关。

相机拍照前需要setRotation(),入参角度与CameraInfo.orientation(传感器偏角)和OrientationEventListener返回的orientation(终端自然角度偏角)有关,二者的换算结果就是图像写入偏角,该偏角意味着图像被顺时针旋转该角度就能够回正展示。

Android调用系统相机拍照

Refrence:

Android 调用系统相机拍照适配主要经历了 6.0 7.0 10和11这几个大版本:

其中:

常用到的为 external-path 和 external-files-path,name和path按照自己需求编写

上述示例意思是,external-path标签指向的路径后path中指向的文件/文件夹拥有被访问权限,即 /storage/emulate/0/000 这个路径拥有被访问的权限。

简单示例:

安卓手机相机用不了有什么办法啊

若使用的是vivo手机,相机无法使用处理方法如下:

1、若软件无法打开相机,进入设置--应用与权限/更多设置--权限管理--找到对应的软件--开启相机,在单项权限设置--开启“使用摄像头”权限;

2、卸载第三方管家类软件,如:腾讯手机管家、360手机卫士等,再尝试开启相机

3、进入设置--应用与权限/更多设置--应用管理/应用程序--(全部)--找到相机--存储后清除数据和缓存,后重启手机;

4、进入设置--系统管理/更多设置--备份与重置/恢复出厂设置--还原所有设置/清除所有数据(需进行备份数据);

5、固件升级;

6、若以上方法未解决,可携带手机和有效购机凭证去客户服务中心处理,关注微信公众号“vivo”或者“vivo客户服务”进行查询服务中心地址电话,建议去之前电话联系,确保有工作人员接待再过去,避免耽误宝贵时间白跑一趟。

Android 使用系统相机拍照和读取相册照片

1.拍照 (对于7.0以上的版本,不在允许直接访问uri)

`

若不指定输出路径intent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri(srcActivity)); 在onActivityResult()中,通过

`

可以拿到uri,但获得的图片是被压缩过的。若指定intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);输出路径,则此处的intent为null,但可以使用我们存的uri读取照片,此时的照片没有被压缩。

2.从相册中读取照片, 方法:

`

`

即使设置 intent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri(srcActivity));输出路径,仍然不能从此路径中读取,只能在onActivityForResult()中通过event.uri = intent.getData();方式获得图片uri。

此种现象也好理解,拍照时产生新的图片,自然可根据设置的uri进行图片保存,而读取相册时,图片已经在目录中不能转移到自己设定的uri中。

Androidmanifest.xml中

`

在 res/xml/provider_paths.xml

`

?xml version="1.0" encoding="utf-8"?

paths

external-path name="JDTobs" path=""/

files-path name="name" path="path" /

cache-path name="name" path="path" / external-path name="name" path="path" /

external-files-path name="name" path="path" /

external-cache-path name="name" path="path" / /paths `

读取uri

Android调用系统相机实现拍照和视频录制

(1)申请权限

(2)设置布局

这里做了一个简单的布局:添加了一个按钮和一个ImageView控件用于显示拍摄的图像。

(3)为按钮添加点击事件监听

点击按钮时,调用系统相机进行拍照,并在确定后将图像显示在ImageView控件中。

(1)申请权限

(2)设置布局

添加了一个按钮和一个VideoView控件用于显示录制的视频。

(3)为按钮添加点击事件监听

同前面一样,点击按钮后调用系统相机进行录制视频,录制完成后点击确定即可将录制的视频显示在VideoView控件中。

对于Android11.0的版本,在调用系统相近进行视频录制的时候,即使在AndroidMenifest.xml中申请了CAMERA权限,还是会在程序运行时报错: Permission  Denial ,   . .... ....  with revoked permission android.permission.CAMERA

解决方法是在程序中动态申请权限:

写在最后:文章是在学习过程中做的学习笔记,同时与志同道合者分享,文章内容均经过我自己实验证实可行,如有问题欢迎留言,很高兴一起交流讨论,共同进步!


当前标题:android系统相机,安卓系统单反相机
文章地址:http://cqcxhl.cn/article/hoigpo.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP