Android 8.0 功能和 API

Android 8.0(API 级别 26)为用户和开发者引入了各种新功能。本文档重点介绍了面向开发者的新变化。

此外,请务必查看 Android 8.0 行为变更,了解平台变更可能会在哪些方面影响您的应用。

用户体验

画中画模式

Android 8.0 中的画中画。

Android 8.0(API 级别 26)允许以画中画 (PIP) 模式启动 activity。画中画是一种特殊的多窗口模式,主要用于视频播放。画中画模式最初仅适用于 Android TV;Android 8.0 使该功能可用于其他 Android 设备。

当某个 activity 处于画中画模式时,它会处于暂停状态,但应继续显示内容。因此,您应确保您的应用不会在其 onPause() 处理程序中暂停播放。您应改为在 onStop() 中暂停视频,在 onStart() 中继续播放。如需了解详情,请参阅多窗口生命周期

如需指定您的 activity 可以使用画中画模式,请在清单中将 android:supportsPictureInPicture 设置为 true。(从 Android 8.0 开始,画中画不需要 android:resizeableActivity 清单属性。不过,如果 activity 支持其他多窗口模式,则必须将 android:resizeableActivity 设为“true”。)

Android 8.0(API 级别 26)引入了一个新的对象 PictureInPictureParams,您可以将该对象传递给画中画方法,以指定 activity 在画中画模式下的行为。此对象可指定 activity 的首选宽高比等属性。

添加画中画中所述的现有画中画方法现在可以在所有 Android 设备上使用,而不仅限于 Android TV。此外,Android 8.0 还提供了以下方法来支持画中画模式:

  • Activity.enterPictureInPictureMode(PictureInPictureParams args):将 activity 置于画中画模式。activity 的宽高比和其他配置设置由 args 指定。如果 args 中的任何字段为空,系统会使用您上次调用 Activity.setPictureInPictureParams() 时设置的值。

    指定的 activity 位于屏幕的一角,屏幕的其余部分填充屏幕上出现的上一个 activity。 进入画中画模式的 activity 将进入暂停状态,但仍处于启动状态。如果用户点按画中画 activity,系统会显示一个菜单供用户互动;当该 activity 处于画中画状态时,系统不会向其发送任何触摸事件。

  • Activity.setPictureInPictureParams():更新 activity 的画中画配置设置。如果 Activity 当前处于画中画模式,则会更新设置;如果 Activity 的宽高比发生变化,这非常有用。如果 activity 未处于画中画模式,那么无论您调用什么 enterPictureInPictureMode() 方法,系统都会使用这些配置设置。

通知

在 Android 8.0(API 级别 26)中,我们重新设计了通知,以提供更轻松、更统一的方式来管理通知行为和设置。这些更改包括:

    Android 8.0(API 级别 26)中的通知长按菜单。

    在 Android 8.0 中,用户可以长按应用启动器图标来查看通知。

  • 通知渠道:Android 8.0 引入了通知渠道,可让您为要显示的每种通知类型创建一个用户可自定义的渠道。界面将通知渠道称为通知类别。如需了解如何实现通知渠道,请参阅管理通知渠道
  • 通知圆点:Android 8.0 引入了对在应用启动器图标上显示圆点或标记的支持。通知圆点反映了是否存在用户尚未关闭或操作的通知。 如需了解如何使用通知圆点,请参阅通知标记
  • 延后:用户可以暂停通知,这会导致通知在重新显示之前消失一段时间。通知重新显示时,其重要性与首次显示时相同。应用可以移除或更新已延后的通知,但更新已延后的通知不会导致它重新显示。
  • 通知超时:您可以在使用 setTimeoutAfter() 创建通知时设置超时。 您可以使用此方法指定时长,超过该时长后,应取消通知。如果需要,您可以在指定的超时持续时间过去之前取消通知。
  • 通知设置:您可以调用 setSettingsText() 来设置在您使用 Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES intent 从通知创建指向应用通知设置的链接时所显示的文字。 系统可能会提供以下 extra 以及 intent,以过滤应用必须向用户显示的设置:EXTRA_CHANNEL_IDNOTIFICATION_TAGNOTIFICATION_ID
  • 通知关闭:用户可以自行关闭通知,而应用也可以以编程方式移除通知。您可以实现 NotificationListenerService 类中的 onNotificationRemoved() 方法,以确定通知何时关闭以及为什么关闭它。
  • 背景颜色:您可以为通知设置和启用背景颜色。您应仅在用户一目了然地查看持续性任务的通知中使用此功能。例如,您可以为与行车路线或正在进行的通话相关的通知设置背景颜色。您还可以使用 setColor() 设置所需的背景颜色。这样,您就可以使用 setColorized() 为通知启用背景颜色。
  • 消息样式:在 Android 8.0 中,使用 MessagingStyle 类的通知会在折叠形式中显示更多内容。对于与消息相关的通知,您应该使用 MessagingStyle 类。您还可以使用 addHistoricMessage() 方法,通过向与消息相关的通知添加历史消息为对话提供上下文。

