Android Q 适配

  1. 简介

首先Android Q将会何时发布呢?预计2019年3月为开发者预览构建发布公开测试版,预计Android Q开发者预览1(Android Q DP1)将在3月中旬的某天通过发布会宣布推出,而第一个公共测试版本可能会在2019年5月发布,稳定版本应该可能与Android Pie发布时间基本同步,在2019年8月。

Android Q Beta 1刚出,但是3月末的一封华为要求适配Q的邮件要求我们在5月底之前完成相关适配,不然应用会被下架。

废话不多说,开始

  1. Q行为变更 所有应用 (不管targetSdk是多少,对所有跑在Q设备上的应用均有影响)
    1. 用户隐私权限变更(AndroidQ引入了大量更改和限制以增强对用户隐私的保护。

官方文档将这一部分内容独立于Q 行为变更:所有应用来介绍,是因为这一部分内容庞大且重要 ,Q的最大更新就是用户隐私权限变更。具体变更的权限如下

权限

受影响应用

如何启用(影响范围)

存储权限

访问和共享外部存储设备中的文件的应用

adb shell sm set-isolated-storage on(下文详述)

定位权限

在后台时请求访问用户位置信息的应用

这种权限策略在 Android Q 上始终处于启用状态

从后台启动 Activity

不需要用户互动就启动 Activity 的应用

关闭允许系统执行后台活动开发者选项即可启用限制

设备标识符(deviceId)

访问设备序列号或 IMEI 的应用

在搭载 Android Q 的设备上安装应用

无线扫描权限

使用 WLAN API 和 Bluetooth API 的应用

以 Android Q 为目标平台

 

以下介绍存储权限,定位权限设备标识符三种权限的变更与适配

  1. targetSDK<=P 应用如果请求ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION权限,Q设备会自动帮你申请ACCESS_BACKGROUND_LOCATION权限。
  2. 访问自己文件:Q中用更精细的媒体特定权限替换并取消了 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE权限,并且无需特定权限,应用即可访问自己沙盒中的文件。
  3. 访问系统媒体文件:Q中引入了一个新定义媒体文件的共享集合,如果要访问沙盒外的媒体共享文件,比如照片,音乐,视频等,需要申请新的媒体权限:READ_MEDIA_IMAGES,READ_MEDIA_VIDEO,READ_MEDIA_AUDIO,申请方法同原来的存储权限。
  4. 访问系统下载文件:对于系统下载文件夹的访问,暂时没做限制,但是,要访问其中其他应用的文件,必须允许用户使用系统的文件选择器应用来选择文件。
  5. 访问其他应用沙盒文件:如果你的应用需要使用其他应用在沙盒内创建的文件,请点击使用其他应用的文件
  6. 模拟器

Android Q Beat1中,谷歌暂未开放存储权限的改动。我们需要使用adb命令adb shell sm set-isolated-storage on来开启模拟器对于存储权限的变更来进行适配。

  1. 真机

当满足以下每个条件时,将开启兼容模式,即不开启Q设备中的存储权限改动:

1.应用targetSDK<=P。
2.应用安装在从 Android P 升级到 Android Q 的设备上。

但是当应用重新安装(更新)时,不会重新开启兼容模式,存储权限改动将生效。

  1. 存储权限

Android Q 在外部存储设备中为每个应用提供了一个“隔离存储沙盒”(例如 /sdcard)。任何其他应用都无法直接访问您应用的沙盒文件。由于文件是您应用的私有文件,因此您不再需要任何权限即可在外部存储设备中访问和保存自己的文件。此变更可让您更轻松地保证用户文件的隐私性,并有助于减少应用所需的权限数量。

沙盒,简单而言就是应用专属文件夹,并且访问这个文件夹无需权限。谷歌官方推荐应用在沙盒内存储文件的地址为Context.getExternalFilesDir()下的文件夹。比如要存储一张图片,则应放在Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)中。

以下将按访问的目标文件的地址介绍如何适配。

所以请判断当应用运行在Q平台上时,取消READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE两个权限的申请。并替换为新的媒体特定权限。

  1. 关于存储权限的(如何启用)影响范围

所以按官方文档所说,无论targetSDK是否为Q,必须对应用进行存储权限改动的适配。

在我的测试中,当targetSDK<=P,在Q Beat1版上申请两个旧权限时会自动改成申请三个新权限,不会影响应用正常使用,但当targetSDK==Q时,申请旧权限将失败并影响应用正常使用。

 

  1. 定位权限

为了让用户更好地控制应用对位置信息的访问权限,Android Q 引入了新的位置权限 ACCESS_BACKGROUND_LOCATION。与现有的 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 权限不同,新权限仅会影响应用在后台运行时对位置信息的访问权。除非应用的某个 Activity 可见或应用正在运行前台服务,否则应用将被视为在后台运行。

