Android11 适配

2023-09-18 09:26:03

一、修改targetSdkVersion为30

将build.gradle的目标版本targetSdkVersion修改为30(Android 11)

 targetSdkVersion 30

Android11的改变改变主要影响以Adnroid11 为目标版本的应用(targetSdkVersion>=30才有影响),和所有应用在Android11设备上适配改动(无论targetSdkVersion是多少,只要在Android11设备上运行的应用都有影响)

二、Android11需要适配的地方

1、分区存储

分区存储,将公共区域划分成了不同的集合,并且在媒体文件和其他文档之间建立了清楚的分割。经过划分之后应用不可以随意访问外部存储区中的文件,而只能访问媒体文件。如果想访问包含更多细节数据的其他文档,应用专门向用户申请有关文档的访问权限。

关于分区存储,在Android10就已经推行了,简单的说,就是应用对于文件的读写只能在沙盒环境,也就是属于自己应用的目录里面读写。其他媒体文件可以通过MediaStore进行访问。

但是在android10的时候,Google还是为开发者考虑,留了一手。在targetSdkVersion = 29应用中,设置android:requestLegacyExternalStorage=“true”,就可以不启动分区存储,让以前的文件读取正常使用。但是targetSdkVersion = 30中不行了,强制开启分区存储,设置android:requestLegacyExternalStorage="true"已经无效了。

四种访问文件的方法:

1)应用专属目录

//分区存储空间
val file = File(context.filesDir, filename)//应用专属外部存储空间
val appSpecificExternalDir = File(context.getExternalFilesDir(), filename)

2)访问公共媒体目录文件

   val cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, "${MediaStore.MediaColumns.DATE_ADDED} desc")
        if (cursor != null) {
            while (cursor.moveToNext()) {
                val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
                val uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
                println("image uri is $uri")
            } cursor.close()
        }

3)SAF(存储访问框架–Storage Access Framework)

     val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        intent.type = "image/*"
        startActivityForResult(intent, 100)
        @RequiresApi(Build.VERSION_CODES.KITKAT) 
        override fun onActivityResult(requestCode:Int, resultCode:Int, data:Intent ?){
            super.onActivityResult(requestCode, resultCode, data)
            if (data == null || resultCode != Activity.RESULT_OK) returnif(requestCode == 100) {
                val uri = data.dataprintln("image uri is $uri")
            }
        }

4)获取所有文件权限MANAGE_EXTERNAL_STORAGE(官方不推荐),这个权限是给文件管理类软件、杀毒软件使用的
在清单文件中添加权限,这个权限就是用来获取所有文件的管理权限

    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
        val intent = Intent()
        intent.action = Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
        startActivity(intent)
        //判断是否获取MANAGE_EXTERNAL_STORAGE权限:
        val isHasStoragePermission= Environment.isExternalStorageManager()

2、应用包可见性

在 Android 11 之前,我们可以通过 PackageManager.getInstalledPackages(0) 获取其他所有应用的包名等信息。
Android 11 为了增加安全性,更好地保护用户的隐私,对应用包的可见性做出了一些改动。

当 targetSdkVersion 为 30 时,如果我们用getPackageInfo(“another.app”,0) 获取其他应用包信息时 ,会出现 NameNotFoundException 的异常。

我们可以在 AndroidMainfest 中添加 来适配特定的使用场景:(该配置相当于是添加应用白名单)

已知想获取的包名:

	<queries>
		<package android:name="com.test.application1"/>
		<package android:name="com.test.application2"/>
		<package android:name="com.test.application3"/>
	</queries>

3、权限变化

在 Android 11 中,系统为用户的私人数据提供了更多可供选择的授权方式,应用也加大了后台对位置的访问权限限制。

对应摄像头、位置信息和麦克风这几个数据类型,用户可以授予一次性的临时访问权限。
在这里插入图片描述
这个一次性权限的生效周期指的是:

应用 Activity 可见期间
应用转为后台后的短时间内
前台服务存活期间
当用户撤销单次授权后,应用进程退出,再次打开之后需要对应用进行重新授权期间

4、位置权限

在Android10 之前,我们通过ACCESSCOARRSELOCATION 或 ACCESSFINELOCATION(精确位置) 配置即可申请前后台位置权限。

Android 11将位置权限分为前台和后台两种权限。前文说的主要是前台权限,授权方式没有变化。应用想要申请后台权限,除了需要在清单文件中额外添加 ACCESSBACKGROUNDLOCATION 权限外,还需要应用主动引导用户到指定页面授权。

Android 11 要求面向 API 级别为 30 的应用使用递增式位置权限请求。任何同时申请前台位置权限 (无论是粗略位置还是精确位置) 和后台位置权限的请求都会被忽略并且报错。

