[Android各版本特性]Android 8.0 Oreo

好久不见. 提交于 2019-12-10 23:05:18

Android8.0版本调整了很多东西,特别要注意的是:

  1. 后台service限制。
  2. 无法继续在清单中为隐式广播注册广播接收器。
  3. 后台位置信息限制。
  4. 通知增加渠道ID
  5. 音频焦点AudioFocusRequest变更。

1.通知

  1. 通知渠道:Android 8.0 引入了通知渠道,其允许您为要显示的每种通知类型创建用户可自定义的渠道。用户界面将通知渠道称之为通知类别。
  2. 通知标志:Android 8.0 引入了对在应用启动器图标上显示通知标志的支持。通知标志可反映某个应用是否存在与其关联、并且用户尚未予以清除也未对其采取行动的通知。通知标志也称为通知点。
  3. 休眠:用户可以将通知置于休眠状态,以便稍后重新显示它。重新显示时通知的重要程度与首次显示时相同。应用可以移除或更新已休眠的通知,但更新休眠的通知并不会使其重新显示。
  4. 通知超时:现在,使用 setTimeoutAfter() 创建通知时您可以设置超时。您可以使用此函数指定一个持续时间,超过该持续时间后,通知应取消。如果需要,您可以在指定的超时持续时间之前取消通知。
  5. 通知设置:当您使用 Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES Intent 从通知创建指向应用通知设置的链接时,您可以调用 setSettingsText() 来设置要显示的文本。此系统可以提供以下 Extra 数据和 Intent,用于过滤应用必须向用户显示的设置:EXTRA_CHANNEL_ID、NOTIFICATION_TAG 和 NOTIFICATION_ID。
  6. 通知清除:系统现在可区分通知是由用户清除,还是由应用移除。要查看清除通知的方式,您应实现 NotificationListenerService 类的新 onNotificationRemoved() 函数。
  7. 背景颜色:您现在可以设置和启用通知的背景颜色。只能在用户必须一眼就能看到的持续任务的通知中使用此功能。例如,您可以为与驾车路线或正在进行的通话有关的通知设置背景颜色。您还可以使用 Notification.Builder.setColor() 设置所需的背景颜色。这样做将允许您使用 Notification.Builder.setColorized() 启用通知的背景颜色设置。
  8. 消息样式:现在,使用 MessagingStyle 类的通知可在其折叠形式中显示更多内容。对于与消息有关的通知,您应使用 MessagingStyle 类。您还可以使用新的 addHistoricMessage() 函数,通过向与消息相关的通知添加历史消息为会话提供上下文。

2.画中画模式

Android 8.0 允许以画中画 (PIP) 模式启动操作组件。PIP 是一种特殊的多窗口模式,最常用于视频播放。当某个 Activity 处于 PIP 模式时,它会处于暂停状态,但仍应继续显示内容。因此,您应确保您的应用在 onPause() 处理程序中进行处理时不会暂停播放。相反,您应在 onStop() 中暂停播放视频,并在 onStart() 中继续播放。

3.可下载字体

Android 8.0 和 Android 支持库 26 允许您从提供程序应用请求字体,而无需将字体绑定到 APK 中或让 APK 下载字体。此功能可减小 APK 大小,提高应用安装成功率,使多个应用可以共享同一种字体。

4.XML 中的字体

Android 8.0 推出一项新功能,即 XML 中的字体,允许您使用字体作为资源。这意味着,不再需要以资产的形式捆绑字体。字体在 R 文件中编译,并且作为一种资源,可自动用于系统。然后,您可以利用一种新的资源类型 font 来访问这些字体。

在运行 API 版本 14 及更高版本的设备中,支持库 26 对此功能提供完全支持。

5.自动调整 TextView 的大小

Android 8.0 允许您根据 TextView 的大小自动设置文本展开或收缩的大小。这意味着,在不同屏幕上优化文本大小或者优化包含动态内容的文本大小比以往简单多了。

6.自适应图标

Android 8.0 引入自适应启动器图标。自适应图标支持视觉效果,可在不同设备型号上显示为各种不同的形状。

7.颜色管理

图像应用的 Android 开发者现在可以利用支持广色域彩色显示的新设备。要显示广色域图像,应用需要在其清单(每个操作组件)中启用一个标志,并加载具有嵌入的广域彩色配置文件(AdobeRGB、Pro Photo RGB、DCI-P3 等)的位图。

8.多显示器支持

