0%

Android各版本适配点

Android M 6.0

增加了运行时的权限申请

Android N 7.0

强制执行StrictMode API,Intent的Uri中scheme不能为file类型。如果要共享文件,需要使用content://类型的data。如果要共享文件,则使用FileProvider。

官方FileProvider说明

官方是这么说明FileProvider的:

FileProvider是ContentProvider的一个特殊子类,方便了应用间的安全的应用内文件共享,通过创建一个content://的Uri而不是一个file://类型的Uri。

使用FileProvider需要经过以下的几个步骤:

  • 声明一个FileProvider
  • 确定可用的文件
  • 获取文件的Uri
  • 为Uri授予临时权限
  • 把Uri提供给其他应用

官方说明:在授权的时候,需要注意的是如果设备的运行API级别位于Android 4.1 (API Level 16)与Android 5.1(API Level 22)之间,需要创建一个ClipData对象,并为这个ClipData对象授予权限

1
2
3
shareContentIntent.setClipData(ClipData.newRawUri("", contentUri));
shareContentIntent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

Android O 8.0

Android 8.0引入了通知Channel,允许为要显示的每种通知类型创建用户可自定义的渠道。

后台限制执行

现在,在Manifest里面注册的广播接收器无法在后台使用。

未知软件源限制

Android 8.0移除了“允许未知来源”的开关。如果想安装应用,则需要申请权限

1
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

注意:这里申请权限需要跳转到“允许安装未知应用”界面进行授权

1
2
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP);

Android P 9.0

Http请求失败

9.0中的默认禁止了Http请求,需要改用Https。可以添加网络配置:

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

然后在Manifest中声明:

1
android:networkSecurityConfig="network_security_config"

可以指定特定域名:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- Android 9.0 上部分域名时使用 http -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">secure.example.com</domain>
<domain includeSubdomains="true">cdn.example1.com</domain>
</domain-config>
</network-security-config>

前台服务

想创建前台服务,需要申请FOREGROUND_SERVICE权限

设备序列号

在 Android 9 中,调用Build.SERIAL 会始终返回 UNKNOWN 以保护用户的隐私。如果你的应用需要访问设备的硬件序列号,那么需要先请求 READ_PHONE_STATE 权限,然后调用 Build.getSerial

Android Q 10

文件的存储

Android 10的文件存储机制改为了沙盒模式,只能访问自己目录下的文件和公共媒体文件,但是10以下的机型还是使用的老式的文件存储方式。

应用私有目录

应用的外部私有目录对应/Android/data/package_name/,内部对应了/data/data/package_name。应用的私有目录文件访问方式与之前的版本保持一致,不需要改动。

共享目录

包含媒体文件、文档以及其他文件。

  • 共享目录需要通过MediaStore API或者Storage Access Framework的方式访问。
  • MediaStore API在共享目录下创建文件或者访问应用自己创建的文件,是不需要申请存储权限的。
  • MediaStore API访问其他应用在共享目录下创建的文件,需要申请存储权限,否则通过ContentResolver查询不到文件的Uri。
  • MediaStore API不能访问其他应用创建的非媒体文件,如pdf、office、doc、txt等,只能通过Storage Access Framework方式访问。

如果应用还未完成适配工作,可以暂时让应用以兼容模式运行,需要在Manifest中声明:

1
android:requestLegacyExternalStorage="true"

然后在代码中判断是否是兼容模式:

1
Environment.isExternalStorageLegacy()

存储访问框架

  • 调用存储相关操作的Intent;
  • 用户看到系统选择器,供其浏览文档提供其并选择将执行存储文件相关的位置或文档;
  • 应用获得对代表用户所选位置或文档的URI的读写访问权限。

但是发现一个不方便的地方:如果采用Storage Access Framework的话,保存文件的时候只能通过打开窗口来选择保存的地方,不能直接在后台完成所有操作。

如果是在10.0之前的话,应该可以直接通过访问文件来读写文件,只要获取了写权限。但是现在10之后,不需要写权限了,各个应用是拥有沙箱机制的。

定位权限

如果需要使用后台位置权限,则需要声明新的权限ACCESS_BACKGROUND_LOCATION

媒体文件位置权限

图片之类的文件会带有位置信息,而这个信息是敏感的。在Android 10之后如果要访问媒体位置,则需要声明ACCESS_MEDIA_LOCATION 权限。

Android R 11

分区存储

从Android 11开始执行强制分区存储机制,之前Android 10中声明的android:requestLegacyExternalStorage="true"已经不起作用了。

另外,Android 11允许使用除了MediaStore API之外的API通过文件路径直接访问存储空间中的媒体文件,包括:

  • File API
  • 原生库,如fopen()

单次权限授予

就是短时间内授予用户权限。

请求位置权限

Android 11中取消了“始终允许”这一选项,也就是不会授予后台访问位置权限。建议递增位置权限请求,比如先请求前台的权限,再在某一需要的时候请求后台权限。

软件包可见性

新特性,用于限制其他软件获取用户当前安装的软件信息。

前台服务类型

如果需要在前台访问位置信息,则需要在Manifest中声明相应的前台服务类型。

权限自动重置

如果用户的应用经过数个月的时间没有使用的话,那么系统就会自动清除该应用的运行时数据来保护用户的隐私。

读取手机号

如果要读取手机号的话,需要在Manifest中声明READ_PHONE_STATE权限。