Android Q 适配指南 让你少走一堆弯路
2019-04-13 11:10 阅读(351)

导读


文中链接请自行科学上网

Android Q Beta 1刚出,讲道理国内是不到下半年不用理睬Q的,但是上月末的一封华为要求适配Q的邮件要求我们在5月底之前完成相关适配,不然应用会被下架。

一开始还心生奇怪,为什么这次华为的邮件来的那么早以及严格。当我仔细阅读了官方文档之后发现Q的更新特别多,且不适配应用可能无法正常运行(不管targetSDK是否为Q)。

国内相关的文章还比较少,本文将总结归纳AndroidQ官方文档并将自己所踩过的坑记录下来,以便大家少走弯路。

本文将从三个角度介绍Android Q的部分适配问题,也是大家开发适配过程中大概率会遇到的问题:

至于Q的新功能及SDK,我粗略扫了一眼,项目中并没有涉及,故暂不介绍,只放出链接AndroidQ新API及功能

Q 行为变更:所有应用


AndroidQ引入了大量更改和限制以增强对用户隐私的保护。

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

权限

受影响应用

如何启用(影响范围)




存储权限

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

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

定位权限

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

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

从后台启动 Activity

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

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

设备标识符(deviceId)

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

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

无线扫描权限

使用 WLAN API 和 Bluetooth API 的应用

以 Android Q 为目标平台

因为从后台启动Activity权限无线扫描权限两种权限的变更影响较少。本文不作详述,如有涉及请查阅官方文档

  从后台启动Activity权限变更仅针对与用户毫无交互就启动一个Activity的情况,(比如微信登陆授权) 复制代码


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

adb shell sm set-isolated-storage on

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

((TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId()

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

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

本文给出一个不变基本不重复的UUID方法。

public static String getUUID() {

String serial = null;

String m_szDevIDShort = "35" +
        Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +

        Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +

        Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +

        Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +

        Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +

        Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +

        Build.USER.length() % 10; //13 位

try {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        serial = android.os.Build.getSerial();
    } else {
        serial = Build.SERIAL;
    }
    //API>=9 使用serial号
    return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
} catch (Exception exception) {
    //serial需要一个初始化
    serial = "serial"; // 随便一个初始化
}
    //使用硬件信息拼凑出来的15位号码
    return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
}

Q 行为变更:以 Android Q 为目标平台的应用


非 SDK 接口限制

非SDK接口限制在Android P中就已提出,但是在Q中,被限制的接口的分类有较大变化

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

项目升级遇到的问题


在AndroidManifest.xml的application节点下加入android:extractNativeLibs="true"

可能有人加了上面代码还是不行,在app/build.gradle中的defaultConfig节点下加入

packagingOptions{ doNotStrip "/armeabi/.so" doNotStrip "/armeabi-v7a/.so" doNotStrip "/x86/.so" }

Didn't find class “org.apache.http.client.methods.HttpPost"

在AndroidManifest.xml的application节点下加入
<uses-library android:name="org.apache.http.legacy" android:required="false"/>


总结

参考文献

官方文档

非SDK接口


作者:吃猫猫的鱼