从 Android 8.0 开始,此平台为多显示器提供增强的支持。如果 Activity 支持多窗口模式,并且在具有多显示器的设备上运行,则用户可以将 Activity 从一个显示器移动到另一个显示器。当应用启动 Activity 时,此应用可指定 Activity 应在哪个显示器上运行。

9.统一的布局外边距和内边距

Android 8.0 让您可以更轻松地指定 View 元素的对边使用相同外边距和内边距的情形。具体来说,您现在可以在布局 XML 文件中使用以下属性:

  • layout_marginVertical,同时定义 layout_marginTop 和 layout_marginBottom。
  • layout_marginHorizontal,同时定义 layout_marginLeft 和 layout_marginRight。
  • paddingVertical,同时定义 paddingTop 和 paddingBottom。
  • paddingHorizontal,同时定义 paddingLeft 和 paddingRight。

注意:请记住,这些属性不会影响 layout_marginStart、layout_marginEnd、paddingStart 或 paddingEnd 的值。您可以自行设置这些值和新的垂直与水平布局属性来创建取决于文本方向的布局行为。

10.AnimatorSet

从 Android 8.0 开始,AnimatorSet API 现在支持寻道倒播功能。寻道功能允许您将动画的位置设置为指定的时间点处。如果您的应用包含可撤消的操作的动画,倒播功能会很有用。现在,您不必定义两组独立的动画,而只需反向播放同一组动画。

11.缓存数据

Android 8.0 优化了缓存数据的导航和行为。现在,每个应用均获得一定的磁盘空间配额,用于存储 getCacheQuotaBytes(UUID) 返回的缓存数据。

当系统需要释放磁盘空间时,将开始从超过配额最多的应用中删除缓存文件。因此,如果将您的缓存数据量始终保持低于配额的水平,则在必须清除系统中的某些文件时,您的缓存文件将能坚持到最后。系统在决定删除您的应用中的哪些缓存文件时,将首先考虑删除最旧的文件(由修改时间确定)。

您还可以针对每个目录启用两种新行为,以控制系统如何释放缓存数据:

  • StorageManager.setCacheBehaviorAtomic() 可用于指示某个目录及其所有内容应作为一个不可分割的整体进行删除。
  • setCacheBehaviorTombstone(File, boolean) 可用于指示不应删除某个目录内的文件,而应将它们截断到 0 字节长度,使空文件保持完好。

最后,在需要为大文件分配磁盘空间时,可考虑使用新的 allocateBytes(FileDescriptor, long) API,它将自动清除属于其他应用的缓存文件(根据需要),以满足您的请求。在确定设备是否有足够的磁盘空间保存您的新数据时,请调用 getAllocatableBytes(UUID) 而不要使用 getUsableSpace(),因为前者会考虑系统要为您清除的任何缓存数据。

12.内容刷新请求

现在,ContentProvider 和 ContentResolver 类均包含 refresh() 函数,这样,客户端可以更轻松地知道所请求的信息是否为最新信息。

您可以扩展 ContentProvider 以添加自定义的内容刷新逻辑。请务必重写 refresh() 函数,以返回 true,告知提供程序的客户端您已尝试自行刷新数据。

您的客户端应用可通过调用另一个函数(又称 refresh()),显式请求已刷新的内容。在调用此函数时,传入待刷新数据的 URI。

:由于您可能通过网络不断请求数据,您应仅在有明显迹象表明内容确已过时时才从客户端调用 refresh()。执行此类内容刷新最常见的原因是响应滑动刷新手势,该手势显式请求当前界面显示最新内容。

13.JobScheduler 改进

Android 8.0 引入了对 JobScheduler 的多项改进。由于您通常可以使用计划作业替代现在受限的后台服务或隐式广播接收器,这些改进可以让您的应用更轻松地符合新的后台执行限制。

JobScheduler 的更新包括:

  • 您现在可以将工作队列与计划作业关联。要将一个工作项添加到作业的队列中,请调用 JobScheduler.enqueue()。当作业运行时,它可以将待定工作从队列中剥离并进行处理。这种功能可以处理之前需要启动后台服务(尤其是实现 IntentService 的服务)的许多用例。

  • 您现在可以通过调用 JobInfo.Builder.setClipData() 的方式将 ClipData 与作业关联。利用此选项,您可以将 URI 权限授予与作业关联,类似于这些权限传递到 Context.startService() 的方式。您也可以将 URI 权限授予用于工作队列上的 intent。

  • 计划作业现在支持多个新的约束条件:

    1. JobInfo.isRequireStorageNotLow() 如果设备的可用存储空间非常低,作业将不会运行。
    2. JobInfo.isRequireBatteryNotLow() 如果电池电量等于或低于临界阈值,作业将不会运行;临界阈值是指设备显示 Low battery warning 系统对话框的电量。
    3. NETWORK_TYPE_METERED 作业需要一个按流量计费的网络连接,比如大多数移动数据网络数据套餐。