自动填充框架

帐号创建、登录和信用卡交易需要一定的时间,并且容易出错。对于需要执行这些重复性任务的应用,用户很容易感到沮丧。

Android 8.0(API 级别 26)引入了自动填充框架,可让您更轻松地填写表单(例如登录表单和信用卡表单)。用户选择启用自动填充功能后,新老应用都可使用自动填充框架。

您可以采取一些措施,优化应用与该框架的协作方式。如需了解详情,请参阅自动填充框架概览

可下载字体

Android 8.0(API 级别 26)和 Android 支持库 26 允许您从提供程序应用请求字体,而不是将字体捆绑到 APK 中或让 APK 下载字体。此功能可缩减 APK 大小,提高应用安装成功率,并允许多个应用共享同一种字体。

如需详细了解如何下载字体,请参阅可下载的字体

XML 中的字体

Android 8.0(API 级别 26)引入了“XML 中的字体”这项新功能,可让您使用字体作为资源。这意味着,不需要将字体捆绑为资源。字体在 R 文件中编译,在系统中可自动作为资源使用。然后,您可以借助新的资源类型 font 访问这些字体。

支持库 26 在搭载 API 版本 14 及更高版本的设备上为此功能提供全面支持。

如需详细了解如何将字体用作资源以及如何检索系统字体,请参阅 XML 中的字体

自动调整 TextView 的大小

Android 8.0(API 级别 26)允许您根据 TextView 的大小自动设置文本展开或收缩的大小。这意味着,可以更轻松地优化不同屏幕上的文本大小或包含动态内容的文本大小。如需详细了解如何在 Android 8.0 中自动调整 TextView 的大小,请参阅自动调整 TextView 的大小

自适应图标

Android 8.0(API 级别 26)引入了自适应启动器图标。自适应图标支持视觉效果,可以在不同设备型号上显示各种形状。如需了解如何创建自适应图标,请参阅自适应图标指南。

颜色管理

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

WebView API

Android 8.0 提供了多个 API 来帮助您管理在应用中显示 Web 内容的 WebView 对象。这些 API 能够提高应用的稳定性和安全性,其中包括:

  • Version API
  • Google SafeBrowsing API
  • Termination Handle API
  • Renderer Importance API

如需详细了解如何使用这些 API,请参阅管理 WebView

WebView 类现在包含 Safe Browsing API,可增强网络浏览的安全性。如需了解详情,请参阅 Google Safe Browsing API

固定快捷方式和微件

Android 8.0(API 级别 26)引入了应用内固定快捷方式和 widget。在您的应用中,您可以根据用户权限为受支持的启动器创建固定的快捷方式和微件。

如需了解详情,请参阅固定快捷方式和微件功能指南。

最大屏幕纵横比

Android 8.0(API 级别 26)更改了配置应用最大宽高比的方式。

首先,Android 8.0 引入了 maxAspectRatio 属性,您可以使用该属性设置应用的最大宽高比。此外,在 Android 8.0 及更高版本中,应用的默认最大宽高比是运行应用的设备的原生宽高比。

如需详细了解如何声明最大宽高比,请参阅支持多种屏幕

多显示屏支持

从 Android 8.0(API 级别 26)开始,Android 平台为多屏幕提供增强支持。如果某个 activity 支持多窗口模式,并且正在具有多个显示屏的设备上运行,则用户可以将 activity 从一个显示屏移到另一个显示屏。当应用启动 activity 时,应用可以指定 activity 应在哪个显示屏上运行。

