原文
Android P 为用户和开发者引入众多新特性和新功能。
本文重点介绍面向开发者的新功能。 要了解新 API,请阅读 API 差异报告或访问 Android API 参考 — 为醒目起见,将突出显示新 API。 请务必查阅 Android P 行为变更以了解平台变更可能给您的应用带来哪些方面的影响。
利用 Wi-Fi RTT 进行室内定位
Android P 添加了对 IEEE 802.11mc Wi-Fi 协议(也称为 Wi-Fi Round-Trip-Time (RTT))的平台支持,从而让您的应用可以利用室内定位功能。
在提供硬件支持的 Android P 设备上,应用可以使用全新的 RTT API 来测量与附近支持 RTT 的 Wi-Fi 接入点 (AP) 的距离。 设备必须已启用定位并开启了 Wi-Fi 扫描(在 Settings > Location 下),同时您的应用必须具有 ACCESS_FINE_LOCATION 权限。 设备不需要连接至 AP 即可使用 RTT。 为保证隐私性,只有手机可以确定与 AP 的距离;AP 不具备该信息。
如果您的设备测量与 3 个或更多 AP 的距离,您可以使用一个多点定位算法来预估与这些测量值最相符的设备位置。 结果通常精准至 1 至 2 米。
通过这种精确性,您可以打造新的体验,例如楼内导航、基于精细位置的服务,如无歧义语音控制(例如,“打开这盏灯”),以及基于位置的信息(如 “此产品是否有特别优惠?”)。
屏幕缺口支持(刘海屏)
Android P 支持最新的全面屏以及为摄像头和扬声器预留空间的凹口屏幕。 通过全新的 DisplayCutout 类,可以确定非功能区域的位置和形状,这些区域不应显示内容。 要确定这些凹口屏幕区域是否存在及其位置,请使用 getDisplayCutout() 函数。
您可以按如下方法在任何运行 Android P 的设备或模拟器上模拟屏幕缺口:
1. 启用开发者选项。
2. 在 Developer options 屏幕中,向下滚动至 Drawing 部分并选择 Simulate a display with a cutout。
3. 选择凹口屏幕的大小。
注:我们建议您通过使用运行 Android P 的设备或模拟器测试凹口屏幕周围的内容显示。
通知
Android P 引入了多个通知增强功能,可供以 Android P 及更高版本作为目标平台的开发者使用。
从 Android 7.0(API 级别 24)开始,您可以添加一个操作以回复短信或直接从通知中输入其他文本。
渠道设置、广播和请勿打扰
Android O 引入了通知渠道,从而允许您为要显示的每种通知类型创建可由用户自定义的渠道。
多摄像头支持和摄像头更新
现在,在运行 Android P 的设备上,您可以通过两个或更多物理摄像头来同时访问多个视频流。 在配备双前置摄像头或双后置摄像头的设备上,您可以创建只配备单摄像头的设备所不可能实现的创新功能,例如无缝缩放、虚化和立体成像。 通过此 API,您还可以调用逻辑或融合的摄像头视频流,该视频流可在两个或更多摄像头之间自动切换。
摄像头方面的其他改进还包括新的会话参数和 Surface 共享,前者有助于降低首次拍照期间的延迟,而后者则让摄像头客户端能够处理各种用例,而无需停止并启动摄像头视频流。 我们还针对基于显示屏的 flash 支持和 OIS 时间戳访问新增了一些 API,用以实现应用级的图像稳定化和特效。
在受支持的设备上,Android P 还支持外置 USB/UVC 摄像头。
适用于位图和可绘制对象的 ImageDecoder
Android P 引入 ImageDecoder ,以提供现代化的图像解码方法。 您应使用 ImageDecoder 来解码图像,而不是使用 BitmapFactory 和 BitmapFactory.Options API。
ImageDecoder 让您可以从字节缓冲区、文件或 URI 来创建 Drawable 或 Bitmap。 要解码图像,请首先以编码图像的来源为参数,调用 createSource()。 然后,通过传递 ImageDecoder.Source 对象来调用 decodeBitmap() 或 decodeDrawable() ,从而创建 Bitmap或 Drawable。 要更改默认设置,请将 OnHeaderDecodedListener 传递给 decodeBitmap() 或 decodeDrawable()。 ImageDecoder 以图像的默认宽度和高度(若已知的话)为参数,调用onHeaderDecoded()。 如果编码图像是动画 GIF 或 WebP,decodeDrawable() 将返回 Drawable,后者是 AnimatedImageDrawable 类的一个实例。
您可以使用不同的方法来设置图像属性。 这些方法包括:
- 要将解码的图像缩放到精确尺寸,请以目标尺寸为参数,调用 setResize()。 您也可以使用样图尺寸来缩放图像。 将样图尺寸直接传递给 setResize(),或者调用getSampledSize() 以查看 ImageDecoder 能够最高效地获取何种尺寸的样图。
- 要在缩放图像的范围内裁剪图像,请调用 setCrop()。
- 要创建可变的 Bitmap,请调用 setMutable(true)。
通过 ImageDecoder,您还可以为圆角或圆形遮罩之类的图像添加复杂的定制效果。 以 PostProcessor 类的一个实例作为参数,使用 setPostProcessor() 来执行您希望绘制命令执行的任何工作。 当您对 AnimatedImageDrawable 进行后处理时,这些效果会作用与所有框。
动画
Android P 引入了一个新的 AnimatedImageDrawable 类,用于绘制和显示 GIF 和 WebP 动画图像。 AnimatedImageDrawable 的工作方式 AnimatedVectorDrawable 的相似之处在于,都是 RenderThread 驱动 AnimatedImageDrawable 的动画。 RenderThread 还使用工作线程进行解码,因此,解码不会干扰 RenderThread。 这种实现机制允许您的应用在使用动画图像时不必管理其更新,也不会干扰应用的界面线程。
可使用新的 ImageDecoder 解码 AnimagedImageDrawable。 以下代码段演示如何使用 ImageDecoder 来解码 AnimatedImageDrawable:
1 | Drawable d = ImageDecoder.decodeDrawable(...); |
ImageDecoder 有几种方法可用来进一步修改图像。 例如,您可以使用 setPostProcessor() 函数来修改图像的外观,例如应用圆形遮罩或圆角。
HDR VP9 视频、HEIF 图像压缩和 Media API
Android P 新增对 High Dynamic Range (HDR) VP9 Profile 2 的内置支持,因此,现在您可以在支持 HDR 的设备上为用户提供来自 YouTube、Play Movies 和其他来源的采用 HDR 的影片。
Android P 为平台增加了对 HEIF (heic) 图像编码的支持。 MediaMuxer 和 MediaExtractor 类中可支持 HEIF 静态图像示例 HEIF 改进了压缩,可节省存储空间和网络数据流量。 借助 Android P 设备上的平台支持,从后端服务器发送和使用 HEIF 图像轻而易举。 确保应用兼容这种便于共享和显示的数据格式后,尝试在应用中使用 HEIF 作为图像存储格式。 您可以使用 ImageDecoder 或 BitmapFactory 进行 jpeg 到 heicto 的转换,以通过 jpeg 获取位图,并且可以使用全新支持库 alpha 版中的 HeifWriter 编写来自 YUV 字节缓冲区、Surface 或 Bitmap 的 HEIF 静态图像。
另外,Android P 还引入了 MediaPlayer2。 此播放器支持使用 DataSourceDesc 构建的播放列表。 要创建 MediaPlayer2 的实例,请使用 MediaPlayer2.create()。
现在,还可通过 AudioTrack、AudioRecord 和 MediaDrm 类获取媒体指标。
Android P 向 MediaDRM 类添加了新函数以获取指标、高带宽数字内容保护 (HDCP) 级别、安全级别和会话数,并对安全性级别和安全停止进行更多控制。 如需了解更多详情,请参阅 API 差异报告。
JobScheduler 中的数据成本敏感度
Android P 中对 JobScheduler 进行了改进,使其可以更好地为用户处理网络相关的作业,从而与运营商独立提供的网络状态信号相协调。
现在,作业可以声明其预估的数据大小、信号预提取,并指定具体的网络要求,而运营商可以报告网络拥塞或无限流量。 然后,JobScheduler 根据网络状态管理工作。 例如,当网络拥塞时,JobScheduler 可能会延迟较大的网络请求。 如果使用的是无限流量网络,则 JobScheduler 可运行预提取作业以提升用户体验(例如预提取标题)。
添加作业时,确保使用 setEstimatedNetworkBytes()、setIsPrefetch() 和 setRequiredNetwork()(如果适用),以帮助 JobScheduler 正确处理工作。 在执行作业时,请确保使用 JobParameters.getNetwork() 返回的 Network 对象。 否则,您将隐式使用设备的默认网络,其可能不符合您的要求,从而导致意外的流量消耗
Neural Networks API 1.1
Android 8.1(API 级别 27)中引入了 Neural Networks API 以加快 Android 设备上机器学习的速度。 Android P 扩展并改进了该 API,从而增加了对 Pad、BatchToSpaceND、SpaceToBatchND、Transpose、Strided Slice、Mean、Div、Sub 和 Squeeze 九个新运算的支持。
自动填充框架
Android 8.0(API 级别 26)引入了自动填充框架,简化了应用中的表单填写。 Android P 引入了多项改进,自动填充服务可以利用这些改进进一步增强用户填写表单时的体验。 如需了解更多详情,请参阅自动填充框架页面。
安全增强功能
Android P 引入了许多新的安全功能,包括统一的指纹身份验证对话框和针对敏感交易的高可信度用户确认。 如需了解更多详情,请参阅安全性更新页面。
Android 备份的客户端加密
Android P 支持使用客户端密钥加密 Android 备份。 由于此隐私措施,在从用户设备制作的备份恢复数据时,会要求提供设备的 PIN 码、图案或密码。 如需详细了解这项新功能背后的技术,请参阅 Google 云密钥保险柜服务白皮书。
无障碍功能窗格标题
在 Android P 之前,无障碍服务无法轻松确定屏幕的某个区域是否经过更新,例如在 Fragment 过渡期间。
在 Android P 中,各个窗格区域的标题现在采用 accessibility pane titles 的格式。 无障碍服务可以收到这些标题的变更,从而能够提供关于所做变更的更精细信息。
要指定某个区域的标题,请使用新的 android:accessibilityPaneTitle 属性。 您也可以更新您在运行时使用 setAccessibilityPaneTitle() 替换的某个界面区域的标题。 例如,您可以为某个 Fragment 对象的内容区域提供标题。
基于标题的导航
如果您的应用显示的内容包含具有逻辑含义的标题,则对于表示这些标题的 View 实例,将新的 android:accessibilityHeading 属性设置为 true。 这样,用户可以从一个标题导航至下一个标题。 在用户操作屏幕阅读器时,这种导航过程尤其方便。
便捷操作
Android P 新增了一些方便用户执行操作的支持功能:
访问提示: 无障碍框架中的新功能让您可在应用界面中访问提示。 使用 getTooltipText() 读取提示文本,使用新的 ACTION_SHOW_TOOLTIP 和 ACTION_HIDE_TOOLTIP 来指示 View 的实例显示或隐藏提示。
新的全局操作: Android P 在 AccessibilityService 类中引入了对两个新设备操作的支持。 您的 Service 现在可以帮助用户分别使用 GLOBAL_ACTION_LOCK_SCREEN 和 GLOBAL_ACTION_TAKE_SCREENSHOT 操作锁定其设备并进行屏幕截图。
窗口变更详情
Android P 让您可以在应用同时重绘多个窗口时,更轻松地跟踪应用窗口的更新。 当发生 TYPE_WINDOWS_CHANGED 事件时,可使用 getWindowChanges() API 来确定窗口发生的变更。 现在,在多窗口更新期间,每个窗口都会生成自己的一组事件。 getSource() 函数返回与每个事件相关联的窗口的根视图。
如果应用已为其 View 对象定义无障碍功能窗格标题,您的 Service 将可以识别应用界面何时进行更新。 当发生 TYPE_WINDOW_STATE_CHANGED 事件时,可使用 getContentChangeTypes() 所返回的新类型来确定窗口发生的变更。 例如,框架现在可以检测窗格何时有新标题或者窗格何时消失。
旋转
为避免无意的旋转,我们新增了一个模式,哪怕设备位置发生变化,也会固定在当前屏幕方向上。 必要时用户可以通过按系统栏上的一个新增按钮手动触发旋转。
在大多数情况下,对应用的兼容性影响应该微不足道。 不过,如果您的应用有任何自定义旋转行为,或使用了任何机密的屏幕方向设置,则可能会遇到以前用户旋转首选项始终设置为纵向时被忽视的问题。 我们鼓励您审视一下您的应用所有关键 Activity 中的旋转行为,并确保您的所有屏幕方向设置仍可提供最佳体验。
一个新的旋转模式允许用户在必要时利用系统栏上的一个按钮手动触发旋转。
内置 QR 码库
Android P 自行捆绑了一个 QR 码库,以精简 QR 码设备配置。 IT 管理员不再需要手动输入 Wi-Fi 详细信息来设置设备。 从 Android P 开始,可在 QR 码内包含这些 Wi-Fi 详细信息。 当 IT 管理员使用公司所有的设备扫描 QR 码时,设备会自动连接到 Wi-Fi 并进入配置流程,无需任何额外的手动输入。
后台应用中的输入和数据隐私
Android P 通过限制后台应用访问用户输入和传感器数据的能力增强了隐私性。 如果您的应用在运行 Android P 的设备上在后台运行,系统将对您的应用施加以下限制:
- 您的应用不能访问麦克风或摄像头。
- 使用连续报告模式的传感器(例如加速度计和陀螺仪)不会接收事件。
- 使用发送变化时或一次性报告模式的传感器不会接收事件。
如果您的应用需要在运行 Android P 的设备上检测传感器事件,请使用前台服务。
注:对 SensorManager 的某个实例调用 flush() 的应用不会受此变更影响。
加密变更
Android P 针对加密算法的实现和处理引入了几项变更。
参数和算法的 Conscrypt 实现
Android P 在 Conscrypt 中实现了更多的算法参数{: .external-link}。 这些参数包括: AES、DESEDE、OAEP 和 EC。 这些参数和许多算法的 Bouncy Castle 版本{: .external-link} 在 Android P 中已被弃用。
注:EC 参数的 Conscrypt 实现仅支持已命名的曲线。
如果您的应用以 Android 8.1(API 级别 27)或更低版本为目标,则在请求上述已弃用算法的 Bouncy Castle 实现时,您将收到一条警告消息。 然而,如果您以 Android P 为目标,则这些请求会各自引发 NoSuchAlgorithmException。
Android P 引入了其他几项加密变更:
- 使用 PBE 密钥时,如果 Bouncy Castle 需要初始化矢量 (IV),而您的应用未提供 IV,则会收到一条警告消息。
- ARC4 加密的 Conscrypt 实现允许您指定 ARC4/ECB/NoPadding 或 ARC4/NONE/NoPadding。
- Crypto Java 加密架构 (JCA) 提供程序现已被移除。 因此,如果您的应用调用 SecureRandom.getInstance(“SHA1PRNG”, “Crypto”),将会发生 NoSuchProviderException。
- 如果您的应用从大于密钥结构的缓冲区中解析 RSA 密钥,将不会再发生异常。
Java UTF 解码器
UTF-8 是 Android 中的默认字符集。 UTF-8 字节序列可由 String(byte[] bytes) 之类的 String 构造函数解码。 Android P 中的 UTF-8 解码器更严格,其遵循 Unicode 标准,也即:
- 非最短形式的 UTF-8(例如 <C0, AF>)现在被视为格式不正确。
- 替代形式的 UTF-8(例如 U+D800..U+DFFF)现在被视为格式不正确。
- 最大的子部分被单个 U+FFFD 取代。 例如,在字节序列“41 C0 AF 41 F4 80 80 41”中,最大子部分为“C0”、“AF”和“F4 80 80”。其中“F4 80 80”可以是“F4 80 80 80”的初始子序列,但“C0”不能是任何形式正确的代码单位序列的初始子序列。 因此,输出应为“A\ufffd\ufffdA\ufffdA”。
- 要在 Android P 中解码修改后的 UTF-8/CESU-8 序列,请使用 DataInputStream.readUTF() 函数或 NewStringUTF() JNI 函数。
套接字标记
在 Android P 以前的平台版本上,如果使用 setThreadStatsTag() 函数标记某个套接字,则当使用带 ParcelFileDescriptor 容器的 binder IPC 将其发送给其他进程时,套接字会被取消标记。
从 Android P 开始,利用 binder IPC 将套接字发送至其他进程时,其标记将得到保留。 此变更可能影响网络流量统计,例如,使用queryDetailsForUidTag() 函数时。 您可以通过先调用 untagSocket() 然后再将套接字发送至其他进程,保留以前的行为。
在调用 shutdownInput() 函数后调用 available() 函数会返回 0。
现在,强制执行 FLAG_ACTIVITY_NEW_TASK 要求
在 Android P 中,您不能从非 Activity 环境中启动 Activity,除非您传递 Intent 标志 FLAG_ACTIVITY_NEW_TASK。 如果您尝试在不传递此标志的情况下启动 Activity,则该 Activity 不会启动,系统会在日志中输出一则消息。
注:在 Android N 之前,标志要求一直是期望的行为并被强制执行。 Android N 中的一个错误会临时阻止实施标志要求。
屏幕旋转变更
Android O 中的用户可以使用 Quicksettings 图块或 Display 设置在自动屏幕旋转和纵向旋转模式之间切换。 Android P 对纵向旋转模式做出了重大变更。 纵向模式已重命名为旋转锁定,它会在自动屏幕旋转关闭时启用。 自动屏幕旋转模式没有任何变更。
当设备处于旋转锁定模式时,用户可将其屏幕锁定到顶层可见 Activity 所支持的任何旋转。 Activity 不应假定它将始终以纵向呈现。 如果顶层 Activity 可在自动屏幕旋转模式下以多种旋转呈现,则应在旋转锁定模式下提供相同的选项,根据 Activity 的 screenOrientation 设置,允许存在一些例外情况(见下表)。
请求特定屏幕方向(例如,screenOrientation=landscape)的 Activity 会忽略用户锁定首选项,并且行为与 Android O 中的行为相同。
可在 Android 清单中,或以编程方式通过 setRequestedOrientation(),在 Activity 一级设置屏幕方向首选项。
旋转锁定模式通过设置 WindowManager 在处理 Activity 旋转时使用的用户旋转首选项来发挥作用。 用户旋转首选项可能在下列情况下发生变更。 请注意,恢复纵向模式存在偏差:
- 当用户接受旋转建议时,旋转首选项变为建议方向。
- 当用户切换到强制纵向应用(包括锁定屏幕或启动器)时,旋转首选项变为纵向。
下表总结了常见屏幕方向的旋转行为:
表格,看原文