14.显式请求音频焦点

您的服务可以使用 requestAudioFocus() 函数提交一个更精细的设备级音频焦点接收请求。传入一个 AudioFocusRequest 对象,您可以使用 AudioFocusRequest.Builder 创建这个对象。在这个构建类中,您可以指定以下选项:

  • 您希望获得的焦点类型,例如 AUDIOFOCUS_GAIN_TRANSIENT 或 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK。
  • 当另一个音频服务获得设备焦点时,您的服务应以更安静的方式继续,还是完全暂停。
  • 您的服务能否等待获得焦点,直至设备就绪。

:构建您的 AudioFocusRequest 实例时,如果您通过调用 setAcceptsDelayedFocusGain() 指示您的服务可以等待产生声音,您也必须调用 setOnAudioFocusChangeListener(),以便您的服务了解它何时可以开始产生声音。

15.蓝牙

Android 8.0 通过增加以下功能,增强了平台对蓝牙的支持:

  • 支持 AVRCP 1.4 标准,该标准支持音乐库浏览。
  • 支持蓝牙低功耗 (BLE) 5.0 标准。
  • 将 Sony LDAC 编解码器集成到蓝牙堆叠中。

16.权限

Android 8.0 引入了多个与电话有关的新权限:

  • ANSWER_PHONE_CALLS 允许您的应用通过编程方式接听呼入电话。要在您的应用中处理呼入电话,您可以使用 acceptRingingCall() 函数。
  • READ_PHONE_NUMBERS 权限允许您的应用读取设备中存储的电话号码。

这些权限均被划分为危险类别,属于 PHONE 权限组。

在 Android 8.0 之前,如果应用在运行时请求权限并且被授予该权限,系统会错误地将属于同一权限组并且在清单中注册的其他权限也一起授予应用。

对于针对 Android 8.0 的应用,此行为已被纠正。系统只会授予应用明确请求的权限。然而,一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准。

*17.后台执行限制

Android 8.0 为提高电池续航时间而引入的变更之一是,当您的应用进入已缓存状态时,如果没有活动的组件,系统将解除应用具有的所有唤醒锁。

此外,为提高设备性能,系统会限制未在前台运行的应用的某些行为。具体而言:

  • 现在,在后台运行的应用对后台服务的访问受到限制。
  • 应用无法使用其清单注册大部分隐式广播(即,并非专门针对此应用的广播)。

默认情况下,这些限制仅适用于针对 O 的应用。不过,用户可以从 Settings 屏幕为任意应用启用这些限制,即使应用并不是以 O 为目标平台。

Android 8.0 还对特定函数做出了以下变更:

  • 如果针对 Android 8.0 的应用尝试在不允许其创建后台服务的情况下使用 startService() 函数,则该函数将引发一个 IllegalStateException。
  • 新的 Context.startForegroundService() 函数将启动一个前台服务。现在,即使应用在后台运行,系统也允许其调用 Context.startForegroundService()。不过,应用必须在创建服务后的五秒内调用该服务的 startForeground() 函数。

18.Android 后台位置限制

为节约电池电量、保持良好的用户体验和确保系统健康运行,在运行 Android 8.0 的设备上使用后台应用时,降低了后台应用接收位置更新的频率。此行为变更会影响包括 Google Play 服务在内的所有接收位置更新的应用。

19.网络连接和 HTTP(S) 连接

Android 8.0 对网络连接和 HTTP(S) 连接行为做出了以下变更:

  • 无正文的 OPTIONS 请求具有 Content-Length: 0 标头。之前,这些请求没有 Content-Length 标头。

  • HttpURLConnection 在包含斜线的主机或颁发机构名称后面附加一条斜线,使包含空路径的网址规范化。例如,它将 http://example.com 转化为 http://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 协议,现在也许能够访问它们。
    • 对于确实无法访问的主机,此项变更意味着调用需要两倍的时间才能返回结果。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!