学习Camera2自定义相机从入门到高级一篇就够了
Camera2适用是Android5.0(API 级别 21)或更高版本的所有设备
总览
- 1、加入权限
- 1.1 系统Android6.0以下
- 1.2 系统Android6.0以上或者更高版本
- 2、实现功能列表
- 2.1 Camera2基础(入门篇)
- 2.1.1 显示预览图
- 2.1.1 摄像头方向切换
- 2.1.2 预览图片出现拉伸情况处理
- 2.1.3 手动对焦和自动对焦
- 2.1.4 缩放镜头大小
- 2.2 图片
- 2.2.1 图片拍摄
- 2.2.2 图片剪辑
- 2.3 视频
- 2.3.1 视频录制
- 2.3.2 视频剪辑
- 2.3.3 直播流程
- 2.4 保存处理
- 2.4.1 视频分段保存
- 2.4.2 图片压缩
1、加入权限
(所需要的的权限有:读写文件权限、拍摄照片和录制视频权限、 录音权限)
1.1 系统Android6.0以下
- 系统Android6.0以下的版本的直接在AndroidManifest.xml加入*
// 读写权限<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_CALENDAR" />// 拍摄照片和录制视频权限<uses-permission android:name="android.permission.CAMERA"/> // 录音权限<uses-permission android:name="android.permission.RECORD_AUDIO"/>
1.2 系统Android6.0以上或者更高版本
- 系统Android6.0或者更高版本需要动态获取权限(一般应用安装第一次打开获取,只获取一次就好)*
//先把所需要的的权限用数组装起来//READ_CALENDAR、WRITE_EXTERNAL_STORAGE : 读写权限//CAMERA : 拍摄照片和录制视频权限//RECORD_AUDIO: 录音权限private static String[] PERMISSIONS_STORAGE = {"android.permission.READ_CALENDAR","android.permission.WRITE_EXTERNAL_STORAGE","android.permission.CAMERA","android.permission.RECORD_AUDIO"};public void verifyStoragePermissions(Activity activity) {//然后通过其中的一个函数来申请int checkSelfPermission = ActivityCompat.checkSelfPermission(activity, PERMISSIONS_STORAGE[0]);if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {// 没有写的权限,去申请写的权限,会弹出对话框ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);}}
2、实现功能列表
2.1 Camera2基础(入门篇)
2.1.1 显示预览图
- 利用渲染图层中TextureView.SurfaceTextureListener监听,以下为监听的方法解析
方法 | 解析 |
---|---|
onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) | 当TextureView准备好使用Surface的SurfaceTexture时调用 (在这个方法里面做打开相机操作) |
onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) | SurfaceTexture的缓冲区大小更改时调用 |
onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) | 在将SurfaceTexture要销毁指定的对象时调用 |
onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) | SurfaceTexture通过更新指定的值 时调用 |
- 接收有关摄像头设备状态的更新CameraDevice.StateCallback(其中包括:摄像头打开,摄像头关闭,打开摄像头错误原因)
方法 | 解析 |
---|---|
onOpened( CameraDevice camera) | 照相机设备完成打开时调用的方法 |
onDisconnected(CameraDevice camera) | 当照相机设备不再可用时调用的方法(一般是其他应用占用了会回调,释放资源,调用camera.close()) |
onError(CameraDevice camera, int error) | 相机设备遇到严重错误时调用的方法(一般会释放资源,调用camera.close()) |
- 在onOpened(CameraDevice camera) 得到CameraCaptureSession(一个用于接收有关摄像机捕获会话状态更新的回调对象)
/*** 渲染图层*/private final TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {surface = new Surface(surfaceTexture);openCameraBase();}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}};/*** 摄像头状态回调*/private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {@Overridepublic void onOpened(@NonNull CameraDevice camera) {//成员变量device = camera;try {device.createCaptureSession(Collections.singletonList(surface), new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(@NonNull CameraCaptureSession session) {cameraCaptureSession = session;try {//创建一个请求//TEMPLATE_PREVIEW:创建适合摄像机预览窗口的请求//TEMPLATE_MANUAL:用于捕获参数的直接应用程序控制的基本模板//TEMPLATE_RECORD:创建适合视频录制的请求//TEMPLATE_STILL_CAPTURE:创建适合静态图像捕获的请求//TEMPLATE_VIDEO_SNAPSHOT:创建一个适合在录制视频时捕获静态图像的请求//TEMPLATE_ZERO_SHUTTER_LAG:创建一个适合零快门滞后仍然捕获的请求builder = device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);//在此请求的目标列表中添加一个表面builder.addTarget(surface);cameraCaptureSession.setRepeatingRequest(builder.build(), null, null);} catch (CameraAccessException e) {e.printStackTrace();}}@Overridepublic void onConfigureFailed(@NonNull CameraCaptureSession session) {}}, null);} catch (CameraAccessException e) {e.printStackTrace();}Log.i(TAG, "onDisconnected: " + "摄像头已打开");}@Overridepublic void onDisconnected(@NonNull CameraDevice camera) {camera.close();device.close();Log.i(TAG, "onDisconnected: " + "摄像头已关闭");}@Overridepublic void onError(@NonNull CameraDevice camera, int error) {camera.close();}};/*** 打开摄像头*/private void openCameraBase() {//摄像头管理 获取系统服务CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);//判断系统摄像机权限if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {//权限处理verifyStoragePermissions(getContext());}try {//打开摄像头assert cameraManager != null;cameraManager.openCamera(cameraDirection, stateCallback, null);} catch (CameraAccessException e) {e.printStackTrace();}}
注意:当切换到后台再进来会发现预览图画面卡着问题(是因为相机关闭了,渲染图层TextureView.SurfaceTextureListener没有清除图层,所以会以为画面卡着),解决方案如下:
/*** 防止其他应用占用摄像头,所以每一次进去都新打开摄像头*/@Overrideprotected void onResume() {super.onResume();openCameraBase();}/*** (关闭相机)释放资源*/@Overrideprotected void onPause() {super.onPause();if (device != null) {device.close();}}
2.1.1 摄像头方向切换
在 cameraManager.openCamera(cameraDirection, stateCallback, null);中cameraDirection是控制摄像头的方向(摄像头方向:“1”:为前置 “0”:为后置 (默认值为0))
//切换摄像头binding.button2.setOnClickListener(v -> {if (device.getId().equals(index)) {cameraDirection = "1";} else {cameraDirection = "0";}//先关闭,再打开device.close();openCameraBase();});
注意:记得先关闭当前摄像头,再打开要切换的摄像头
2.1.2 预览图片出现拉伸情况处理
- 一、自定义TextureView,重写宽高
- 二、初始化控件
private int ratioW = 0;private int ratioH = 0;public void setAspectRation(int width, int height){if (width < 0 || height < 0){throw new IllegalArgumentException("width or height can not be negative.");}ratioW = height;ratioH = width;//请求重新布局requestLayout();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);if (0 == ratioW || 0 == ratioH){//未设定宽高比,使用预览窗口默认宽高setMeasuredDimension(width, height);}else {//设定宽高比,调整预览窗口大小(调整后窗口大小不超过默认值)if (width < height * ratioW / ratioH){setMeasuredDimension(width, width * ratioH / ratioW);}else {setMeasuredDimension(height * ratioW / ratioH, height);}}}
注意:用法在跟TextureView控件一样,其他没有变
2.1.3 手动对焦和自动对焦
2.1.4 缩放镜头大小
2.2 图片
2.2.1 图片拍摄
2.2.2 图片剪辑
2.3 视频
2.3.1 视频录制
2.3.2 视频剪辑
2.3.3 直播流程
2.4 保存处理
2.4.1 视频分段保存
2.4.2 图片压缩
学习Camera2自定义相机从入门到高级一篇就够了相关推荐
- Android Camera2自定义相机绿屏
一.问题现象 在项目中使用Camera2自定义相机拍照,在其他手机上没有问题.在华为P40上.相机预览出现绿屏,绿屏如下所示 二.问题原因 预览设置高宽参数不符合相机高宽的话就会有绿条 原来的设置代码 ...
- docker入门,这一篇就够了。
Docker入门,这一篇就够了. Docker容器虚拟化平台. 前言 接触docker很长时间了,但是工作中也没有用到,所以总是学了忘,忘了学.不过这次,我打算跟大家分享一下我的学习历程,也算是我的独 ...
- Docker入门实战看这篇就够了(最新详细以及踩过的坑)
Docker入门实战看这篇就够了 前言 初识 是什么 容器与虚拟机 能干什么 去哪玩 安装 先决条件 查看自己的内核 安装所需的软件包(支持devicemapper存储类型) 设置镜像的仓库 设置yu ...
- Git【入门】这一篇就够了
前言 Git[入门]这一篇就够了 欢迎关注公众号,白嫖原创PDF,也可以催更,微信搜:JavaPub,回复:[666] Git 在生产工作中是使用频率很高的工具,但我发现很多文章只是对它做了简单的提交 ...
- Spring入门,看这篇就够了
Spring入门,看这篇就够了 文章目录 Spring入门,看这篇就够了 一. 初识Spring 二.Spring Framework系统架构 三.核心概念 1.IoC(inversion of co ...
- Android 自定义相机Demo 入门学习
Android 自定义相机Demo 本文是参考网上一些自定义相机示例,再结合自己对相机的功能需求写的,基本上包含了很多基本功能,比如相机对焦.闪光灯,以及在手机预览界面上绘制自己想要绘制的图案. 话不 ...
- Android开发(Jetpack) 学习CameraX 自定义相机实现
目录 一.CameraX和Camera2 二.CameraX的引入 三.自定义拍照 四.自定义视频录制 五.XML 配置 一.CameraX和Camera2 CameraX 是一个 Jetpack 库 ...
- 超硬核Python避坑学习方案奉上!入门到就业一篇就搞定!
本文收录了python从基础入门到高级进阶,再到之后发展方向的详细介绍,欢迎小伙伴们关注阅读!相信对你的python学习之路定能助一臂之力!评论提出你的见解!大家一起为你解答! 目录 一.迈出开发的第 ...
- Spring Cloud入门,看这篇就够了!
点击▲关注 "中生代技术" 给公众号标星置顶 更多精彩 第一时间直达 概述 首先我给大家看一张图,如果大家对这张图有些地方不太理解的话,我希望你们看完我这篇文章会恍然大悟. 什 ...
- mybatis-plus学习(一)——入门看这一篇就够了
文章目录 前言 准备工作 1.需要准备的SQL 2.一个简单的maven项目 3.配置文件如下 4.建立一个简单的实体和mapper 5.简单的helloworld测试程序 基本使用 通用mapper ...
最新文章
- mysql custom_MySQL安装教程
- 项目进度管理:定义活动
- 【-】WebKit Layout (布局)
- 使用机器学习预测天气_如何使用机器学习预测着陆
- 在阿里云服务器centOs7系统中部署.NET Core项目
- android 自定义dialog 定时关闭,Android 快速实现自定义 Dialog
- pycharm通过pytest运行报错:No test were found 解决
- System.Data.OleDb.OleDbException: 未指定的错误的解决方法
- 练手|常见近30种NLP任务的练手项目
- 简易的文件上传 tp5
- pclzip.lib.php,LimeSurvey
- 东北大学毕业设计(论文)全程解析
- 错误: -source 1.6 中不支持 diamond 运算符的解决办法
- 一份超详细的Spring4常用知识清单!
- 理解Tensorflow的shape
- 首次试水天池数据大赛——7个小时玩了把美年健康AI大赛
- 移动支付申请所需材料及流程整理
- 数据窗口Pageup与Pagedown翻页
- 用IE点击html页面用谷歌打开,如何在电脑中使用谷歌浏览器打开不兼容的网页
- mysql:SQL语言包含4个部分
热门文章
- php中怎么获取提交时间,php – 通过curl_getinfo()获取详细信息来获取cURL请求的时间...
- cdr2018更新内容
- TIPS-国库信息处理系统
- css3线性渐变怎么写,CSS3线性渐变指南
- labwindows 多线程
- 如何科学地利用A/B测试快速迭代产品?
- 常用数字信号处理方法在matlab上的实现(目录和先导)
- 40年间,“国货”如何崛起
- U盘/移动硬盘 有写保护怎么解除【未解决】
- 程序员薪酬待遇大调查:学哪种语言的最赚钱?