注意 :如果 activity 支持多窗口模式,则 Android 8.0 会自动为该 activity 启用多显示屏支持。您应对应用进行测试,确保它在多显示屏环境中能够正常运行。

一次只有一个 activity 可以处于已恢复状态,即使该应用有多个显示屏也是如此。具有焦点的 activity 处于继续状态;所有其他可见的 activity 都会暂停,但不会停止。如需详细了解多个 activity 可见时的 activity 生命周期,请参阅多窗口生命周期

当用户将 activity 从一个显示屏移到另一个显示屏时,系统会调整 activity 的大小,并根据需要发出运行时更改。您的 activity 可以自行处理配置变更,也可以允许系统销毁包含 activity 的进程,并以新的尺寸重新创建该 activity。如需了解详情,请参阅处理配置变更

ActivityOptions 提供了两种新方法来支持多个显示屏:

setLaunchDisplayId()
指定 activity 在启动时应该在哪个显示屏上显示。
getLaunchDisplayId()
返回 activity 的当前启动显示画面。

扩展了 adb shell 以支持多个显示屏。shell start 命令现在可用于启动 activity,并指定 activity 的目标显示屏:

adb shell start <activity_name> --display <display_id>

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

Android 8.0(API 级别 26)可让您更轻松地指定 View 元素的对边使用相同外边距或内边距的情况。具体而言,您现在可以在布局 XML 文件中使用以下属性:

注意:如果您自定义应用的逻辑以支持不同的语言和文化(包括文本方向),请注意,这些属性不会影响 layout_marginStart layout_marginEnd paddingStart paddingEnd 的值。除了新的垂直和水平布局属性外,您还可以自行设置这些值,以创建依赖于文本方向的布局行为。

指针捕获

某些应用(例如游戏、远程桌面和虚拟化客户端)可极大地受益于控制鼠标指针。指针捕获是 Android 8.0(API 级别 26)中的一项新功能,可通过将所有鼠标事件传递到应用中的聚焦视图来提供此类控制。

从 Android 8.0 开始,应用中的 View 可以请求指针捕获并定义监听器来处理捕获的指针事件。在此模式下,鼠标指针处于隐藏状态。当不再需要鼠标信息时,视图可以释放指针捕获。系统还可以在视图失去焦点时(例如,当用户打开另一个应用时)释放指针捕获。

如需了解如何在应用中使用此功能,请参阅指针捕获

应用类别

Android 8.0(API 级别 26)允许每个应用在必要时声明其所属的类别。在向用户呈现具有相似用途或功能的应用(例如,在流量消耗、电池用量或存储空间用量等方面)时,您可以使用这些类别将此类应用归为一组。您可以通过在 <application> 清单标记中设置 android:appCategory 属性来为应用定义类别。

Android TV 启动器

Android 8.0(API 级别 26)提供了以内容为中心的全新 Android TV 主屏幕体验,适用于 Android 8.0 的 Android TV 模拟器和 Nexus Player 设备映像。在新的主屏幕中,视频内容按行整理,频道对应行,其中每个频道都由系统上的应用填充节目。应用可以发布多个频道,用户可以配置希望在主屏幕上看到哪些频道。Android TV 主屏幕上还包含“接下来观看”行,该行会根据用户的观看习惯填充应用中的节目。应用还可以提供视频预览,当用户聚焦于某个节目时,系统会自动播放这些预览。用于填充频道和节目的 API 是 TvProvider API 的一部分,这些 API 作为 Android 8.0 中的 Android 支持库模块分发。

AnimatorSet

从 Android 8.0(API 级别 26)开始,AnimatorSet API 现在支持寻道和反向播放。借助跳转功能,您可以将动画的位置设置为特定时间点。如果您的应用包含可撤消操作的动画,反向播放非常有用。您可以将同一个动画集倒放,而无需定义两个单独的动画集。

输入和导航

键盘导航键区

如果应用中的 activity 使用复杂的视图层次结构(如图 2 所示),不妨考虑将界面元素组整理成聚类,以便在这些元素之间更轻松地进行键盘导航。用户可以在 Chromebook 设备上按 Meta+Tab 或 Search+Tab,从一个集群导航到另一个集群。聚类的典型示例包括:侧边栏、导航栏、主要内容区域以及可包含多个子元素的元素。

一个 Activity 示例,包含五个导航键区,用户可以使用键盘导航键区快捷键进行导航。这些仪表板按以下排列方式显示:顶部面板、左侧面板、主内容区域、底部面板和悬浮操作按钮。
图 2. 包含 5 个导航集群的 activity

如需将 ViewViewGroup 元素设为聚类,请在该元素的布局 XML 文件中将 android:keyboardNavigationCluster 属性设置为 true,或将 true 传递到应用界面逻辑中的 setKeyboardNavigationCluster()

注意:虽然非嵌套集群可能出现在层次结构的不同级别,但集群不能嵌套。如果您尝试嵌套集群,框架只会将最顶层的 ViewGroup 元素视为集群。

在具有触摸屏的设备上,您可以将仪表板指定的 ViewGroup 对象的 android:touchscreenBlocksFocus 元素设置为 true,以允许仅从仪表板导航进出该仪表板。如果您将此配置应用于仪表板,用户将无法使用 Tab 键或箭头键进入或退出仪表板;他们必须改为按仪表板导航键盘组合。

视图默认焦点

在 Android 8.0(API 级别 26)中,您可以分配应在(重新)创建的 activity 恢复且用户按键盘导航键(如 Tab 键)后接收焦点的 View。如需应用此“默认获得焦点”设置,请在包含界面元素的布局 XML 文件中将 View 元素的 android:focusedByDefault 属性设置为 true,或在应用的界面逻辑中将 true 传入 setFocusedByDefault()

语音输出

activity 和服务可以使用 TextToSpeech 的实例对内容进行口述和发音。从 Android 8.0(API 级别 26)开始,只要引擎提供此信息,您的应用就可以获取有关文字转语音引擎何时开始朗读单个合成字词的更精确的时间信息。您可以使用此功能在文字转语音引擎读出特定字词时引起人们的注意。

如需在您的应用中使用这些文字转语音引擎改进,请注册 UtteranceProgressListener 实例。在注册过程中,为 onRangeStart() 方法添加处理程序。

文字转语音引擎会调用 rangeStart() 来记录预期开始播放特定范围文本的音频的时间点。当该文本范围的音频开始播放时,系统会执行应用的 onRangeStart() 方法。然后,您的应用可以响应此回调,例如通过突出显示与语音内容关联的文本范围来响应此回调。

如需详细了解如何跟踪文字转语音引擎的播放进度,请参阅 UtteranceProgressListener 类参考文档。

系统

新的 StrictMode 检测程序

Android 8.0(API 级别 26)添加了三个新的 StrictMode 检测器来帮助识别应用中的潜在 bug:

缓存的数据

Android 8.0(API 级别 26)为缓存数据提供了更好的指导和行为。现在,每个应用都会获得由 getCacheQuotaBytes(UUID) 返回的磁盘空间配额,以用于缓存数据。

当系统需要释放磁盘空间时,首先会从超出分配配额最多的应用中删除缓存文件。因此,如果您将缓存数据控制在分配的配额以下,缓存文件将是系统上需要时最后清除的文件。当系统决定在应用中删除哪些缓存文件时,会首先考虑最旧的文件(由修改时间确定)。

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

  • StorageManager.setCacheBehaviorAtomic() 可用于指示某个目录及其所有内容应作为一个原子单元删除。
  • setCacheBehaviorTombstone(File, boolean) 可用于指示不应删除某个目录中的文件,而应将其截断为 0 字节,使空文件保持完好。

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

内容提供程序分页

我们更新了内容提供程序,以支持一次加载一页大型数据集。例如,包含数千张图片的照片应用可以查询要在网页中显示的部分数据。content provider 返回的每一页结果都由一个 Cursor 对象表示。客户端和提供程序都必须实现分页才能使用此功能。

如需详细了解 content provider 的变化,请参阅 ContentProviderContentProviderClient

内容刷新请求

ContentProviderContentResolver 类现在都包含一个 refresh() 方法,从而使客户端可以更轻松地了解其请求的信息是否为最新信息。

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

您的客户端应用可以通过调用另一个方法(也称为 refresh())来明确请求已刷新的内容。调用此方法时,传入要刷新的数据的 URI。

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

JobScheduler 改进

Android 8.0(API 级别 26)引入了对 JobScheduler 的多项改进。这些改进可让您的应用更轻松地符合新的后台执行限制,因为通常您可以使用预定作业替换现在受限的后台服务或隐式广播接收器。

JobScheduler 的更新包括:

  • 您现在可以将工作队列与预定作业相关联。如需将工作项添加到作业的队列,请调用 JobScheduler.enqueue()。当作业运行时,它可以将待处理工作从队列中移出并进行处理。此功能可处理以前需要启动后台服务(尤其是实现 IntentService 的服务)的许多用例。
  • Android 支持库 26.0.0 引入了一个新的 JobIntentService 类,该类提供与 IntentService 相同的功能,但在 Android 8.0(API 级别 26)或更高版本上运行时会使用作业(而不是服务)。
  • 您现在可以调用 JobInfo.Builder.setClipData()ClipData 与作业相关联。通过此选项,您可以将 URI 权限授予与作业相关联,类似于这些权限传播到 Context.startService() 的方式。您还可以将 URI 权限授予用于工作队列上的 intent。
  • 预定作业现在支持多个新限制条件:
    JobInfo.isRequireStorageNotLow()
    如果设备的可用存储空间不足,作业将不会运行。
    JobInfo.isRequireBatteryNotLow()
    如果电池电量等于或低于临界阈值,作业不会运行;临界阈值是指设备显示“低电量警告”系统对话框的水平。
    NETWORK_TYPE_METERED
    与大多数移动数据网络套餐一样,作业需要按流量计费的网络连接。

自定义数据存储

Android 8.0(API 级别 26)允许您为您的偏好设置提供自定义数据存储,如果您的应用将偏好设置存储在云端或本地数据库中,或者偏好设置特定于设备,那么该设置非常有用。如需详细了解如何实现数据存储区,请参阅自定义数据存储区

媒体增强功能

VolumeShaper

有一个新的 VolumeShaper 类。它可用于执行简短的自动音量转换,如淡入、淡出和淡入淡出。如需了解详情,请参阅使用 VolumeShaper 控制振幅

音频焦点增强功能

音频应用通过请求和放弃音频焦点在设备上共享音频输出。 应用通过开始、停止播放或降低音量等操作来处理焦点变更。有一个新的 AudioFocusRequest 类。通过将此类用作 requestAudioFocus() 的参数,应用在处理音频焦点变化时可以使用新的功能:自动降低音量延迟焦点增益

媒体指标

新的 getMetrics() 方法会返回一个包含配置和性能信息的 PersistableBundle 对象,表示为属性和值的对应关系。可以为以下媒体类定义 getMetrics() 方法:

系统会为每个实例分别收集相关指标,并在实例的整个生命周期内保留这些指标。如果没有任何可用指标,则该方法会返回 null。返回的实际指标取决于类。

MediaPlayer

从 Android 8.0(API 级别 26)开始,MediaPlayer 可以播放受 DRM 保护的材料和 HLS 样本级加密媒体

Android 8.0 引入了一个新的过载 seekTo() 命令,可在定位到某个帧时提供精细的控制。它包含用于指定跳转模式的第二个参数:

  • SEEK_PREVIOUS_SYNC 将媒体位置移动到与数据源(紧接在给定时间之前或给定时间之前)关联的同步帧(或关键帧)。
  • SEEK_NEXT_SYNC 将媒体位置移动到与数据源(紧接在给定时间之后或给定时间)关联的同步帧(或关键帧)中。
  • SEEK_CLOSEST_SYNC 用于将媒体位置移至与位于最接近指定时间或位于指定时间的数据源相关联的同步帧(或关键帧)。
  • SEEK_CLOSEST 可将媒体位置移至与位于最接近或位于给定时间的数据源相关联的帧(不一定是同步帧或关键帧)。

在连续跳转时,应用应使用任意 SEEK_ 模式,而不应使用 SEEK_CLOSEST,后者的运行速度相对较慢,但可能更精确。

音频录制器

  • MediaRecorder 现在支持对流式传输非常有用的 MPEG2_TS 格式:

    Kotlin

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS)
    

    Java

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
    

    查看MediaRecorder.OutputFormat

  • MediaMuxer 现在可以处理任意数量的音频和视频流。您不再局限于一个音轨和/或一个视频轨道。使用 addTrack() 即可混录任意数量的曲目。
  • MediaMuxer 还可以添加一个或多个包含用户定义的每帧信息的元数据轨道。元数据的格式由您的应用定义。只有 MP4 容器支持元数据轨道。

元数据对于离线处理非常有用。例如,来自传感器的陀螺仪信号可用于执行视频防抖。

添加元数据轨道时,轨道的 MIME 格式必须以前缀“application/”开头。写入元数据与写入视频/音频数据相同,只不过数据不是来自 MediaCodec。相反,应用会将带有关联时间戳的 ByteBuffer 传递给 writeSampleData() 方法。时间戳必须与视频和音轨采用相同的时间基准。

生成的 MP4 文件使用 ISOBMFF 第 12.3.3.2 节中定义的 TextMetaDataSampleEntry 来指示元数据的 MIME 格式。使用 MediaExtractor 提取包含元数据轨道的文件时,元数据的 MIME 格式将提取到 MediaFormat 中。

增强的媒体文件访问功能

存储访问框架 (SAF) 允许应用公开自定义 DocumentsProvider,以便其他应用能够访问数据源中的文件。事实上,文档提供程序甚至可以提供对驻留在网络存储空间或使用媒体传输协议 (MTP) 等协议的文件的访问权限。

但是,访问远程数据源中的大型媒体文件会带来一些挑战:

  • 媒体播放器需要对来自文档提供程序的文件进行可寻址访问。如果大型媒体文件位于远程数据源上,文档提供程序必须提前提取所有数据并创建快照文件描述符。如果没有相应的文件描述符,媒体播放器将无法播放该文件,因此在文档提供程序下载完该文件之前,将无法开始播放。
  • 媒体集合管理器(如照片应用)必须遍历一系列访问 URI,才能通过限定了作用域的文件夹访问存储在外部 SD 卡上的媒体。这种访问模式会使媒体上的批量操作(例如移动、复制和删除)变得非常缓慢。
  • 媒体集合管理器无法根据文档的 URI 确定该文档的位置。这使得这些类型的应用难以允许用户选择媒体文件的保存位置。

Android 8.0 通过改进存储访问框架解决了每个挑战。

自定义文档提供程序

从 Android 8.0 开始,存储访问框架允许自定义文档提供程序为驻留在远程数据源中的文件创建可查找的文件描述符。SAF 可以打开一个文件,以获取原生可查找文件描述符。然后,SAF 会向文档提供程序传送离散字节请求。此功能允许文档提供程序返回媒体播放器应用已请求的确切字节范围,而不是提前缓存整个文件。

如需使用此功能,您需要调用新的 StorageManager.openProxyFileDescriptor() 方法。openProxyFileDescriptor() 方法接受 ProxyFileDescriptorCallback 对象作为回调。每当客户端应用对从文档提供程序返回的文件描述符执行文件操作时,SAF 都会调用该回调。

直接文档访问

从 Android 8.0(API 级别 26)开始,您可以使用 getDocumentUri() 方法获取与给定 mediaUri 引用相同文档的 URI。不过,由于返回的 URI 由 DocumentsProvider 提供支持,因此媒体集合管理器可以直接访问文档,而无需遍历限定作用域的目录树。因此,媒体管理器可以更快地对文档执行文件操作。

注意getDocumentUri() 方法仅定位媒体文件;它不会授予应用访问这些文件的权限。如需详细了解如何获取媒体文件的访问权限,请参阅参考文档。

文档路径

在 Android 8.0(API 级别 26)中使用存储访问框架时,您可以使用 DocumentsContractDocumentsProvider 类中提供的 findDocumentPath() 方法,根据文档 ID 确定从文件系统的根目录开始的路径。该方法会在 DocumentsContract.Path 对象中返回此路径。如果文件系统具有多个指向同一文档的已定义路径,则该方法会返回访问具有指定 ID 的文档时最常用的路径。

此功能在以下情况下特别有用:

  • 您的应用使用“另存为”对话框来显示特定文档的位置。
  • 您的应用在搜索结果视图中显示文件夹,如果用户选择特定文件夹,则必须加载该文件夹内的子文档。

注意:如果您的应用只能访问路径中的某些文档,findDocumentPath() 的返回值将仅包含应用可以访问的文件夹和文档。

监控音频播放

AudioManager 系统服务会维护一个活跃 AudioPlaybackConfiguration 对象列表,其中每个对象都包含特定音频播放会话的相关信息。您的应用可以通过调用 getActivePlaybackConfigurations() 检索当前活跃的配置集。

