Android CameraX适配Android11的踩坑之路
目录
前言:
CameraX适配Android11的整个流程图如下:
1.我们来看看Google的通知说明:
2.目标版本:
3.我们把sdk的版本改为30之后出现的错误如下:
4.先看没有适配Android11之前的代码:
5.适配之后的正确代码:
6.适配步骤:
7.拍照成功后的日志如下:
8.拍照成功后的截图:
9.拍照适配Android11步骤:
10.总结:
前言:
11月份Google发通知上架的应用必须适配到Android30,要不然提交到google play的app不能发布更新,用户就只能使用旧版本。
CameraX适配Android11的整个流程图如下:
1.我们来看看Google的通知说明:
自 2021 年 11 月 1 日起,针对 Google Play 上的应用和游戏的更新必须以 Android 11(API 级别 30)或更高版本为目标运行环境。此日期过后,您将无法上传 targetSdkVersion
低于 30 的新 app bundle 和 APK。
请注意,Wear OS 应用不受关于 API 级别 30 的要求限制。
将您的应用配置为使用新近的 API 级别能使安全性和性能上的显著改进惠及用户,同时仍然允许您的应用在较低版本的 Android(低至 minSdkVersion
)上运行。
查看迁移指南
2.目标版本:
3.我们把sdk的版本改为30之后出现的错误如下:
以上错误信息具体意思就是在Android11及以上的手机读写文件失败
4.先看没有适配Android11之前的代码:
5.适配之后的正确代码:
6.适配步骤:
6.1 初始化文件和图片输出路径
6.2.创建一个文件:
6.3.文件创建成功后把图片插入媒体库:
val metadata = ImageCapture.Metadata().apply { // Mirror image when using the front cameraisReversedHorizontal = lensFacing == CameraSelector.LENS_FACING_FRONT }
6.4.构建图片输出对象outputOptions:
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).setMetadata(metadata).build()
6.5.拍照成功后通过MediaScannerConnection.scanFile刷新图库照片
![点击并拖拽以移动](data:ima
7.拍照成功后的日志如下:
8.拍照成功后的截图:
9.拍照适配Android11步骤:
9.1 请求文件读写权限,这里在首页已经请求过了直接上代码,实际项目根据需要每个界面都要动态请求权限
if (allPermissionsGranted()) {// ImageCapturestartCamera() } else {ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, Constants.REQUEST_CODE_PERMISSIONS) } private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults:IntArray ) {if (requestCode == Constants.REQUEST_CODE_PERMISSIONS) {if (allPermissionsGranted()) {startCamera()} else {ToastUtils.shortToast("请您打开必要权限")finish()}} }
9.2 调起系统相机拍照
/*** 调起系统相机拍照*/ private fun startSystemCamera() {val takeIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)val values = ContentValues()//根据uri查询图片地址photoUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)Log.w("lzq", "photoUri:" + photoUri?.authority + ",photoUri:" + photoUri?.path)//放入拍照后的地址takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)//调起拍照startActivityForResult(takeIntent,REQUEST_CODE_CAMERA) }
9.3 拍照和裁剪回调,由于加了系统裁剪,所以在拍照成功后会调用裁剪方法
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)if (resultCode == RESULT_OK) {if (requestCode == REQUEST_CODE_CAMERA) {//拍照回调workCropFun(photoUri)} else if (requestCode == REQUEST_CODE_CROP) {//裁剪回调setAvatar()}} }
9.4 图片裁剪方法,适配Android11
/*** 系统裁剪方法*/ private fun workCropFun(imgPathUri: Uri?) {mUploadImageUri = nullmUploadImageFile = nullif (imgPathUri != null) {val imageObject: Any = FileUtil.getHeadJpgFile()if (imageObject is Uri) {mUploadImageUri = imageObject}if (imageObject is File) {mUploadImageFile = imageObject}val intent = Intent("com.android.camera.action.CROP")if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)}intent.run {setDataAndType(imgPathUri, "image/*")// 图片资源putExtra("crop", "true") // 裁剪putExtra("aspectX", 1) // 宽度比putExtra("aspectY", 1) // 高度比putExtra("outputX", 150) // 裁剪框宽度putExtra("outputY", 150) // 裁剪框高度putExtra("scale", true) // 缩放putExtra("return-data", false) // true-返回缩略图-data,false-不返回-需要通过UriputExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()) // 保存的图片格式putExtra("noFaceDetection", true) // 取消人脸识别if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {putExtra(MediaStore.EXTRA_OUTPUT, mUploadImageUri)} else {val imgCropUri = Uri.fromFile(mUploadImageFile)putExtra(MediaStore.EXTRA_OUTPUT, imgCropUri)}}startActivityForResult(intent, REQUEST_CODE_CROP)} }
9.5从上图红框内容可以看到当系统版本为Android11及以上时裁剪后直接获取url和文件路径的方式会报错,提示读写失败,解决方法为在Android11及以上的手机上通过MediaStore把uri插入到file中,从而得到文件路径.
9.6 裁剪成功后设置用户头像,这里需要注意一下裁剪完之后这个路径在Android11上面是不能直接获取到的,也是需要MediaStore查询媒体库然后转为file,最后才能把路径设置为用户头像
/*** 设置用户头像*/ private fun setAvatar() {val file: File? = if (mUploadImageUri != null) {FileManager.getMediaUri2File(mUploadImageUri)} else {mUploadImageFile}Glide.with(this).load(file).into(iv_avatar)Log.d("filepath", file!!.absolutePath) }
9.7 打印拍照成功后的图片路径为:
10.总结:
在Google11月份要求必须适配到30后,我们查阅很多资料,第一时间进行了适配,但是一路坎坷,所有文件权限可以解决文件读写问题,但是这个权限若应用不是杀毒或文件管理类这个权限是不允许随便申请的,即使你申请了上架google play的时候审核也会被拒绝,Android11外部文件不允许随便读写和删除,今天只是讲解了拍照和录像时适配内外部存储权限,还有应用可见性、Toast、后台运行权限等等一些列的适配,在后面会写一篇文章全面总结一下最近的Android11适配工作。
11.最后给出最新的demo地址:感兴趣的同学可以看看,如有问题及时提出,一起成长.
CameraXApp: Android CameraX相机Api的使用实例
Android CameraX适配Android11的踩坑之路相关推荐
- Android SDK 开发——发布使用踩坑之路
前言 在 Android 开发过程中,有些功能是通用的,或者是多个业务方都需要使用的. 为了统一功能逻辑及避免重复开发,因此将该功能开发成一个 SDK 是相当有必要的. 背景 刚好最近自己遇到了类似需 ...
- 转:android.support升级到androidx踩坑记录
原文链接:android.support升级到androidx踩坑记录 - 简书 年前想着Google老大之前提醒过将项目升级到androidx,所以年前一通操作猛如虎把Android Studio唰 ...
- contentprovider踩坑之路之Failed to find provider info for com.example.app.provider和cursor=null空指针问题
目录 bug1.Failed to find provider info for com.example.app.provider bug2:cursor=null bug1.Failed to fi ...
- mybatis mapper.xml dtd_全栈开发踩坑之路4-用MyBatis实现服务
1.前言 上一篇文章介绍了如何设计后端的Mysql数据库:Alex Wang:全栈开发踩坑之路3-MySql数据库设计,本文介绍如何用MyBatis实现后端服务. 本后端项目的Github地址(撰写中 ...
- jmeter 3版本到5版本踩坑之路
jmeter 3-5版本升级踩坑路 新版本下载安装 踩坑之路 新版本下载安装 下载新版本软件 ,链接: https://jmeter.apache.org/download_jmeter.cgi: 配 ...
- 微信小程序实现大转盘抽奖----踩坑之路
微信小程序实现大转盘抽奖----踩坑之路 需求:现在有一个小程序抽奖页面如下,此类抽奖方式为大转盘 思路:由服务端获取抽奖次数和奖品,根据服务端的中奖概率来决定是否中奖,最后利用小程序动画将转盘转起来 ...
- 2021-11-01 富文本编辑器Vue-Quill-Editor 踩坑之路
Vue-Quill-Editor 基于 Quill.适用于 Vue 的富文本编辑器,支持服务端渲染和单页应用. 相对于ssr,spa是通过component进行工作 ssr和spa的区别 1 踩坑之路 ...
- [Java灵信LED] -- 踩坑之路
灵信led -T8 控制板卡 --踩坑之路 下载lv_led.dll 动态库链接 https://pan.baidu.com/s/11ZO-M6kllsq2AyhVW4AKoA 提取码:unsb 提取 ...
- webpack踩坑之路 (2)——图片的路径与打包
webpack踩坑之路 (2)--图片的路径与打包 刚开始用webpack的同学很容易掉进图片打包这个坑里,比如打包出来的图片地址不对或者有的图片并不能打包进我们的目标文件夹里(bundle).下面我 ...
- 基于dx11的动作游戏踩坑之路--1
基于dx11的动作游戏踩坑之路--1 首先要声明所有的博客都是学习博客,不是技术博,只是用来记录.整理自己的学习路线,以及日后可以回顾一下.本人也只是一个小菜鸡,可能会有很多错误与纰漏,有大佬愿意指出 ...
最新文章
- 我的Java设计模式-工厂方法模式
- 处理除第一个之外的所有参数(在bash脚本中)
- mysql 重构同步老数据_MySQL 重构查询的方式
- LeetCode 1562. 查找大小为 M 的最新分组
- android studio 本地html,android - 从当前HTML文件Android Studio中打开本地HTML文件? - 堆栈内存溢出...
- 杜克大学用13幅图告诉你人生的真谛,值得深思!
- FFmpeg滤镜:使用colorkey抠图
- 计算机传真,电脑收发传真
- max3232ese_MAX3232CSE使用指南,MAX3232CES和MAX3232ESE有什么区别?
- java计算某天到当前时间的间隔天数
- 垃圾小白羊leetcode刷题记录1
- 查找中位数(分治策略)
- html之简单新闻网制作
- 美化Ubuntu18桌面伪装成MAC桌面
- Excel表中查找、去除重复项方法合集
- hqyj-IO-day2
- 013、静态网页开发
- Zookeeper 安装配置(大数据工程师工作笔记)
- J2EE与javaweb的区别
- 功能安全 李艳文_李艳文:智能网联全新安全问题凸显相关自动驾驶事故逐年增加...
热门文章
- 房产销售数据分析与可视化的设计与实现
- xp访问共享文件夹需要重启服务器,winXP共享文件夹断开、重新连接、重设置密码的方法...
- 小米平板开启位置服务器,小米平板电脑防盗定位方法
- HTML-滚动字幕的源代码(可作滚动公告)
- std::asio小记
- 日常办公,无特殊要求者怎么选择显示器?
- STM32自学笔记-12-和迪文屏的联用
- 韦恩州立大学计算机科学,2019上海软科世界一流学科排名计算机科学与工程专业排名韦恩州立大学排名第301-400...
- CTO、首席架构师、技术总监、研发Leader、高级程序员的职责
- 利用R语言进行探索性数据分析(EDA)