API level targeting to 28,准备好了吗?
- 2019 年 10 月 10 日
- 筆記
【前言】
小编负责的地图手表项目,和Google合作,需要尽快完成targetsdk升级的适配测试工作。
Google Play的目标API级别要求:Google Play 要求新应用(自2019年8月1日起)和应用更新(自2019年11月1日起)将目标API级别至少设为28(至少为Android9.0)。小编对主要的行为变更进行了学习和测试准备
【1. 限制 HTTP 网络请求】
说明
Android9.0中限制了HTTP(明文传输)网络请求,若仍继续使用HTTP请求,则会在日志中提示异常。
测试
(1). app应用请求
理论上都换成https,如有抓到http,需和开发确认,Android9.0限制了明文流量的网络请求,非加密的流量请求,都会被禁止掉。
测试,需覆盖所有模块直接和服务交互的请求(参照项目功能模块list)
(2). app应用涉及下载任务的模块
例如地图项目:离线地图、离线导航、导航音色包(语音广场)、样式文件、模板包
(3). 应用内置的己方的sdk
例如地图项目:mapsdk、定位sdk、mapmatch、pushsdk、导航引擎sdk、数据引擎sdk、搜索引擎sdk
(4). 第三方的sdk
例如地图项目:分享、登录注册、滴滴打车
(5). wap页面
例如:webview打开图片等、常见问题及帮助等
(6). 应用服务端支持
如果仍有部分接口数据没完全转成https,需要一个类似通配符,允许所有的http流量。
【2. 弃用 Apache HTTPClient】
说明
官方在Android 9.0 中,移除了所有 Apache HTTP Client 相关的类。
测试
覆盖应用中的各种请求,生效性,尤其是下载相关模块(离线资源、语音包等)
覆盖第三方库,涉及请求的模块,功能正常
sdk,是否有使用http客户端,如有使用,会找不到该库,抛出异常
分享sdk,如qq分享sdk、微信分享等
注意:有上传图片,需要接口回调的模块
【3. 限制非SDK接口的调用】
3.1 说明
为帮助确保应用稳定性和兼容性,此平台对某些非SDK函数和字段的使用进行了限制;无论您是直接访问这些函数和字段,还是通过反射或JNI 访问,这些限制均适用。在Android 9中,您的应用可以继续访问这些受限的接口;该平台通过toast和日志条目提醒您注意这些接口。如果您的应用显示这样的toast,则必须寻求受限接口之外的其他实现策略。
3.2 官方对非 SDK 接口的分类
共分为三类:黑名单、灰名单、白名单。其中灰名单又被分为浅灰名单和深灰名单。(非受限灰名单中的非SDK 接口称为浅灰名单,而受限灰名单中的非 SDK 接口称为深灰名单)
(1). 白名单(Whitelist)
此列表中的接口已在 Android 框架软件包索引中正式记录,它们是受支持的接口,没有任何访问限制,可以自由使用。
(2). 灰名单(light-greylist和dark-greylist)
light-greylist(浅灰名单):对于此名单中的非SDK 接口,官方暂未找到可替代的 SDK 接口,因此开发者仍可继续访问(如果targetSdkVersion 大于等于28时会出现警告)。dark-greylist(深灰名单):targetSdkVersion小于28时仍可继续使用此名单中的接口,但会出现警告提示;大于等于28时,这些接口将会限制访问。
(3). 应用内置的己方的sdkblacklist(黑名单):
无论targetSdkVersion 为多少,只要应用运行在Android 9.0 平台上,访问此名单中的任何一个接口都会受限(系统就会抛出错误)
3.3 应用尝试访问黑名单中的非 SDK 接口时可能会出现的预期行为

3.4 测试应用是否使用非 SDK 接口
(1). 使用 Android 9.0 或更高版本的设备调试应用
在您的应用上运行测试时,如果该应用访问了某些非SDK 接口,系统就会输出一条日志消息。您可以检查应用的日志消息,查找以下详细信息:
- 声明的类、名称和类型(采用Android 运行时所使用的格式)。
- 访问方式:链接、反射或JNI。
- 所访问的非SDK 接口属于哪个列表。
您可以使用adb logcat 来查看这些日志消息,这些消息显示在所运行应用的PID 下。例如:

(2). 使用StrictMode API 进行测试
(3). 使用google工具veridex 对应用进行扫描
可以在APK上运行静态分析工具veridex。veridex工具会扫描APK的整个代码库(包括所有第三方库),并报告发现的所有使用非SDK接口的行为,该工具的扫描结果会列出应用对于三个限制名单中的接口的调用细节。
veridex工具也在不断地更新,它存在以下局限性:
- 它无法检测到通过JNI 实现的调用。
- 它只能检测到一部分通过反射实现的调用。
- 它对非活动代码路径的分析仅限于API 级别的检查。
【4. 前台服务权限】
说明
在Android 9.0 中,应用在使用前台服务之前必须先申请FOREGROUND_SERVICE权限,否则就会抛出Security Exception 异常。
处理
由于FOREGROUND_SERVICE权限只是普通权限,因此开发者只需在AndroidManifest.xml中注册此权限即可,系统会自动对此权限进行授权:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
【5.不允许共享Web View数据目录】
说明
Android 9.0 为了改善应用稳定性和数据完整性,应用无法再让多个进程共用同一Web View 数据目录。
测试
应用程序不能再跨进程共享单个WebView数据目录。如果您的应用有多个使用Web View,CookieManager或android.webkit包中的其他API的进程,则当第二个进程调用WebView方法时,您的应用将崩溃。
【6. 其他行为变更】
6.1 Build.SERIAL (设备唯一标识符)被弃用
说明
Android 9.0 之前,开发者可以使用Build.SERIAL 获取设备的序列号。现在这个方法被弃用了,Build.SERIAL将始终设置为 "UNKNOWN" 以保护用户的隐私。
处理
如果您的应用需要访问设备的硬件序列号,适配的方法为:先请求READ_PHONE_STATE 权限,然后调用Android9 中新增的 Build.getSerial()方法。
测试
最新版本,targetSdkVersion升级后,能正常拿到该参数。涉及到需要有设备序列号相关的请求,参数完整可用
6.2 限制访问通话记录
说明
Android 9.0 引入CALL_LOG 权限组并将 READ_CALL_LOG、WRITE_CALL_LOG和 PROCESS_OUTGOING_CALLS 权限移入该组。在之前的 Android 版本中,这些权限位于PHONE 权限组。
测试
如果应用需要访问通话记录或者需要处理去电,则您必须向CALL_LOG 权限组,明确请求这些权限。否则会发生SecurityException
6.3 限制访问电话号码
说明
在未获得READ_CALL_LOG 权限的情况下,除了应用的用例需要的其他权限之外,运行于Android 9.0 上的应用无法读取电话号码或手机状态。
测试
与来电和去电关联的电话号码可在手机状态广播(比如来电和去电的手机状态广播)中看到,并可通过PhoneStateListener 类访问。但是,如果没有READ_CALL_LOG 权限,则 PHONE_STATE_CHANGED 广播和PhoneStateListener“提供的电话号码字段为空”。
6.4 后台对传感器的访问受限
说明
Android9 限制后台应用访问用户输入和传感器数据的能力。如果您的应用在运行Android 9 设备的后台运行,系统将对您的应用采取以下限制:
- 您的应用不能访问麦克风或摄像头。
- 使用连续报告模式的传感器(例如加速度计和陀螺仪)不会接收事件。
- 使用变化或一次性报告模式的传感器不会接收事件。
- 如果您的应用需要在运行Android 9 的设备上检测传感器事件,请使用前台服务。
测试
例如地图项目:测试覆盖后台导航,后台录音(如唤醒)等
6.5 限制访问 Wi-Fi 位置和连接信息
在Android 9 中,应用进行 Wi-Fi 扫描的权限要求比之前的版本更严格。
类似的限制也适用于 getConnectionInfo() 函数,该函数返回描述当前Wi-Fi 连接的 WifiInfo 对象。如果调用应用具有以下权限,则只能使用该对象的函数来检索SSID 和 BSSID 值:
- ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION
- ACCESS_WIFI_STATE
检索SSID 或 BSSID 还需要在设备上启用位置服务(在 Settings> Location 下)。
6.6 电话信息现在依赖设备位置设置
如果用户在运行Android 9 的设备上停用设备定位,则以下函数不提供结果:
- getAllCellInfo()
- listen()
- getCellLocation()
- getNeighboringCellInfo()
6.7 Android 9.0 移除了Crypto Java 加密架构 (JCA) 提供程序
从Android 9 开始,Crypto JCA 提供程序已被移除。调用SecureRandom.getInstance("SHA1PRNG","Crypto"),将抛出NoSuchProviderException。
【参考】
https://developer.android.com/about/versions/pie/android-9.0-changes-28?hl=zh-cn
https://developer.android.com/about/versions/pie/android-9.0-migration?hl=zh-CN
https://juejin.im/post/5cbc146751882541625684bd
https://blog.csdn.net/jjzhoujun2010/article/details/89647738
https://blog.csdn.net/qq_38520096/article/details/90579475