target SDK升级是一个老生常谈的问题,由于总所周知的原因,很多国内APP的Target SDK版本号还停留在23以前,甚至是19。本文结合项目中实际遇到的问题,简单的梳理一下升级Target SDK遇到的问题。
来自Google Play官方的要求:
Improving app security and performance on Google Play for years to come
同时,国内也终于迎来工信部的要求,手机出厂预置的所有应用android:targetSdkVersion>=26。
这里简单梳理一下从API21->API28的升级工作吧。
Android 5.0 & 5.1
关于Android 5.0和5.1(API 21和API 22),最深的影响就是ART取代Dalvik,成为平台默认设置.
不再支持隐式intent去bindService()
Target SDK部分的变更不多,影响最大的变更可能是不再支持隐式intent去bindService()的方式,简单说就是bindService的intent,不光需要指定Action,还需要指定Service的PackageName,不然系统会报错。
其他的没什么多说的,遇到问题可以自行查看官方文档。
Android 6.0
权限申请
关于Android 6.0(API 23),最值得一提的也就是运行时权限了。这也是很多国内APP迟迟不愿意升级Target SDK的最主要原因,也是我们升级过程中最需要处理的问题。首先明确一点,仅被Android认定为『危险权限』,才需要使用前申请。然后,危险权限根据系统认定,具有以下四种不同的状态:
- 有权限
- 需要询问
- 仅拒绝
- 拒绝+不再提醒
如果权限被拒绝过,下次申请时建议弹窗说明理由。如果用户设置不再提醒,又确实需要,可以引导用户去设置里手动开启。其他的就不多说了,这里给两个比较好的权限库。
一个是google的开源库方案,googlesamples/easypermissions,优点是google出品,代码风格和质量都有保证。不过缺点也很明显,调用方式依赖Activity和Fragment,而项目中很多代码不可能从头改造。
另一个是我强烈推荐的国内的一个开源库方案,yanzhenjie/AndPermission,star数4000+,依赖context+流式调用,同时兼容国内的各类机型,非常好用。
Android 7.0 & 7.1.1
关于Android 7.0和7.1.1(API 24和API 25),也有很多需要开发者注意的地方。
User-added CAs not trusted by default for secure connections
首先是 User-added CAs not trusted by default for secure connections, 也就是说,如果开发者没有配置的话,通过charles等抓包软件,在仅导入用户证书的情况下,是没有办法抓https请求的包的。(如果有https系统的证书,还是可以抓包的)。
具体可以参考 Android 7.1 以上机型Charles抓包解决办法
处理方式其实也很简单,假如期待的是Dev渠道的APK安装包可以信任用户证书,实现抓包,则新建一个xml文件:
1 | <?xml version="1.0" encoding="utf-8"?> |
然后放在Applicaiton所在模块下的src/Dev/res/xml目录下
应用私有目录被限制访问
(系统权限更改-应用私有目录被限制访问)[https://developer.android.com/about/versions/nougat/android-7.0-changes#permfilesys]
简单来说,影响有以下几点:
- 外部App被限制访问App的私有目录。尝试的话将触发SecurityException
- 传递 file:// URI 会触发 FileUriExposedException。分享私有文件内容的推荐方法是使用 FileProvider
具体内容可以参考这篇博文:
关于 Android 7.0 适配中 FileProvider 部分的总结
举两个具体受影响的业务场景:
调起系统相机拍照
之前调起系统拍照的代码:
1 | public void takePhoto() { |
如果在android 7.0以上的机型,则会发现resultCode返回Activity.RESULT_CANCELED,也就是0。处理起来也很简单,Android Support库为我们提供了工具方法:
1 | public void takePhoto() { |
这样即可正常拍照了。
安装apk
Android 6.0 7.0 8.0三个版本Install Apk 采坑记录
这篇博文说的很清楚,这里就不多说了。
Android 8.0
访问用户账户需要授权
首当其冲的是如果没有用户的许可,App无法直接访问Android的系统用具账户。什么意思?在Android系统中,App可以通过AccountManager类,创建和访问用户账户.如Android系统的Google账户,小米手机里面的小米账户等等。此前App仅需有如下权限:
1 | <uses-permission android:name="android.permission.GET_ACCOUNTS" /> |
但Target 26的App,非系统签名的应用则无法获取到系统帐号.原生的系统AccountManager机制提供了两种方式使这些app来获取:
- 由authenticator app或是跟authenticator app相同签名的其他app调用setAccountVisibility(Account account, String packageName, int visibility)来将指定的app设置为帐号可见
- 没有权限的app自己调用newChooseAccountIntent方法来由用户来选择是否允许该app访问对应帐号
方案一般来说用户体验更加好,方案二的原生页面会让用户很难费解.这里就不做具体展开了。
提醒窗口
一些App需要在其他应用和系统窗口上方显示提醒窗口,Target 26的App,使用 SYSTEM_ALERT_WINDOW 权限的应用无法再使用以下窗口类型来显示提醒窗口了:
TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR
替换方案是使用名为 TYPE_APPLICATION_OVERLAY 的新窗口类型.新窗口有一些特性,更多的可以在这里进行了解 提醒窗口
Android 9.0
前台服务
引用官方文档:
针对 Android 9 或更高版本并使用前台服务的应用必须请求 FOREGROUND_SERVICE 权限。 这是普通权限,因此,系统会自动为请求权限的应用授予此权限。
如果针对 Android 9 或更高版本的应用尝试创建一个前台服务且未请求 FOREGROUND_SERVICE,则系统会引发 SecurityException。
(更多内容,待续)