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 | shareContentIntent.setClipData(ClipData.newRawUri("", contentUri)); |
Android O 8.0
Android 8.0 引入了通知 Channel,允许为要显示的每种通知类型创建用户可自定义的渠道。
后台限制执行
现在,在 Manifest 里面注册的广播接收器无法在后台使用。
未知软件源限制
Android 8.0 移除了“允许未知来源”的开关。如果想安装应用,则需要申请权限
1 | <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/> |
注意:这里申请权限需要跳转到“允许安装未知应用”界面进行授权
1 | Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES); |
Android P 9.0
Http请求失败
9.0 中的默认禁止了 Http 请求,需要改用 Https。可以添加网络配置:
1 |
|
然后在 Manifest 中声明:
1 | android:networkSecurityConfig="network_security_config" |
可以指定特定域名:
1 |
|
前台服务
想创建前台服务,需要申请 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
权限。