Android Q 适配指南
在Android 10开始版本中,官方的改动较大,相应的开发者适配成本还是很高的。
这里按照2019.11.11 google android q workshop
流程,大概说明一下Android Q适配需要注意的内容。虽然是大概介绍,但应该是目前最全的适配攻略了...
- 非SDK 接口
- 设备ID
- 外部存储
- 权限
- 新功能——夜间模式
官方适配文档:
https://developer.android.com/about/versions/10
一、非SDK接口
官方文档:针对非 SDK 接口的限制
官方从 Android 9(API 级别 28)开始,对应用使用的非 SDK 接口实施了限制。
如果你的APP通过引用非 SDK 接口
或尝试使用反射或 JNI 来获取句柄
,这些限制就会起作用。官方给出的解释是为了提升用户体验、降低应用崩溃
风险。
1.1、非SDK接口检测工具
官方给出了一个检测工具,下载地址:veridex
veridex使用方法:
appcompat.sh --dex-file=apk.apk
1.2、blacklist、greylist、greylist-max-o、greylist-max-p含义
以上截图中,blacklist、greylist、greylist-max-o、greylist-max-p含义如下:
- blacklist 黑名单:禁止使用的非SDK接口,运行时直接Crash(因此必须解决)
- greylist 灰名单:即当前版本仍能使用的非SDK接口,但在下一版本中可能变成被限制的非SDK接口
- greylist-max-o: 在targetSDK<=O中能使用,但是在targetSDK>=P中被禁止使用的非SDK接口
- greylist-max-p: 在targetSDK<=P中能使用,但是在targetSDK>=Q中被禁止使用的非SDK接口
如果觉得我没有说清楚,可以看以下 2019.11.11 google android q workshop PPT 截图
1.3、Android Q 加固 与 热修复
关于加固与热修复,官方也提供了相应的API
-
加固
-
热修复
注:
未适配Android Q的应用,若使用了blacklist 相关接口,在Android Q系统上打开时,会直接Crash!
未适配Android Q的应用,若使用了blacklist 相关接口,在Android Q系统上打开时,会直接Crash!
未适配Android Q的应用,若使用了blacklist 相关接口,在Android Q系统上打开时,会直接Crash!
二、设备ID
从Android 10开始已经无法完全标识一个设备
,曾经用mac地址、IMEI
等设备信息标识设备的方法,从Android 10开始统统失效。而且无论你的APP是否是配过Android 10。
2.1、IMEI等设备信息
从Android10开始普通应用
不再允许请求权限android.permission.READ_PHONE_STATE
。
而且,无论你的App是否适配过Android Q(既targetSdkVersion
是否大于等于29),均无法再获取到设备IMEI
等设备信息。
受影响的API如下:
Build.getSerial();
TelephonyManager.getImei();
TelephonyManager.getMeid()
TelephonyManager.getDeviceId();
TelephonyManager.getSubscriberId();
TelephonyManager.getSimSerialNumber();
targetSdkVersion<29
的应用,其在获取设备ID时,会直接返回null
targetSdkVersion>=29
的应用,其在获取设备ID时,会直接跑出异常SecurityException
如果您的App希望在Android 10以下的设备中仍然获取设备IMEI等信息
,可按以下方式进行适配:
2.2、Mac地址随机分配
从Android10开始,默认情况下,在搭载 Android 10 或更高版本的设备上,系统会传输随机分配的 MAC 地址。(既从Android 10开始,普通应用已经无法获取设备的真正mac地址,标识设备已经无法使用mac地址)
2.3、如何标识设备唯一性?
Google给出的解决方案是:如果您的应用有 追踪非登录用户重装
的需求,可用ANDROID_ID
来标识设备。
- ANDROID_ID的生成规则为:
签名+设备信息+设备用户
- ANDROID_ID重置规则:
设备恢复出厂设置时,ANDROID_ID将被重置
String androidId = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
也就是从Android 10开始已经无法完全标识一个设备
,曾经用mac地址、IMEI
等设备信息标识设备的方法,从Android 10开始统统失效。而且无论你的APP是否是配过Android 10。
求高手留言解答:
在Android 10系统上,目前本人尚未找到标识设备唯一性的办法,如果大家有办法希望留言告知!!!
三、外部存储
官方文档:
外部存储访问权限范围限定为应用文件和媒体
Manage scoped external storage access
为解决截图中的问题,从Android Q开始,官方对外部存储进行了一定的限制。
To give users more control over their files and to limit file clutter, apps targeting Android 10 (API level 29) and higher are given scoped access into an external storage device, or scoped storage, by default. Such apps can see only their app-specific directory—accessed using Context.getExternalFilesDir()—and specific types of media. It's a best practice to use scoped storage unless your app needs access to a file that doesn't reside in either the app-specific directory or the MediaStore.
为了使用户更改的管理Sdcard中的文件,解决文件混乱的问题。从Android 10开始(API level 29),Android将对外部存储
进行一定的限制。
默认情况下,对于外部存储,App只能通过Context.getExternalFilesDir()
访问自己的特定文件目录;
以及系统特定的文件类型目录(例:照片、屏幕快照、视频 等)。
3.1、APP专属路径
对于App专属 内部存储路径
与外部存储路径
的访问,将不再需要 READ_EXTERNAL_STORAGE
与 WRITE_EXTERNAL_STORAGE
权限:
- 内部存储路径
/data/data/<包名>/
- 外部存储路径
/storage/Android/data/<包名>/
Android Q 存储目录的获取,可参考以下文档:Android Sdcard存储目录
Android Q 存储目录的获取,可参考以下文档:Android Sdcard存储目录
Android Q 存储目录的获取,可参考以下文档:Android Sdcard存储目录
3.2、手机共享路径
读取其他APP创建的共享文件,例:相册、屏幕快照 等,则需要申请READ_EXTERNAL_STORAGE
权限:
- 图片:Photos、Screenshots 使用MediaStore.Images API访问
- 视频 使用MediaStore.Video API访问
- 音频 使用 MediaStore.Audio API访问
3.3、Downloads文件夹
读取手机的Downloads文件夹,不需要任何权限,需要使用API Storage Access Framework
四、权限相关
主要包括:
- 在后台运行时访问设备位置信息
- 从后台启动 Activity 的限制
- 屏幕录制
- 摄像头和麦克风
- 剪切板隐私限制
4.1、在后台运行时访问设备位置信息
Android 10 引入了 ACCESS_BACKGROUND_LOCATION
权限。
若应用在后台运行时,访问手机位置,需要动态申请该权限,用户则可以选择拒绝。
官方给出的数据,大部分用户对位置信息是比较敏感的。而且大部分用户是不允许应用在后台使用位置信息的。
4.2、从后台启动 Activity 的限制
4.3、屏幕录制
不需要手动申请权限,但官方 API内部会向用户弹窗申请权限
4.4、摄像头和麦克风
Android 9 摄像头和麦克风 后台权限已经移除了
4.5、活动探知——新增权限
4.6、剪切板隐私限制
从Android P开始,除非你的应用是默认输入法,否则它无法访问用户的剪贴板数据;但向剪切板写入数据不影响。
五、新功能——夜间模式
关于夜间模式,感兴趣的同学,可以查看我的另一篇文档: