安卓10.0新特性与开发适配

本文将重点介绍该版本特性中部分需要开发适配的部分。汇总自己踩过的坑以及百度所得,本文会持续更新。

背景:谷歌在GoogleI / O 2019发布了Android Q Beta X。对当前应用影响重大,急需适配。

API = 29;主要影响分类:

  • 影响所有应用的行为变更(不管targetSdk是多少,对所有跑在Q设备上的应用均有影响)
  • 影响以 Android Q 为目标平台的应用的行为变更(targetSDK == Q ,且跑在Q设备上的应用才有影响)
  • 项目升级遇到的问题(这个没有实践过,怕误导大家,在此不讨论)

影响所有应用的行为变更

用户隐私权限变更:AndroidQ引入了大量更改和限制以增强对用户隐私的保护。具体变更如下:

权限受影响应用如何启用(影响范围)
存储权限访问和共享外部存储设备中的文件的应用adb shell sm set-isolated-storage on(下文详述)
定位权限在后台时请求访问用户位置信息的应用这种权限策略在 Android Q 上始终处于启用状态
从后台启动 Activity不需要用户互动就启动 Activity 的应用关闭允许系统执行后台活动开发者选项即可启用限制
设备标识符(deviceId)访问设备序列号或 IMEI 的应用在搭载 Android Q 的设备上安装应用
无线扫描权限使用 WLAN API 和 Bluetooth API 的应用以 Android Q 为目标平台

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

沙盒,简单而言就是应用专属文件夹,并且访问这个文件夹无需权限。
谷歌官方推荐应用在沙盒内存储文件的地址为Context.getExternalFilesDir()下的文件夹。
比如要存储一张图片,
则应放在Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)中。
  • 操作自己APP的内部外部存储无需任何权限
    多媒体文件(照片,音频,视频)可以通过MediaStore进行操作。
    其他文件可以通过文件路径以及File API进行操作,应用卸载时,该目录会被清除。
  • 访问系统媒体文件:Q中引入了一个新定义媒体文件的共享集合,比如照片,音乐,视频等,需要申请新的媒体权限,READ_MEDIA_IMAGES,READ_MEDIA_VIDEO,READ_MEDIA_AUDIO,申请方法同原来的存储权限。
  • 访问系统下载文件:对于系统下载文件夹的访问,暂时没做限制,但是,要访问其中其他应用的文件,必须允许用户使用SAF(存储访问框架)来选择文件。
  • 访问其他沙盒的多媒体文件需要申请READ_EXTERNAL_STORAGE权限。                                                                                       必须使用MediaStore和ContentResolver来进行文件的访问和操作。
  • 访问其他沙盒的非多媒体文件,必须使用SAF(存储访问框架),也就是打开系统的文件选择器
  • SAF可以访问任何一个文件,而无需请求任何权限。

2、定位权限:如果应用需要在后台时也获得用户位置,就需要动态申请ACCESS_BACKGROUND_LOCATION权限。

与现有的 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 权限不同,新权限仅会影响应用在后台运行时对位置信息的访问权。除非应用的某个 Activity 可见或应用正在运行前台服务,否则应用将被视为在后台运行。

targetSDK <= P 应用如果请求了ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION权限,Q设备会自动帮你申请ACCESS_BACKGROUND_LOCATION权限。

3、不可重置的设备标识符限制:从 Android 10 开始,去掉了READ_PHONE_STATE权限,取而代之的是一个系统级别的权限:READ_PRIVILEGED_PHONE_STATE(只提供给系统app),只有拥有该权限才能访问设备的不可重置标识符(包含 IMEI 和序列号)。那么在Android Q平台,我们的应用也不会再有IMEI和序列号。

受影响的方法:

针对(targetSDK >= 29)的设备唯一标识符适配,谷歌官方有提供解决方案,但是ID可变。ANDROID_ID的获取一直不受影响,但可能由于机型原因返回null,两种方法半斤八两。目前没有很好的解决方案。取ANDROID_ID适配如下:

public static String getDeviceId(Context context) {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
        Log.e(TAG, "Have not permission to obtain DeviceId");
        return "";
    }
    if (Build.VERSION.SDK_INT >= 29) {
        return getAndroidId(context);
    }
    TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    return telephonyManager.getDeviceId();
}

4、禁止应用后台弹页面

Android Q在开发者选项中:关闭允许系统执行后台活动开发者选项即可启用限制。只能通过用户的交互来打开活动如果存在该场景的应用(比如闹钟、语音、视频电话等),需要通过通知提醒的方式解决。

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

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

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

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

非SDK接口介绍:为了确保应用稳定性和兼容性,Android 平台开始限制您的应用可在 Android 9(API 级别 28)中使用哪些非 SDK 接口。Android Q 包含更新后的受限非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。

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

获取方法报错信息
Dalvik instruction referencing a fieldNoSuchFieldError thrown
Dalvik instruction referencing a methodNoSuchMethodError 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

非SDK接口查找:如果不确定自己的应用是否使用了非 SDK 接口,则可以测试该应用进行确认。当你调用了非SDK接口时,会有类似Accessing hidden XXX的日志:

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

但是一个大项目到底哪里使用了这些方法,靠review代码和看日志肯定是不现实的,谷歌官方也提供了官方检查器veridex用来检测一个apk中哪里使用了非SDK接口。veridex下载地址:https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat,选择相应版本对应下载即可。

下载解压后命令行cd到veridex目录下使用./appcompat.sh --dex-file=Q.apk即可自动扫描。Q.apk为包的绝对路径,如果包与veridex在相同目录下直接输入包文件名即可。扫描结果分为两部分,一部分为被调用的非SDK接口的位置,另一部分为非SDK接口数量统计。

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

官方要求targetSDK>=P的应用不使用这些方法,并寻找其他的公共API去替代这些非SDK接口,如果找不到,则可以向谷歌申请,请求一个新的公共API https://developer.android.com/distribute/best-practices/develop/restrictions-non-sdk-interfaces#feature-request (一般不需要)。

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

  • 在自定义View的过程中为了方便,使用反射修改某个参数。
  • 三方SDK中使用了非SDK接口(这种情况比较多)。

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值