原文地址(QQ音乐微信公众号首发): https://mp.weixin.qq.com/s?__biz=MzI1NjEwMTM4OA==&mid=2651232573&idx=1&sn=56963d1ecb1eeea2c82ec88d9667c0b0&chksm=f1d9e45ec6ae6d480b1b8ab73b
前段时间解决了几个 QQ 音乐多窗口屏幕显示的 bug,虽然这个问题最终不是 Android O 版本的问题,多窗口是 Android 7.1 之后引入的(关于多窗口适配需要注意的地方,可以看看这篇文章:Android Multi-Window详细介绍),但是趁此机会了解一下 Android O 版本的新特性也不错,而且 Google IO 大会刚刚过去,趁这个热度介绍一下。
在大会上介绍到的 Android O 新版本更新和优化主要集中在两个方面:Fluid Experiences 和 Vitals,Fluid Experience 主要包含了四个显著特性:Notification Dots, Picture In Picture, Autofill Framework 和 Smart Text Selection;而 Vitals 主要在电池续航、安全、启动时间以及稳定性这几个方面做优化。
Android O 版本重新设计了通知,让通知的管理更加方便,首先引入了通知渠道用来让用户统一管理通知,当 targetApi 设置为 O 版本时,必须要实现一个或多个通知渠道,如果设置为 O 版本之前的版本,在 O 版本设备上的行为则和 7.x 版本保持一致。通知渠道提供了一种将应用内的通知变成一个个易于管理组的方法,通知渠道创建并提交到 notification manager 后,便无法通过编程方式修改通知渠道的行为,这些设置之后则由用户掌控。用户现在可以使用一致的系统 UI 管理大多数与通知有关的设置。所有发布至同一通知渠道的通知都具有相同的行为。当用户长摁通知或者通过设置去到通知的设置页面的时候,可以看到这些界面:
通过这个设置页面可以看到,用户可以将应用所有的通知渠道关闭,或者关闭某一个单独的通知渠道,每一个通知渠道也有相应的行为,用户可以去自行修改,比如修改通知渠道的优先级,如果支持的话,用户还可以去声明通知是否同时显示为应用的角标。Android O 还引入了通知角标,当一个应用的通知没有 dismiss 的时候,会在应用的图标上面显示一个角标,长摁这个应用的图标,也会显示通知的详情信息:
O 版本弃用了对单个通知设置优先级的功能,现在是对通知渠道设置优先级,该通知渠道的所有通知都适用于该优先级,优先级从 IMPORTANCE_NONE(0) 至 IMPORTANCE_HIGH(4),对用户的提醒等级从小到大。关于创建通知渠道组,向渠道组发送通知或者修改通知渠道组设置的代码可以查看 Google 文档:通知渠道。
同时还引入了一个通知睡眠的功能,用户可以休眠一个通知,让它在指定的时候再出现,被休眠的时候仍然可以修改这个通知的设置,但是不会让这个通知立马出现。另外还可以设置一个通知的超时时间,用来让某个通知在一段时间之后被自动 cancel。其他的比如可以获取通知的清除方式,修改通知的背景颜色,修改通知的样式可以看官方文档:Android O-通知。
使用场景:针对应用的不同优先级别的通知设置不同的通知渠道,强提醒可以发出声音加震动,弱提醒可能仅仅只需要呼吸灯和角标这样等,这样可以最大程度减少对用户的干扰。
在 Android O 之前,画中画模式已经可用于 Android TV,而 Android O 则让这一个功能可以支持到其他的 Android 设备,当某个 Activity 处于 PIP 模式时,它会回调生命周期的 onPause 方法,所以此时在 PIP 模式下比如视频播放等操作就不能够在 onPause 里面暂停,而应该在 onStop 里面,这一点和多窗口模式一样,来看看它的效果:
我们可以看到在当从 youtube 视频切换出去之后会回到桌面,这时候会有一个视频播放的窗口悬浮在所有的应用之上,这个小窗口在播放视频,而此时点击这个小窗口区域会弹出几个操作按钮,可以选择关闭,或者是重新打开 youtube 视频播放页,而且底部的几个按钮也是可以自定义的,非常方便。
这里需要提到的一点是,升级到 8.0 的系统后不是立马会激活这个功能,激活这个功能可能会有点复杂:
System UI Tuner
功能,开启的方式是下拉通知栏,长摁右下角的设置按钮, System UI Tuner
已开启;Settings > System > System UI Tuner > Navigation bar
,去到 navigation bar 之后选择 extra left button type
或者 extra right button type
,选择 keycode
,选择完成之后返回到上一个页面填写 right/left keycode
为 171
,代表将当前显示页面变为 PIP 模式窗口(如果不支持页面没有任何反应),然后选择一个 right/left icon
: System UI Tuner
页面,选择 Picture-in-Picture
模式,进去之后将 Minimize 打开即可。android:supportsPictureInPicture
设置为 true,除了上面提到的用户手动将 Activity 变成 PIP 模式,还可以使用
Activity.enterPictureInPictureMode(PictureInPictureArgs args)
动态将 Activity 设置为 PIP 模式,
PictureInPictureArgs
这个对象参数是用来指定 Activity 处于 PIP 模式时的行为,此对象还指定了各种属性,例如 Activity 的首选纵横比,同时还可以使用
Activity.setPictureInPictureArgs()
更新 Activity 的 PIP 配置设置,如果 Activity 目前处于 PIP 模式,则会更新此设置。
为了帮助开发者更好的与设备 UI 集成,Android O 支持创建自适应图标,系统可以基于设备选择的蒙版将这些图标显示为不同形状。系统还将实现与图标的自动交互,并在启动器、快捷方式、设置、共享对话框以及概览屏幕中使用它们:
可以通过定义两层图层(前景和背景)来指定桌面图标外观,必须提供没有形状和阴影的 PNG 格式图象作为图层:
在以前的 Android 版本中,图标大小定义为 48 x 48 dp,但是现在必须按照以下的规范定义图层大小:
1. 两张图层大小都必须为 108 x 108 dp。
2. 图层中心 72 x 72 dp 范围为可视范围。
3. 系统会保留四周的 18dp 范围用于生成有趣的视觉效果(如视差和跳动):
创建自适应图标可以参考:Create adaptive icons with Android Studio:
这个就将以前混乱的图标统一化了,现在 Android 很多应用的图标,有的是正方形的,有的带圆弧,而且这圆弧的弧度各有差异,有的图标还是圆形,有的则是不规则的图片,统一之后所有的应用图标将具有一致的风格,比较推荐。
Android O 还引入了自动填充框架,简化了用户在账号创建、登录和信用卡表单之类的填写工作,在用户选择自动填充框架之后,新老用户都可以使用自动填充框架,我们使用 Chrome 的时候已经体验过了自动填充用户名和密码的功能,只不过这次是在系统层面提供了这样的一种功能,可以快速的填充用户名,地址甚至密码等,而且用户也不需要去担心安全问题。
同样自动填充框架也需要去设置页面打开: Settings > Apps & Notifications > Default apps > Autofill app
,关于如何适配自动填充框架:Autofill Framework:
这个场景可以参考 Chrome 的记住账号和密码功能,例如现在的 QQ 登录其实是已经做了一个类似的 Auto-Fill 功能,比较适合用在账号密码等场景上。
Android O 推出了 xml 字体,可以在资源文件中建立 font 字体资源文件夹,放入相应的字体 ttf 文件,然后建立自己的字体 xml 文件,在 R 文件中编译,最终作为一种资源供 TextView 等使用,
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
<font
android:fontStyle="normal"
android:fontWeight="400"
android:font="@font/lobster_regular" />
<font
android:fontStyle="italic"
android:fontWeight="400"
android:font="@font/lobster_italic" />
font-family>
同时 Android O 和 Android support library 26 提供了一个 API,可以从另一个应用中获取字体资源,而不是将字体资源打包到 apk 中或者让 apk 去下载,通过 Android support library 26 版本可以让这个特性支持到 14 版本或者之上的设备上,具体的 API 可以看看这个:Downloadable Fonts 或者这个 sample android-DownloadableFonts:
适用场景:这个比较适合在公司的一系列 APP 上使用,更换皮肤同时更换字体等等。
这个功能在 7.1.1 之后就已经有了,长摁桌面图标就会显示一个 App shortcuts 菜单栏,然后长摁菜单栏上的一项,就能把它拖下来成为单独的一个应用图标,被拖下来的单独的应用图标就是Pinned shortcuts,虽然这个功能在 7.1.1 引入的,但是在 O 版本我们可以通过提供的 API 按照一定的步骤去使用代码添加:Pinning Shortcuts and Widgets。
适用场景:这个可以将某些应用使用频繁的小功能独立出来,比如 QQ 的最常用联系人,音乐的听歌识曲等功能。
Android O 版本允许设置 TextView 的字体大小根据设置的初始大小自动放大或者缩小,这样就可以让字体的显示在不同的屏幕和不同的显示内容上达到最优的效果,而且使用 Android support library 26 中的 android.support.v4.widget.TextViewCompat 可以让该特性支持到 14 版本,Android O 版本的 TextView 已经可以支持 autosize 了,设置 autosize 特性也非常简单,在 O 版本上,只需要使用 setAutoSizeTextTypeWithDefaults(@AutoSizeTextType int autoSizeTextType)
或者
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoSizeTextType="uniform"
/>
就可以了,关于使用的细节:Autosizing TextViews。
适用场景:TextView 显示内容较多的时候,如果可以接受的话,适当的减小字体的大小,让显示的字数增加。
Android O 版本新增 VolumeShaper 类,用来为应用提供声音的淡入淡出等音效;新增AudioFocusRequest 类用来提供检测音频焦点的新功能;新增了以下的方法 getMetrics 方法用来返回一个包含配置和性能信息的 Bundle 对象:
Android O 允许应用查询和获取设备如何发出声音,应用可以通过 requestAudioFocus()
函数来为设备范围的音频焦点提交一个细粒度的请求,比如传入一个 AudioFocusRequest
对象,设置对应的 type,就可以指定获取焦点的类型,同时可以设置当音频焦点被强占时候应用的行为,轻声继续播放还是彻底暂停。
值得一提的是,在 Android O 上引入了 sony “捐赠”的 LDAC 无线声音加密格式,用来进行高质量音乐的蓝牙通信,这样就可以通过蓝牙耳机播放真正的无损音乐了:
可以看到使用了 LDAC 无线声音加密协议之后,最高可以达到 990kbps 的传输速率,好消息是不是!但是可惜的是 LDAC 只能再 sony 制造的耳机上使用,比如 £330 MDR-1000X,高呼Sony大法好~~
1. 可以设置 Activity 支持广色域;
2. 可以设置最大的屏幕宽高比;
3. 多屏幕支持,支持设备外接一个显示器;
4. 最新版本 emoji 支持,使用 EmojiCompat
类可以让应用在老版本的应用上显示新的 emoji;
5. 支持点击位置的捕捉;
6. 支持设置应用类别,这些类别用于将应用呈现给用户的用途或功能相同的应用归类在一起,例如按流量消耗、电池消耗和存储消耗将应用归类。
7. Smart Text Selection,这个功能有人可能在今年老罗的锤子手机发布会上看到过,思想是很类似的,复制一段数字,就会出现直接拨打电话的选项,复制一段地址就会弹出进入地图的选项,地图 APP 可以一下这个地方能否成为一个很方便入口。
这个列举了当前可能会影响应用的几个行为变更。
Android O 在当进程进入已缓存状态时,如果没有活动的组件,系统将解除应用具有的所有唤醒锁(已缓存状态指的是没有前台 Activity 或者正在执行的前台 Service)。同时 Android O 上运行在后台的应用将会有限制的使用后台的 Service,并且应用也不能在 Manifest 中注册一些不必要的隐式广播用来进行自启等操作:
Android O 包含以下与安全性有关的变更:
Android O 对网络连接和 HTTP(S) 连接行为做出了不少变更,其中包括无正文的 OPTIONS 请求现在有 Content-Length: 0 标头;HttpURLConnection 在包含斜线的主机或颁发机构名称后面附加一条斜线,将 http://example.com 转化为 http://example.com/ ;通过 ProxySelector.setDefault() 设置的自定义代理选择器的范围变化;URI 不能包含空白标签;如果之前执行的 connect() 方法失败,send(java.net.DatagramPacket) 方法将会引发 SocketException;在回退到 TCP Echo 协议之前,InetAddress.isReachable() 会尝试执行 ICMP;隧道 HTTP(S) 连接处理进行了一些变更。
变更内容比较繁多:网络连接和 HTTP(S) 连接。
在 Android O 之前,如果应用在运行时请求权限并且被授予该权限,系统会错误地将属于同一权限组并且在清单中注册的其他权限也一起授予应用。对于针对 Android O 的应用,此行为已被纠正。系统只会授予应用明确请求的权限。然而,一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准。
在针对 Android O 的应用中,如果 Native libraries 包含任何可写且可执行的代码段,则不会再加载 Native libraries,可写和可执行必须是在新版本必须是互斥的,倘若某些应用的 Native libraries 包含不正确的加载代码段,则此变更可能会导致这些应用停止工作,官方文档:Writable and Executable Segments。
1. ContentProvider 支持分页,即获取内容的选中区域的子集;
2. ContentProvider 和 ContentResolver 增加 refresh 方法,用来让客户端更容易的知道数据是不是最新;
3. JobScheduler 更新,让应用更容易遵从后台执行限制;
4. 集合的处理的变化,AbstractCollection.removeAll() 和 AbstractCollection.retainAll() 始终引发 NullPointerException;
5. 语言区域和国际化变化;
6. 联系人提供程序使用情况统计方法的变更;
7. 蓝牙 ScanRecord.getBytes() 方法检索的数据长度变更;
8. 输入和导航;
Android O 预览版本提供了几个新的 API 用来管理 WebView:
PackageInfo webViewPackageInfo = WebView.getCurrentWebViewPackage();
Log.d("MY_APP_TAG", "WebView version: " + webViewPackageInfo.versionName);
"android.webkit.WebView.EnableSafeBrowsing"
android:value="true" />
...
...
Termination Handle API
一起搭配使用;
findViewById 函数现在返回的是
Android 引入了几个新的 xml 属性:
Android O 中,AnimationSet API 现在支持了动画的 seek 和动画倒转播放,seek 操作可以设置 AnimationSet 从指定的点开始播放,倒转播放则将以前需要重复定义两个相反的动画操作简化成只需要定义一个动画即可。
在 Android O 版本之前,应用如果不用 type_toast 显示悬浮窗,一般正常情况下都会使用声明 SYSTEM_ALERT_WINDOW 权限 + 使用 TYPE_SYSTEM_ERROR 的形式来显示悬浮窗,国内的第三方 ROM 也会对此有限制,Android 6.0 版本曾经对悬浮窗有过一次限制,必须要用户手动开启“在其他应用之上显示”的权限才能展示悬浮窗,在 Android O 之后 SYSTEM_ALERT_WINDOW 权限的应用无法再使用以下窗口类型来在其他应用和系统窗口上方显示提醒窗口: