最近 Google 爸爸对 Google Play 上架的应用提出了目标 API 等级要求html
从 2018 年 8 月 1 日起,全部向 Google Play 首次提交的新应用都必须针对 Android 8.0 (API 等级 26) 开发; 2018 年 11 月 1 日起,全部 Google Play 的现有应用更新一样必须针对 Android 8.0。java
Google Play 目标 API 等级(targetSdkVersion)重要变动要求android
同时,国内的华为、360、应用宝也要求开发者适配 Android P,不然应用将被不推荐、隐藏甚至下架(华为),能够看出国内应用市场对于推进应用适配新 API 的决心,虽然没有强制要求适配,但也算国内应用市场的一大进步,相信很快就会有其余应用市场跟进。git
为保障华为用户的使用体验,华为应用市场已在7月份启动Android P版本应用适配检测工做,针对未作适配的应用开发者陆续进行邮件通知。 请您对应用适配这一环节加以重视,并于2018年10月底前完成Android P版本适配工做并自检经过。针对未适配或在Android P版本体验欠佳的应用,华为应用市场将在Android P版本机型上采起下架、不推荐更新或屏蔽策略,可能会对您的推广、用户口碑及品牌产生影响。github
咱们都知道每次 Android 版本的更新都会新增一大波优化功能,好比 Android M 上引入了运行时权限,Android N 上带来了 Doze 模式,Android O 上的后台执行限制bash
总的来讲,新版本会让咱们的 Android 设备更流畅,更省电,隐私性更好。服务器
应用也能够利用新版本的特性以提高用户体验,如 Android M 引入可指定通知栏颜色,以实现彻底沉浸式体验。网络
因此固然要适配新版本啦架构
新版本新增了不少优化,但同时对 APP 的限制也更多,好比在新版本上应用保活愈来愈困难,应用没法在后台作一些偷偷摸摸的事情,有些应用提供商确定不乐意啦,所以国内不少应用对 Android API 适配的积极性不高。
如今各大应用市场联合起来催促开发者适配 Android API,这种状况很定会慢慢有所改观,国内的 Android 应用生态也会愈来愈良好。
扯了这么多,说到底,仍是想说为了国内的 Android 应用生态,你们赶忙适配起来新版本吧
俗话说,不能一口吃个胖子,所以咱们先从 Android O 适配器来,也能达到 Google 爸爸的要求
下面是考拉 APP 适配 Android O 的记录
1. 通知栏
Android 8.0 引入了通知渠道,其容许您为要显示的每种通知类型建立用户可自定义的渠道。用户界面将通知渠道称之为通知类别。
针对 8.0 的应用,建立通知前须要建立渠道,建立通知时须要传入 channelId,不然通知将不会显示。示例代码以下:
// 建立通知渠道
private void initNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = mContext.getString(R.string.app_name);
NotificationChannel channel = new NotificationChannel(mChannelId, name, NotificationManager.IMPORTANCE_DEFAULT);
mNotificationManager.createNotificationChannel(channel);
}
}
// 建立通知传入channelId
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationBarManager.getInstance().getChannelId());
复制代码
developer.android.com/about/versi…
2. 后台执行限制
若是针对 Android 8.0 的应用尝试在不容许其建立后台服务的状况下使用 startService() 函数,则该函数将引起一个 IllegalStateException。
咱们没法得知系统如何判断是否容许应用建立后台服务,因此咱们目前只能简单 try-catch startService(),保证应用不会 crash,示例代码:
Intent intent = new Intent(getApplicationContext(), InitializeService.class);
intent.setAction(InitializeService.INITIALIZE_ACTION);
intent.putExtra(InitializeService.EXTRA_APP_INITIALIZE, appInitialize);
ServiceUtils.safeStartService(mApplication, intent);
public static void safeStartService(Context context, Intent intent) {
try {
context.startService(intent);
} catch (Throwable th) {
DebugLog.i("service", "start service: " + intent.getComponent() + "error: " + th);
ExceptionUtils.printExceptionTrace(th);
}
}
复制代码
developer.android.com/about/versi…
3. 容许安装未知来源应用
针对 8.0 的应用须要在 AndroidManifest.xml 中声明 REQUEST_INSTALL_PACKAGES 权限,不然将没法进行应用内升级。
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
复制代码
4. 主题的 Activity 设置屏幕方向
针对 8.0 的应用,设置了透明主题的Activity,再设置屏幕方向,代码以下:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowIsTranslucent">true</item>
</style>
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme">
</activity>
复制代码
将会抛出如下异常:
java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
复制代码
大概意思是:只有不透明的全屏Activity能够自主设置界面方向
即便知足上述条件,该异常也并不是必定会出现,为何这么说,看下面两种表现:
有点摸不清 Google 的套路了……
可知,targetSdk=26 时,API 26 和 27 都没有问题,因此这个坑暂时放在适配 API 27 时再填吧。
5. 桌面图标适配
针对 8.0 的应用若是不适配桌面图标,则应用图标在 Launcher 中将会被添加白色背景:
适配方法:一块儿来学习Android 8.0系统的应用图标适配吧
适配后的效果:
6. 隐式广播
因为 Android 8.0 引入了新的广播接收器限制,所以您应该移除全部为隐式广播 Intent 注册的广播接收器。将它们留在原位并不会在构建时或运行时令应用失效,但当应用运行在 Android 8.0 上时它们不起任何做用。
显式广播 Intent(只有您的应用能够响应的 Intent)在 Android 8.0 上仍以相同方式工做。
这个新增限制有一些例外状况。如需查看在以 Android 8.0 为目标平台的应用中仍然有效的隐式广播的列表,请参阅隐式广播例外。
developer.android.com/about/versi…
我对隐式广播的理解:
未指定广播接收器类名,经过 Action 发送。若有不妥,还请指教。
须要检查应用静态注册的隐式广播,须要改成动态注册。
7. 网络链接和 HTTP(S) 链接
Android 8.0 对网络链接和 HTTP(S) 链接行为作出了如下变动:
无正文的 OPTIONS 请求具备 Content-Length: 0 标头。以前,这些请求没有 Content-Length 标头。
HttpURLConnection 在包含斜线的主机或颁发机构名称后面附加一条斜线,使包含空路径的网址规范化。例如,它将 example.com 转化为 example.com/。
经过 ProxySelector.setDefault() 设置的自定义代理选择器仅针对所请求的网址(架构、主机和端口)。所以,仅可根据这些值选择代理。传递至自定义代理选择器的网址不包含所请求的网址的路径、查询参数或片断。
URI 不能包含空白标签。 以前,平台支持一种权宜方法,即容许主机名称中包含空白标签,但这是对 URI 的非法使用。此权宜方法只是为了确保与旧版 libcore 兼容。开发者若是对 API 使用不当,将会看到一条 ADB 消息:“URI example..com 的主机名包含空白标签。此格式不正确,将不被将来的 Android 版本所接受。”Android 8.0 废除了此权宜方法;系统对格式错误的 URI 会返回 null。
Android 8.0 在实现 HttpsURLConnection 时不会执行不安全的 TLS/SSL 协议版本回退。
对隧道 HTTP(S) 链接处理进行了以下变动: 在经过链接创建隧道 HTTP(S) 链接时,系统会在 Host 行中正确放置端口号 (:443) 并将此信息发送至中间服务器。以前,端口号仅出如今 CONNECT 行中。 系统再也不将隧道链接请求中的 user-agent 和 proxy-authorization 标头发送至代理服务器。 在创建隧道时,系统再也不将隧道 Http(s)URLConnection 中的 proxy-authorization 标头发送至代理。相反,由系统生成 proxy-authorization 标头,在代理响应初始请求发送 HTTP 407 后将其发送至此代理。
一样地,系统再也不将 user-agent 标头由隧道链接请求复制到创建隧道的代理请求。相反,库为此请求生成 user-agent 标头。
- 若是以前执行的 connect() 函数失败,send(java.net.DatagramPacket) 函数将会引起 SocketException。 若是存在内部错误,DatagramSocket.connect() 会引起 pendingSocketException。对于 Android 8.0 以前的版本,即便 send() 调用成功,后续的 recv() 调用也会引起 SocketException。为确保一致性,如今这两个调用均会引起 > SocketException。
- 在回退到 TCP Echo 协议以前,InetAddress.isReachable() 会尝试执行 ICMP。 对于某些屏蔽端口 7 (TCP Echo) 的主机(例如 google.com),若是它们接受 ICMP Echo 协议,如今也许可以访问它们。 对于确实没法访问的主机,此项变动意味着调用须要两倍的时间才能返回结果。
developer.android.com/about/versi…
这点应用通常无需适配
8. 视图焦点
可点击的 View 对象如今默认也能够成为焦点。若是您但愿 View 对象可点击但不可成为焦点,请在包含 View 的布局 XML 文件中将 android:focusable 属性设置为 false,或者将 false 传递至应用界面逻辑中的 setFocusable()。
developer.android.com/about/versi…
这点基本无需适配
9. 权限
在 Android 8.0 以前,若是应用在运行时请求权限而且被授予该权限,系统会错误地将属于同一权限组而且在清单中注册的其余权限也一块儿授予应用。
对于针对 Android 8.0 的应用,此行为已被纠正。系统只会授予应用明确请求的权限。然而,一旦用户为应用授予某个权限,则全部后续对该权限组中权限的请求都将被自动批准。
例如,假设某个应用在其清单中列出 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE。应用请求 READ_EXTERNAL_STORAGE,而且用户授予了该权限。若是该应用针对的是 API 级别 24 或更低级别,系统还会同时授予 > WRITE_EXTERNAL_STORAGE,由于该权限也属于同一 STORAGE 权限组而且也在清单中注册过。若是该应用针对的是 Android 8.0,则系统此时仅会授予 READ_EXTERNAL_STORAGE;不过,若是该应用后来又请求 > WRITE_EXTERNAL_STORAGE,则系统会当即授予该权限,而不会提示用户。
developer.android.com/about/versi…
考拉中的权限都是按需申请的,不须要修改。
10. Tinker
特别是在Android N以后,因为混合编译的inline策略修改,对于市面上的各类方案都不太容易解决。而Tinker热补丁方案不只支持类、So以及资源的替换,它仍是2.X-8.X(1.9.0以上支持8.X)的全平台支持。
经测试,Tinker在8.0上功能正常。
随着 Android 版本的不断迭代,Android 系统的体验已经愈来愈好了。
Android 系统的绚烂多彩离不开广大的 Android 开发者,咱们做为开发者,咱们应该尽快适配 Android 新版本,让咱们的应用拥有最好的体验。
本篇介绍了 Android O 的适配要点,若有不足,还请指教
下一篇将会介绍 Android P 的适配,敬请期待
迁移自个人简书 2018.09.19