需要先申请前台位置权限,然后在稍晚些再申请后台位置权限。

	<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />//后台位置权限
更多推荐

VUE build:gulp打包:测试、正式环境

目录项目结构GulpVUE使用GulpVue安装GulpVue定义Gulp.jspackage.jsonbuild文件夹config文件夹static-config文件夹项目结构GulpGulp是一个自动化构建工具,可以帮助前端开发者通过自动化任务来管理工作流程。Gulp使用Node.js的代码编写,可以更加灵活地管理

STM32 基础学习——GPIO位结构(江科大老师教程)

一、GPIO内部结构1、GPIO外设名称是由GPIOA、GPIOB、GPIOC等命名,共有16个引脚2、每个GPIO模块内,主要包含了寄存器和驱动器这些东西3、寄存器写1,对应的端口就是高电平。写0,对应的端口就是低电平4、寄存器只负责存储数据这是GPIO结构图,总体来说上半部分是输入部分,下半部分是输出部分这是部分是

Bartender for Mac菜单栏图标自定义

Bartender是一款可以帮助用户更好地管理和组织菜单栏图标的macOS软件。它允许用户隐藏和重新排列菜单栏图标,从而减少混乱和杂乱。以下是Bartender的主要特点:菜单栏图标隐藏:Bartender允许用户隐藏菜单栏图标,只在需要时显示。这样可以减少菜单栏的拥挤和视觉干扰,使界面更加整洁和专注。可自定义的菜单栏

Layui快速入门之第九节 表格事件的使用

目录一:事件二:头部工具栏事件三:排序切换事件四:列拖拽宽度后的事件五:列筛选(显示或隐藏)后的事件六:行单击和双击事件七:行右键菜单事件八:单元格编辑事件九:单元格工具事件十:复选框事件十一:单选框事件十二:尾部分页栏事件一:事件table.on('event(filter)',callback);参数event(f

Spring后处理器-BeanPostProcessor

Spring后处理器-BeanPostProcessorBean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过bean的初始化过程((该后处理器的执行时机)),例如:属性的填充、初始化方法init的执行等,其中有一个对外拓展的点BeanPostProcessor,我们称之为bean后

2D游戏开发和3D游戏开发有什么不同?

2D游戏开发和3D游戏开发是两种不同类型的游戏制作方法,它们之间有一些显著的区别:1.图形和视觉效果:2D游戏开发:2D游戏通常使用二维图形,游戏世界和角色通常在一个平面上显示。这种类型的游戏具有平面的外观,就像经典的平台游戏,如《超级马里奥》或《糖果传奇》。3D游戏开发:3D游戏使用三维图形,玩家可以在三维环境中自由

MySQL学习系列(3)-每天学习10个知识

目录1.全文搜索(Full-TextSearch)vs.LIKE操作符2.MySQL中的大数据量处理3.分区(Partitioning)在MySQL中的作用和用法4.MySQL中的数据复制(Replication)5.索引的覆盖和索引下推6.预处理语句(PreparedStatements)7.视图和存储过程8.MyS

C语言知识阶段性总结项目:电子词典

项目需求使用TCP实现客户端和服务端通信使用sqlite存放用户信息客户端需要有登录、注册、查询单词、账号查询记录功能服务器需要实时显示在线用户解决方案使用sqlite创建三个数据库,分别存放用户账号密码,单词表,用户查询记录使用链表存放在线用户的信息,在子线程中循环遍历,达到实时显示在线用户的效果主要的功能代码头文件

大数据(九):数据可视化(一)

专栏介绍结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来!全部文章请访问专栏:《Python全栈教程(0基础)》再推荐一下最近热更的:《大厂测试高频面试题详解》该专栏对近年高频测试相关面试题做详细解答,结合自己多年

Mysql---第六篇

系列文章目录文章目录系列文章目录一、分表后非sharding_key的查询怎么处理,分表后的排序?二、mysql主从同步原理一、分表后非sharding_key的查询怎么处理,分表后的排序?可以做一个mapping表,比如这时候商家要查询订单列表怎么办呢?不带user_id查询的话你总不能扫全表吧?所以我们可以做一个映

SBCS、DBCS、ASCII、MBCS(ANSI)、Unicode

1.三种编码方式和三种字符类型。第一种编码方式是单字节字符集,称之为SBCS,它的所有字符可用一个字节存储。ASCII码就是SBCS。SBCS字符串由一个零字节结尾。第二种编码方式是多字节字符集,称之为MBCS,它包含的字符中有单字节长的字符,也有多字节长的字符。Windows用到的MBCS只有二种字符类型,单字节字符

热文推荐