与iOS系统一样,Q中也加入了后台位置权限ACCESS_BACKGROUND_LOCATION,如果应用需要在后台时也获得用户位置(Uber),就需要动态申请ACCESS_BACKGROUND_LOCATION权限。当然如果不需要的话,应用就无需任何改动

  1. 设备唯一标识符

从 Android Q 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 签名权限才能访问设备的不可重置标识符(包含 IMEI 和序列号)。许多用例不需要不可重置的设备标识符。如果您的应用没有该权限,但您仍尝试查询标识符的相关信息。会返回空值或报错。

设备唯一标识符需要特别注意,原来的READ_PHONE_STATE权限已经不能获得IMEI和序列号,如果想在Q设备上通过

((TelephonyManager)getActivity().getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId()获得设备ID,会返回空值(targetSDK<=P)或者报错(targetSDK==Q)。且官方所说的READ_PRIVILEGED_PHONE_STATE权限只提供给系统app,所以这个方法算是废了。

谷歌官方给予了设备唯一ID最佳做法,但是此方法给出的ID可变,可以按照具体需求具体解决。

  1. minSDK警告

在 Android Q 中,当用户首次运行以 Android 6.0(API 级别 23)以下的版本为目标平台的任何应用时,Android平台会向用户发出警告。如果此应用要求用户授予权限,则系统会先向用户提供调整应用权限的机会,然后才会允许此应用首次运行。

 

歌要求运行在Q设备上的应用targetSDK>=23,不然会向用户发出警告。

 

  1. Q 行为变更:以 Android Q 为目标平台的应用
    1. 非SDK接口限制

非SDK接口限制就是某些SDK中的私用方法,如private方法,你通过Java反射等方法获取并调用了。那么这些调用将在target>=Ptarget>=Q的设备上被限制使用,当你使用了这些方法后,会报错:

获取方法

报错信息

Dalvik instruction referencing a field

NoSuchFieldError thrown

Dalvik instruction referencing a method

NoSuchMethodError thrown

Reflection via Class.getDeclaredField() or Class.getField()

NoSuchFieldException thrown

Reflection via Class.getDeclaredMethod(), Class.getMethod()

NoSuchMethodException thrown

Reflection via Class.getDeclaredFields(), Class.getFields()

Non-SDK members not in results

Reflection via Class.getDeclaredMethods(), Class.getMethods()

Non-SDK members not in results

JNI via env->GetFieldID()

NULL returned, NoSuchFieldError thrown

JNI via env->GetMethodID()

NULL returned, NoSuchMethodError thrown

 

    1. 非SDK接口查找

如果您不确定自己的应用是否使用了非 SDK 接口,则可以测试该应用进行确认

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)

 

项目到底哪里使用了这些方法,靠review代码和看日志肯定是不现实的,谷歌官方也提供了官方检查器veridex用来检测一个apk中哪里使用了非SDK接口。

其中有windows,linuxmac版本,对应下载即可。下载解压后命令行cdveridex目录下使用./appcompat.sh --dex-file=Q.apk即可自动扫描。Q.apk为包的绝对路径,如果包与veridex在相同目录下直接输入包文件名即可。

扫描结果分为两部分,一部分为被调用的非SDK接口的位置,另一部分为非SDK接口数量统计,例如:

所以从适配Q的角度出发,除了greylist我们可以暂时不解决以外,其余三种类型的非SDK接口需要我们进行适配。

greylist: 灰名单,即当前版本仍能使用的非SDK接口,但在下一版本中可能变成被限制的非SDK接口

blacklist:黑名单,使用了就会报错。也是我们项目中必须解决的非SDK接口

greylist-max-o: 在targetSDK<=O中能使用,但是在targetSDK>=P中被限制的非SDK接口

greylist-max-p: 在targetSDK<=P中能使用,但是在targetSDK>=Q中被限制的非SDK接口

 

    1. 非SDK接口适配

如果您的应用依赖于非 SDK 接口,则应该开始计划迁移到 SDK 替代方案。如果您无法为应用中的某项功能找到使用非 SDK 接口的替代方案,则应该请求新的公共 API。

官方要求targetSDK>=P的应用不使用这些方法,并寻找其他的公共API去替代这些非SDK接口,如果找不到,则可以向谷歌申请,请求一个新的公共API(一般不需要)。

项目中使用非SDK接口大概率有以下两种情况:

第一种是好解决的,毕竟是我们自己写的代码。

第二种就头疼了,只能更新到最新的三方SDK版本,或者提工单、换库(也是整个适配过程中工作量最庞大的部分)。

在自定义View的过程中为了方便,使用反射修改某个参数。

三方SDK中使用了非SDK接口(这种情况比较多)。

 

更多 Android Q 新特性请查看 https://android-developers.googleblog.com

 

你可能感兴趣的:(Andorid)