Android O 适配详细指南,Android 开发三年月薪才 12K
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);}}// 创建通知传入 channelIdNotificationCompat.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>
<activityandroid:name=".MainActivity"android:screenOrientation="portrait"android:theme="@style/AppTheme"></activity>
将会抛出以下异常:
java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
大概意思是:只有不透明的全屏 Activity 可以自主设置界面方向
即使满足上述条件,该异常也并非一定会出现,为什么这么说,看下面两种表现:
targetSdk=26,满足上述条件,API 26 手机没问题,API 27 手机没问题
targetSdk=27,满足上述条件,API 26 手机 Crash,API 27 手机没问题
有点摸不清 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 后将其发送至此代理。
同样地,系统不再将 use
r-agent 标头由隧道连接请求复制到建立隧道的代理请求。相反,库为此请求生成 user-agent 标头。
如果之前执行的 connect() 函数失败,send(java.net.DatagramPacket) 函数将会引发 SocketException。 如果存在内部错误,DatagramSocket.connect() 会引发 pendingSocketException。对于 Android 8.0 之前的版本,即使 send() 调用成功,后续的 recv() 调用也会引发 SocketException。为确保一致性,现在这两个调用均会引发 > SocketException。
评论