从 Android 8.0(API 级别 26)开始,您可以注册一个回调,以便在一个或多个 AudioPlaybackConfiguration 对象发生更改时通知您的应用。为此,请调用 registerAudioPlaybackCallback(),并传入 AudioManager.AudioPlaybackCallback 的实例。AudioManager.AudioPlaybackCallback 类包含 onPlaybackConfigChanged() 方法,系统会在音频播放配置发生更改时调用该方法。

连接性

Wi-Fi 感知

Android 8.0(API 级别 26)添加了对 Wi-Fi 感知的支持,这项支持基于近邻感知网络 (NAN) 规范。在具有相应 Wi-Fi 感知硬件的设备上,应用和附近的设备可以通过 Wi-Fi 发现和通信,而无需互联网接入点。我们正在与硬件合作伙伴合作,尽快将 Wi-Fi 感知技术应用于设备。如需了解如何将 Wi-Fi 感知集成到您的应用中,请参阅 Wi-Fi 感知

蓝牙

Android 8.0(API 级别 26)通过添加以下功能,丰富了平台对蓝牙的支持:

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

配套设备配对

Android 8.0(API 级别 26)提供的 API 允许您在尝试通过蓝牙、BLE 和 Wi-Fi 与配套设备配对时自定义配对请求对话框。如需了解详情,请参阅配套设备配对

如需详细了解如何在 Android 上使用蓝牙,请参阅蓝牙指南。如需了解特定于 Android 8.0(API 级别 26)的蓝牙变更,请参阅 Android 8.0 行为变更页面的蓝牙部分。

分享

智能共享

Android 8.0(API 级别 26)可以了解用户的个性化分享偏好设置,并可以更好地了解各种类型的内容,确定合适的分享应用。例如,如果用户拍摄收据照片,Android 8.0 可以推荐一款费用跟踪应用;如果用户自拍,社交媒体应用可以更好地处理这张图片。Android 8.0 会根据用户的个性化偏好设置自动学习所有这些模式。

智能分享功能适用于 image 以外的内容类型,例如 audiovideotextURL 等。

如需启用智能分享功能,请向分享内容的 intent 添加 ArrayList(包含最多三个字符串注解)。注释应描述内容中的主要组成部分或主题。以下代码示例展示了如何向 intent 添加注释:

Kotlin

val annotations: ArrayList<String> = arrayListOf(
        "topic1",
        "topic2",
        "topic3"
)

intent.putStringArrayListExtra(
        Intent.EXTRA_CONTENT_ANNOTATIONS,
        annotations
)

Java

ArrayList<String> annotations = new ArrayList<>();

annotations.add("topic1");
annotations.add("topic2");
annotations.add("topic3");

intent.putStringArrayListExtra(
    Intent.EXTRA_CONTENT_ANNOTATIONS,
    annotations
);

如需详细了解智能分享注释,请参阅 EXTRA_CONTENT_ANNOTATIONS

文本分类器

在兼容的设备上,应用可以使用新的文本分类器来检查字符串是否与已知的分类器实体类型匹配,并获取建议的替代选项。系统识别的实体包括地址、网址、电话号码和电子邮件地址。如需了解详情,请参阅 TextClassifier

无障碍功能

Android 8.0(API 级别 26)为自行创建无障碍服务的开发者提供了多项新的无障碍功能:

如需详细了解如何让您的应用使用起来更没有障碍,请参阅无障碍功能

安全与隐私权

权限

Android 8.0(API 级别 26)引入了若干与电话相关的新权限:

这些权限都归类为危险权限,并且属于 PHONE 权限组。

新的账号访问和 Discovery API

Android 8.0(API 级别 26)针对应用访问用户帐号的方式引入了多项改进。对于由身份验证器管理的帐号,身份验证器可以使用自己的政策来决定是否向应用隐藏帐号或显示帐号。Android 系统会跟踪可以访问特定帐号的应用。

在以前的 Android 版本中,想要跟踪用户帐号列表的应用必须获取有关所有帐号的更新,包括类型不相关的帐号。Android 8.0 添加了 addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]) 方法,可让应用指定应接收哪些帐号类型的帐号更改。

API 变更

AccountManager 提供六种新方法,以帮助身份验证器管理哪些应用可以查看帐号:

Android 8.0(API 级别 26)引入了两个特殊的软件包名称值,用于为未使用 setAccountVisibility(android.accounts.Account, java.lang.String, int) 方法设置的应用指定可见性级别。PACKAGE_NAME_KEY_LEGACY_VISIBLE 可见性值会应用于具有以下权限的应用:具有 GET_ACCOUNTS 权限,并且目标 Android 版本低于 Android 8.0,或者其签名与定位到任何 Android 版本的身份验证器相匹配。PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE 会为之前未设置且 PACKAGE_NAME_KEY_LEGACY_VISIBLE 不适用的应用提供默认的可见性值。

如需详细了解新的帐号访问 API 和 Discovery API,请参阅 AccountManagerOnAccountsUpdateListener 的参考文档。

测试

仪器测试

Android 8.0(API 级别 26)为应用的插桩测试提供了以下几项额外的支持。

针对非默认应用进程运行

现在,您可以指定应针对应用默认进程之外的进程运行特定插桩测试。如果您的应用包含多个在不同进程中运行的 activity,此配置非常有用。

如需定义非默认进程插桩,请转到您的清单文件,然后找到所需的 <instrumentation> 元素。添加 android:targetProcess 属性,并将其值设置为以下某个值:

  • 特定进程的名称。
  • 以逗号分隔的进程名称列表。
  • 通配符 ("*"),允许针对执行 android:targetPackage 属性中指定的软件包中的代码的任何已启动进程运行插桩测试。

在执行插桩测试时,您可以通过调用 getProcessName() 来检查它正在测试哪个进程。

在测试过程中报告结果

您现在可以通过调用 addResults() 在插桩测试执行期间(而不是之后)报告结果。

用于测试的模拟 Intent

为了更轻松地为应用的 activity 创建隔离的独立界面测试,Android 8.0(API 级别 26)引入了 onStartActivity() 方法。您可以在 Instrumentation.ActivityMonitor 类的自定义子类中替换此方法,以处理测试类调用的特定 intent。

当测试类调用 intent 时,该方法会返回桩 Instrumentation.ActivityResult 对象,而不是执行 intent 本身。通过在测试中使用此模拟 intent 逻辑,您可以专注于 activity 如何准备和处理传递给其他 activity 或完全不同的应用的 intent。

运行时和工具

平台优化

Android 8.0(API 级别 26)为平台带来了运行时优化和其他优化,从而大大提升了性能。这些优化包括并发压缩垃圾回收、更高效的内存使用和代码位置。

这些优化可以缩短启动时间,并提高操作系统和应用的性能。

更新了 Java 语言支持

Android 8.0(API 级别 26)添加了对其他几个 OpenJDK Java API 的支持:

如需详细了解这些新添加的软件包中的类和方法,请参阅 API 参考文档。

如果您想在 Android Studio 中 使用 Java 8 语言功能,则应下载最新的预览版

更新的 ICU4J Android Framework API

Android 8.0(API 级别 26)扩展了 ICU4J Android 框架 API(ICU4J API 的子集),供应用开发者在 android.icu 软件包下使用。这些 API 使用设备上存在的本地化数据,因此您可以通过不编译 APK 中的 ICU4J 库来减少 APK 占用的空间。

表 1. Android 中使用的 ICU、CLDR 和 Unicode 版本。

Android API 级别 ICU 版本 CLDR 版本 Unicode 版本
Android 7.0(API 级别 24),Android 7.1(API 级别 25) 56 28 8.0
Android 8.0(API 级别 26) 58.2 30.0.3 9.0

如需详细了解 Android 的国际化(包括 ICU4J 支持),请参阅 Android 上的国际化

Android 企业版

我们针对搭载 Android 8.0(API 级别 26)的设备引入了新的企业功能和 API。亮点包括:

  • 借助完全受管设备上的工作资料,企业可以在管理工作与个人数据的同时,将工作数据与个人数据分开。
  • API 委托可让设备所有者和资料所有者将应用管理分配给其他应用。
  • 配置流程中的用户体验改进(包括新的自定义选项)缩短了设置时间。
  • 蓝牙、Wi-Fi、备份和安全性方面的新控制功能使企业可以管理更多设备。网络活动日志记录可帮助企业跟踪问题。

如需详细了解这些以及其他新的 Android 企业 API 和功能,请参阅企业中的 Android