Android高级进阶--插曲-从Android5.0到Android9.0各版本变化

                            从Android5.0到Android9.0

           自从公司提出了一些出其不意的需求之后我就下定了决心去了解安卓各版本系统的差异。这些出其不意的需求要么属于黑客行为,要么还不成熟,很难顺利的实现,例如做一个杀不死的APP,又或者是一个APP可以模拟人手指随意自动操作手机上的其它APP,例如打开微信,控制微信聊天、控制支付宝等。这些需求都可以实现一部分,但是作为一个APP产品,从长远来说还是很难维持下去,要么是一个流氓软件,要么就是黑客软件,试问您愿意让我开发的APP随意去打开,并代替您的手指自动去操作您的微信聊天,给您的好友自动发送聊天消息,又或者打开支付宝付款相关页面吗?市面上的相关APP经过测试都不成熟,都是半瓶子水。例如代替手指自动操作手机上的其它APP,本人也能实现,但最终也许和其它市场上的APP一样,不成熟,黑客行为,因为我需要窃取您的微信APP界面上的控件ID(可以理解为一个按钮的编号)然后尝试自动点击,这些APP最终会很难维护下去。

          在此期间也不乏有同事拿出市面上已有的APP来向我展示,貌似对我心理暗示:“看,这不是能实现吗?是你技不如人吧”,好吧,我认了。我心中一直有这个意识:人外有人山外有山,还是认怂为秒,与其与他人争论还不如认怂:退一步海阔天空。好了这些都扯远了,今天的目标是给大家总结一下从Android5至Android9各版本的差异,如果你对我说的"杀不死的APP"与"自动控制APP"感兴趣,我将在后续的文章中讲解,或者email:   [email protected]

一、Android5
1.ANDROID 5.0 行为变更:

  • 声音和振动

(1)如果您当前使用 Ringtone、MediaPlayer 或 Vibrator 类向通知中添加声音和振动,则移除此代码,以便系统可以在“优先”模式中正确显示通知。取而代之的是,使用 Notification.Builder 方法添加声音和振动。

(2)以前,Android 使用 STREAM_MUSIC 作为主流式传输来控制平板电脑设备上的音量。在 Android 5.0 中,手机和平板电脑设备的主音量流式传输现已合并,由 STREAM_RING 或 STREAM_NOTIFICATION 进行控制。

(3)媒体播放
       如果您要实现显示媒体播放状态或传输控件的通知,请考虑使用新的 Notification.MediaStyle 模板,而不是自定义 RemoteViews.Remote View 对象。无论您选择使用哪个方法,请务必将通知的可见性设为 VISIBILITY_PUBLIC,以便可通过锁定屏幕访问您的控件。请注意,从 Android 5.0 开始,系统不再将 RemoteControlClient 对象显示在锁定屏幕上。如需了解详细信息,请参阅如果您的应用使用 RemoteControlClient.
       
(4)浮动通知               

现在,当设备处于活动状态时(即,设备未锁定且其屏幕已打开),通知可以显示在小型浮动窗口中(也称为“浮动通知”)。这些通知看上去类似于精简版的通知,只是浮动通知还显示操作按钮。用户可以在不离开当前应用的情况下处理或清除浮动通知。
可能触发浮动通知的条件示例包括:
用户的 Activity 处于全屏模式中(应用使用 fullScreenIntent)
通知具有较高的优先级并使用铃声或振动。

(5)绑定到服务
Context.bindService() 方法现在需要显式 Intent,如果提供隐式 intent,将引发异常。为确保应用的安全性,请使用显式 intent 启动或绑定 Service,且不要为服务声明 intent 过滤器。


(6)WebView
Android 5.0 更改了应用的默认行为。
如果您的应用是面向 API 级别 21 或更高级别:
默认情况下,系统会阻止混合内容和第三方 Cookie。要允许混合内容和第三方 Cookie,请分别使用 setMixedContentMode() 和 setAcceptThirdPartyCookies() 方法。
系统现在可以智能地选择要绘制的 HTML 文档部分。这个新的默认行为有助于减少内存占用和提升性能。如果您要一次渲染整个文档,可通过调用 enableSlowWholeDocumentDraw() 停用此优化。
如果您的应用是面向低于 21 的 API 级别:系统允许混合内容和第三方 Cookie,并始终一次渲染整个文档。

(7)自定义权限
从 Android 5.0 开始,对于使用不同密钥签名的应用,系统会强制执行新的自定义权限唯一性限制。现在,设备上只有一个应用可以定义给定的自定义权限(按其名称确定),除非定义此权限的其他应用使用相同密钥签名

(8)
与服务器握手的 TLS/SSL 被错误地拒绝或出现停顿。首选的修复方法是升级服务器以符合 TLS/SSL 协议


2. ANDROID 5.0 API变更

(1)  WebView 更新

Android 5.0 将 WebView 实现更新至 Chromium M37,增强了安全性和稳定性,并修复了一些问题。运行在 Android 5.0 上的 WebView 的默认用户代理字符串已更新,以纳入 37.0.0.0 作为版本号。

此版本引入了 PermissionRequest 类,让您的应用可以通过 getUserMedia()open_in_new 等网络 API 授予 WebView 访问相机和麦克风之类受保护资源的权限。您的应用必须对这些资源拥有相应的 Android 权限,才能向 WebView 授予权限。

借助新的 onShowFileChooser() 方法,您现在可以在 WebView 中使用输入表单字段,然后启动文件选择器从 Android 设备中选择图像和文件。

此外,此版本还提供了对 WebAudioopen_in_new、WebGLopen_in_new 和 WebRTCopen_in_new 开放标准的支持。要详细了解此版本包含的新功能,请参阅 WebView for Androidopen_in_new。

(2).屏幕采集和共享

Android 5.0 引入了新的 android.media.projection API,让您可以为应用添加屏幕采集和屏幕共享功能。例如,如果您想在视频会议应用中启用屏幕共享,便可使用此功能。

新增的 createVirtualDisplay() 方法允许您的应用将主屏幕(默认显示)的内容采集到一个 Surface 对象中,然后您的应用便可将其发送至整个网络。该 API 只允许采集非安全屏幕内容,不允许采集系统音频。要开始采集屏幕,您的应用必须先使用通过 createScreenCaptureIntent() 方法获得的 Intent 启动屏幕采集对话框,请求用户授予权限。
如需查看新 API 使用方法的示例,请参阅示例项目中的 MediaProjectionDemo 类。


(3). 用户界面
Material Design 支持
Android 5.0 添加了对 Android 的新 Material Design 样式的支持。您可以创建具有 Material Design 功能的应用,实现动态视觉效果,利用其中的 UI 元素转换赋予用户自然的感觉。此支持包括:
----------------------------------------------------------------------------------------------
Material Design 支持
Android 5.0 添加了对 Android 的新 Material Design 样式的支持。您可以创建具有 Material Design 功能的应用,实现动态视觉效果,利用其中的 UI 元素转换赋予用户自然的感觉。此支持包括:
Material Design 主题
视图阴影
RecyclerView 小部件
可绘制动画和造型效果
Material Design 动画和 Activity 转换效果
针对基于视图状态的视图属性的动画生成器
可自定义的 UI 小部件和具有可由您控制的调色板的应用栏
基于 XML 矢量图形的动画和非动画可绘制对象

(4).通知

  • 锁定屏幕通知

Android 5.0 中的锁定屏幕可以显示通知。用户可以通过“Settings” 选择是否允许在安全的锁定屏幕上显示敏感的通知内容。

您的应用可以控制在安全锁定屏幕上显示的通知中可见信息的详细程度。要控制可见性级别,请调用 setVisibility(),然后指定以下值之一:
VISIBILITY_PRIVATE:显示通知图标等基本信息,但隐藏通知的完整内容。
?VISIBILITY_PUBLIC:显示通知的完整内容。
VISIBILITY_SECRET:不显示任何内容,甚至不显示通知图标。

当可视性级别为 VISIBILITY_PRIVATE 时,您还可以提供隐藏个人详情的删减版通知内容。例如,短信应用可能会显示一条通知,指出“您有3 条新短信”,但是隐藏了短信内容和发件人。要提供此替换版本的通知,请先使用 Notification.Builder 创建替换通知。创建专用通知对象时,请通过 setPublicVersion() 方法为其附加替换通知。

  • 通知元数据

Android 5.0 使用与您的应用通知关联的元数据,以更智能的方式对通知排序。要设置元数据,请在构建通知时调用 Notification.Builder 中的下列方法:

setCategory():当设备处于“优先”模式时,指示系统如何处理应用通知(例如,通知代表来电、即时通讯还是闹铃)。
setPriority():标记通知的重要性是高于还是低于普通通知。如果优先级字段设置为 PRIORITY_MAX 或PRIORITY_HIGH 的通知还有声音或振动,则会将其显示在小型浮动窗口中。
addPerson():让您可以添加一名或多名与通知有关的人员。您的应用可以使用此名单指示系统将指定人员发出的通知归成一组,或者将这些人员发出的通知视为更重要的通知。

(5).对 OpenGL ES 3.1 的支持

(6).媒体

用于高级相机功能的 Camera API

Android 5.0 引入了新的 android.hardware.camera2 API 来简化精细照片采集和图像处理。您现在可以使用 getCameraIdList() 通过编程方式访问可供系统使用的相机设备,以及使用 openCamera() 通过编程方式连接特定设备。要开始采集图像,请创建一个 CameraCaptureSession 并指定用于发送已采集图像的 Surface 对象。可将 CameraCaptureSession 配置为进行单张拍摄或多张连拍。

要在采集新图像时得到通知,请实现 CameraCaptureSession.CaptureCallback 侦听器,并在您的采集请求中进行设置。现在,当系统完成图像采集请求时,您的 CameraCaptureSession.CaptureCallback 侦听器会收到对 onCaptureCompleted() 的调用,并在 CaptureResult 中为您提供图像采集元数据。

CameraCharacteristics 类可让您的应用检测到设备上可用的相机功能。该对象的 INFO_SUPPORTED_HARDWARE_LEVEL 属性代表相机的功能级别。

所有设备都至少支持 INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY 硬件级别,该级别具有的能力大致与弃用的 Camera API 相当。
支持 INFO_SUPPORTED_HARDWARE_LEVEL_FULL 硬件级别的设备可手动控制采集和后期处理,以及以高帧速率采集高分辨率图像。
要了解如何使用更新后的 Camera API,请参阅此版本中的 Camera2Basic 和 Camera2Video 实现示例。

(7).音频回放

此版本加入了对 AudioTrack 的下列更改:

您的应用现在可以提供浮点格式 (ENCODING_PCM_FLOAT) 的音频数据。这可以实现更大的动态范围、更一致的精度和更多的动态余量。浮点算法在进行中间计算时特别有用。回放端点为音频数据使用位深度更低的整型格式。(在Android 5.0中,部分内部管道尚未采用浮点格式。)
您的应用现在可以提供音频数据作为 ByteBuffer,数据使用的格式与 MediaCodec 提供的格式相同。
WRITE_NON_BLOCKING 选项可简化某些应用的缓冲和多线程处理。


(8) 媒体回放控制

使用新增的通知和媒体 API 可确保系统 UI 了解您的媒体回放情况,并可提取和显示专辑封面。现在,可以利用新增的 MediaSession 类和 MediaController 类更轻松地在整个 UI 和服务范围内控制媒体回放。

新增的 MediaSession 类替代了弃用的 RemoteControlClient 类,仅提供一套回调方法来处理传输控制和媒体按钮。如果您的应用提供媒体回放,并运行在 Android TV 或 Wear 平台上,请使用 MediaSession 类,通过同样的回调方法来处理您的传输控制。

现在,您可以使用新增的 MediaController 类开发自己的媒体控制器应用。该类可通过您的应用的 UI 进程,以线程安全方式监控和控制媒体回放。请在创建控制器时指定一个 MediaSession.Token 对象,以便您的应用可与给定 MediaSession 交互。您可以利用 MediaController.TransportControls 方法,通过发送 play()、stop()、skipToNext() 和 setRating() 等命令来控制该会话上的媒体回放。对于控制器,您还可以注册一个 MediaController.Callback 对象来侦听该会话上的元数据和状态变化。

此外,您还可以利用新增的 Notification.MediaStyle 类创建允许将回放控制与媒体会话绑定的丰富通知


(9).媒体浏览

Android 5.0 引入了通过新增的 android.media.browse API 让应用能够浏览其他应用媒体内容库的功能。要公开您应用内的媒体内容,请扩展 MediaBrowserService 类。您实现的 MediaBrowserService 应提供对 MediaSession.Token 的访问权限,以便应用能播放通过您的服务提供的媒体内容。

要与媒体浏览器服务交互,请使用 MediaBrowser 类。在您创建 MediaBrowser 实例时为 MediaSession 指定组件名称。然后,您的应用便可利用该浏览器实例连接到关联的服务并获得 MediaSession.Token 对象,以播放通过该服务公开的内容。

(10).无线和连接

多个网络连接

Android 5.0 提供了新的多网络 API,允许您的应用动态扫描具有特定能力的可用网络,并与它们建立连接。当您的应用需要 SUPL、彩信或运营商计费网络等专业化网络时,或者您想使用特定类型的传输协议发送数据时,就可以使用此功能。

要从您的应用以动态方式选择并连接网络,请执行以下步骤:

创建一个 ConnectivityManager。
使用 NetworkRequest.Builder 类创建一个 NetworkRequest 对象,并指定您的应用感兴趣的网络功能和传输类型。
要扫描合适的网络,请调用 requestNetwork() 或 registerNetworkCallback(),并传入 NetworkRequest 对象和 ConnectivityManager.NetworkCallback 的实现。如果您想在检测到合适的网络时主动切换到该网络,请使用 requestNetwork() 方法;如果只是接收已扫描网络的通知而不需要主动切换,请改用 registerNetworkCallback() 方法。
当系统检测到合适的网络时,它会连接到该网络并调用 onAvailable() 回调。您可以使用回调中的 Network 对象来获取有关网络的更多信息,或者引导通信使用所选网络。

(11). 蓝牙低功耗

Android 4.3 为发挥核心作用的蓝牙低功耗(蓝牙 LE)引入了平台支持。在 Android 5.0 中,Android 设备现在可以发挥蓝牙 LE 外围设备的作用。应用可以利用此功能让附近设备发现它。例如,您可以开发这样的应用:让设备发挥计步器或健康监测仪的作用,并与其他蓝牙 LE 设备进行数据通信。

新增的 android.bluetooth.le API 让您的应用可以发布广告、扫描响应以及与附近的蓝牙 LE 设备建立连接。要使用新增的广告和扫描功能,请在您的清单中添加 BLUETOOTH_ADMIN 权限。当用户更新您的应用或从 Play 商店下载您的应用时,会被要求向您的应用授予以下权限:“Bluetooth connection information:Allows the app to control Bluetooth, including broadcasting to or getting information about nearby Bluetooth devices.”

要启动蓝牙 LE 广播,以便其他设备能发现您的应用,请调用 startAdvertising(),并传入 AdvertiseCallback 类的实现。回调对象会收到广播操作成功或失败的报告。

Android 5.0 引入了 ScanFilter 类,让您的应用可以只扫描其感兴趣的特定类型设备。要开始扫描蓝牙 LE 设备,请调用 startScan(),并传入筛选器列表。在方法调用中,您还必须提供 ScanCallback 的实现,以便在发现蓝牙 LE 广播时进行报告。


(12)  计划排定作业JobScheduler

Android 5.0 新增了一个 JobScheduler API,允许您定义一些系统在稍后或指定条件下(如设备充电时)以异步方式运行的作业,从而优化电池寿命。下列情形下,作业计划排定功能很有用:

应用具有不面向用户并且可以推迟的作业
应用具有您更愿意在设备插入电源时再进行的作业
应用具有一项需要接入网络或连接 WLAN 的任务。
应用具有多项您希望定期以批处理方式运行的任务。
一个作业单位由一个 JobInfo 对象封装。该对象指定计划排定标准。

使用 JobInfo.Builder 类可配置应如何运行已排计划的任务。您可以安排任务在特定条件下运行,例如:

在设备充电时启动
在设备连入无限流量网络时启动
在设备空闲时启动
在特定期限前或以最低延迟完成
例如,您可以添加一段如下代码,在无限流量网络上运行您的任务:

JobInfo uploadTask = new JobInfo.Builder(mJobId,
                                         mServiceComponent /* JobService component */)
        .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED)
        .build();
JobScheduler jobScheduler =
        (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(uploadTask);
如果设备有稳定的电源(也就是说,设备已插入电源超过 2 分钟,并且电池处于健康水平),系统将运行任何已做好运行准备的计划作业,无论作业期限是否已过。

要查看如何使用 JobScheduler API 的示例,请参阅此版本中的 JobSchedulerSample 实现示例。

(13)固定屏幕

Android 5.0 引入了一个全新的固定屏幕 API,可让您暂时限制用户离开您的任务或被通知打断。举例来说,如果您要开发一款教育应用来支持 Android 上的高风险评估要求,或者您要开发单一用途或信息亭模式下的应用,便可使用此 API。您的应用激活固定屏幕后,在其退出该模式前,用户将无法看到通知,无法访问其他应用,也无法返回主屏幕。

激活固定屏幕的方式有两种:

  • 手动方式:用户可以在 Settings > Security > Screen Pinning 中启用固定屏幕,然后通过触摸最近使用的应用屏幕中的绿色大头针图标选择其想固定的任务。
  • 编程方式:要以编程方式激活固定屏幕,请在您的应用内调用 startLockTask()。如果请求应用不是设备所有者,系统会提示用户进行确认。设备所有者应用可以调用 setLockTaskPackages() 方法,无需执行用户确认步骤便可使应用变为可固定应用。

激活任务锁定时,会发生以下行为:

状态栏空白,并隐藏用户通知和状态信息。
“主屏幕”按钮和“最近用过的应用”按钮处于隐藏状态。
其他应用无法启动新 Activity
当前应用可以启动新 Activity,前提是这样做不会创建新任务。
当设备所有者调用固定屏幕时,用户将一直锁定于您的应用,直至应用调用 stopLockTask()。
如果固定屏幕是由并非设备所有者的其他应用启动的 Activity,或者是由用户直接启动,则用户可通过同时按住“Back”按钮和“Recent”按钮退出。


(14)可声明的必备功能

现在支持在 <uses-feature> 元素中使用以下值,以便您确保只在提供应用所需功能的设备上安装您的应用

(15)用户权限

现在,<uses-permission> 元素中支持以下权限,以声明您的应用访问特定 API 所需的权限。

BIND_DREAM_SERVICE:如果针对的是 API 级别 21 及更高级别,则互动屏保服务必须获得该权限才能确保只有系统可与其绑定。


二、ANDROID 6.0

1. 行为变更

(1)  运行时权限

此版本引入了一种新的权限模式,如今,用户可直接在运行时管理应用权限。这种模式让用户能够更好地了解和控制权限,同时为应用开发者精简了安装和自动更新过程。用户可为所安装的各个应用分别授予或撤销权限。

对于以 Android 6.0(API 级别 23)或更高版本为目标平台的应用,请务必在运行时检查和请求权限。要确定您的应用是否已被授予权限,请调用新增的 checkSelfPermission() 方法。要请求权限,请调用新增的 requestPermissions() 方法。即使您的应用并不以 Android 6.0(API 级别 23)为目标平台,您也应该在新权限模式下测试您的应用。

如需了解有关在您的应用中支持新权限模式的详情,请参阅使用系统权限。如需了解有关如何评估新模式对应用的影响的提示,请参阅权限最佳做法。


(2)  低电耗模式和应用待机模式

此版本引入了针对空闲设备和应用的最新节能优化技术。这些功能会影响所有应用,因此请务必在这些新模式下测试您的应用。

低电耗模式:如果用户拔下设备的电源插头,并在屏幕关闭后的一段时间内使其保持不活动状态,设备会进入低电耗模式,在该模式下设备会尝试让系统保持休眠状态。在该模式下,设备会定期短时间恢复正常工作,以便进行应用同步,还可让系统执行任何挂起的操作。
应用待机模式:应用待机模式允许系统判定应用在用户未主动使用它时处于空闲状态。当用户有一段时间未触摸应用时,系统便会作出此判定。如果拔下了设备电源插头,系统会为其视为空闲的应用停用网络访问以及暂停同步和作业。
要详细了解这些节能变更,请参阅对低电耗模式和应用待机模式进行针对性优化。

(3)取消支持 Apache HTTP 客户端

Android 6.0 版移除了对 Apache HTTP 客户端的支持。如果您的应用使用该客户端,并以 Android 2.3(API 级别 9)或更高版本为目标平台,请改用 HttpURLConnection 类。此 API 效率更高,因为它可以通过透明压缩和响应缓存减少网络使用,并可最大限度降低耗电量。要继续使用 Apache HTTP API,您必须先在 build.gradle 文件中声明以下编译时依赖项:

android {
    useLibrary 'org.apache.http.legacy'
}


(4)BoringSSL

Android 正在从使用 OpenSSL 库转向使用 BoringSSL 库。如果您要在应用中使用 Android NDK,请勿链接到并非 NDK API 组成部分的加密库,如 libcrypto.so 和 libssl.so。这些库并非公共 API,可能会在不同版本和设备上毫无征兆地发生变化或出现故障。此外,您还可能让自己暴露在安全漏洞的风险之下。请改为修改原生代码,以通过 JNI 调用 Java 加密 API,或静态链接到您选择的加密库。

(5) 蓝牙扫描需要定位权限 才能获得MAC地址,硬件标识符访问权

为给用户提供更严格的数据保护,从此版本开始,对于使用 WLAN API 和 Bluetooth API 的应用,Android 移除了对设备本地硬件标识符的编程访问权。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getAddress() 方法现在会返回常量值 02:00:00:00:00:00。

现在,要通过蓝牙和 WLAN 扫描访问附近外部设备的硬件标识符,您的应用必须拥有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 权限。

WifiManager.getScanResults()
BluetoothDevice.ACTION_FOUND
BluetoothLeScanner.startScan()
注:当运行 Android 6.0(API 级别 23)的设备发起后台 WLAN 或蓝牙扫描时,在外部设备看来,该操作的发起来源是一个随机化 MAC 地址。

(6) 通知
此版本移除了 Notification.setLatestEventInfo() 方法。请改用 Notification.Builder 类来构建通知。要重复更新通知,请重复使用 Notification.Builder 实例。调用 build() 方法可获取更新后的 Notification 实例。

adb shell dumpsys notification 命令不再打印输出您的通知文本。请改用 adb shell dumpsys notification --noredact 命令打印输出 notification 对象中的文本。

(7)音频管理器变更

不再支持通过 AudioManager 类直接设置音量或将特定音频流静音。setStreamSolo() 方法已弃用,您应该改为调用 requestAudioFocus() 方法。类似地,setStreamMute() 方法也已弃用,请改为调用 adjustStreamVolume() 方法并传入方向值 ADJUST_MUTE 或 ADJUST_UNMUTE。


(8)WLAN 和网络连接变更
此版本对 WLAN API 和 Networking API 引入了以下行为变更。

现在,您的应用只能更改由您创建的 WifiConfiguration 对象的状态。系统不允许您修改或删除由用户或其他应用创建的 WifiConfiguration 对象。
在之前的版本中,如果应用利用带有 disableAllOthers=true 设置的 enableNetwork() 强制设备连接特定 WLAN 网络,设备将会断开与移动数据网络等其他网络的连接。在此版本中,设备不再断开与上述其他网络的连接。如果您的应用的 targetSdkVersion 为 “20” 或更低,则会固定连接所选 WLAN 网络。如果您的应用的 targetSdkVersion 为 “21” 或更高,请使用多网络 API(如 openConnection()、bindSocket() 和新增的 bindProcessToNetwork() 方法)来确保通过所选网络传送网络流量。

(9)相机服务变更

在此版本中,相机服务中共享资源的访问模式已从之前的“先到先得”访问模式更改为高优先级进程优先的访问模式。对服务行为的变更包括:

根据客户端应用进程的“优先级”授予对相机子系统资源的访问权,包括打开和配置相机设备。带有对用户可见 Activity 或前台 Activity 的应用进程一般会被授予较高的优先级,从而使相机资源的获取和使用更加可靠;

当高优先级的应用尝试使用相机时,系统可能会“驱逐”正在使用相机客户端的低优先级应用。在已弃用的 Camera API 中,这会导致系统为被驱逐的客户端调用 onError()。在 Camera2 API 中,这会导致系统为被驱逐的客户端调用 onDisconnected();

在配备相应相机硬件的设备上,不同的应用进程可同时独立打开和使用不同的相机设备。但现在,如果在多进程用例中同时访问相机会造成任何打开的相机设备的性能或能力严重下降,相机服务会检测到这种情况并禁止同时访问。即使并没有其他应用直接尝试访问同一相机设备,此变更也可能导致低优先级客户端被“驱逐”。


更改当前用户会导致之前用户帐户拥有的应用内活动相机客户端被驱逐。对相机的访问仅限于访问当前设备用户拥有的用户个人资料。举例来说,这意味着,当用户切换到其他帐户后,“来宾”帐户实际上无法让使用相机子系统的进程保持运行状态

(10)运行时

ART 运行时环境现在可正确实现 newInstance() 方法的访问规则。此变更修正了之前版本中 Dalvik 无法正确检查访问规则的问题。如果您的应用使用 newInstance() 方法,并且您想重写访问检查,请调用 setAccessible() 方法(将输入参数设置为 true)。如果您的应用使用 v7 appcompat 库或 v7 recyclerview 库,则您必须更新应用以使用这些库的最新版本。否则,请务必更新从 XML 引用的任何自定义类,以便能够访问它们的类构造函数。

此版本更新了动态链接程序的行为。动态链接程序现在可以识别库的 soname 与其路径之间的差异(公开错误 6670),并且现在已实现了按 soname 搜索。之前包含错误的 DT_NEEDED 条目(通常是开发计算机文件系统上的绝对路径)却仍工作正常的应用,如今可能会出现加载失败。

现已正确实现 dlopen(3) RTLD_LOCAL 标记。请注意,RTLD_LOCAL 是默认值,因此不显式使用 RTLD_LOCAL 的 dlopen(3) 调用将受到影响(除非您的应用显式使用 RTLD_GLOBAL)。使用 RTLD_LOCAL 时,在随后通过调用 dlopen(3) 加载的库中并不能使用这些符号(这与由 DT_NEEDED 条目引用的情况截然不同)。

在之前版本的 Android 上,如果您的应用请求系统加载包含文本重定位信息的共享库,系统会显示警告,但仍允许加载共享库。从此版本开始,如果您的应用的目标 SDK 版本为 23 或更高,则系统会拒绝加载该库。为帮助您检测库是否加载失败,您的应用应该记录 dlopen(3) 失败日志,并在日志中加入 dlerror(3) 调用返回的问题描述文本。要详细了解如何处理文本重定位,请参阅此指南。


(11)APK 验证

该平台现在执行的 APK 验证更为严格。如果在清单中声明的文件在 APK 中并不存在,该 APK 将被视为已损坏。移除任何内容后必须重新签署 APK。

(12)USB 连接

默认情况下,现在通过 USB 端口进行的设备连接设置为仅充电模式。要通过 USB 连接访问设备及其内容,用户必须明确地为此类交互授予权限。如果您的应用支持用户通过 USB 端口与设备进行交互,请将必须显式启用交互考虑在内

2.ANDROID 6.0 API 变更

1. 指纹身份验证

此版本提供了一些新的 API,在受支持的设备上,用户只需扫描其指纹即可完成身份验证,这些 API 还可与 Android 密钥库系统结合使用。

要通过指纹扫描验证用户身份,请获取新 FingerprintManager 类的实例,并调用 authenticate()方法。您的应用必须运行在带有指纹传感器的兼容设备上。您必须在应用中实现指纹身份验证流的用户界面,并在 UI 中使用标准 Android 指纹图标。FingerprintDialog 示例中包含有 Android 指纹图标 (c_fp_40px.png)。请注意,如果您要开发多个使用指纹身份验证的应用,每个应用必须独立验证用户的指纹。

要在您的应用中使用此功能,请先在清单中添加 USE_FINGERPRINT 权限。

<uses-permission
        android:name="android.permission.USE_FINGERPRINT" />

要查看指纹身份验证的应用实现,请参阅FingerprintDialog 示例。要查看有关将这些身份验证 API 与其他 Android API 结合使用方法的演示,请观看视频 Fingerprint API 和 Payment API。


2.确认凭据

您的应用可以根据用户在多久之前最后一次解锁设备来验证其身份。此功能让用户不必费心记忆应用特定密码,您也无需实现自己的身份验证用户界面。您的应用应当利用此功能并结合实现公钥或私钥,以进行用户身份验证。

要设置成功验证用户身份后可再次使用同一密钥的超时持续时间,请在设置 KeyGenerator 或 KeyPairGenerator 时调用新增的 setUserAuthenticationValidityDurationSeconds() 方法。

避免过多显示重新验证对话框 -- 您的应用应尝试先使用加密对象,如果超时到期,请使用 createConfirmDeviceCredentialIntent() 方法在您的应用内重新验证用户身份。

要查看此功能的应用实现,请参阅 ConfirmCredential 示例。


3.直接共享
此版本为您提供的一些 API 可让用户直观、快捷地进行共享。现在,您可以定义可在您的应用内启动特定 Activity 的直接共享目标。这些直接共享目标通过“共享”菜单公开给用户。此功能让用户可以向其他应用内的目标(如联系人)共享内容。例如,直接共享目标可以启动另一社交网络应用中的某个 Activity,让用户可以直接向该应用中的某位朋友或某个社区共享内容。

要启用直接共享目标,您必须定义一个类,用于扩展 ChooserTargetService 类。在清单中声明您的服务。在该声明内,指定 BIND_CHOOSER_TARGET_SERVICE 权限和一个使用 SERVICE_INTERFACE 操作的 intent 过滤器。

以下示例展示了如何在清单中声明 ChooserTargetService。

<service android:name=".ChooserTargetService"
        android:label="@string/service_name"
        android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE">
    <intent-filter>
        <action android:name="android.service.chooser.ChooserTargetService" />
    </intent-filter>
</service>
对于您想要向 ChooserTargetService 公开的每个 Activity,请在您的应用清单中为其添加一个名为 "android.service.chooser.chooser_target_service" 的 <meta-data> 元素。

<activity android:name=".MyShareActivity”
        android:label="@string/share_activity_label">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
    </intent-filter>
<meta-data
        android:name="android.service.chooser.chooser_target_service"
        android:value=".ChooserTargetService" />
</activity>

4. 语音交互

此版本提供了一个新的语音交互 API,与语音操作一起使用时,可让您为应用打造对话式语音体验。调用 isVoiceInteraction() 方法可确定是否是响应语音操作触发了您的 Activity。如果是这样,则您的应用可以使用 VoiceInteractor 类请求用户进行语音确认、从选项列表中进行选择以及执行其他操作。

大多数语音交互都由用户语音操作发起。但语音交互 Activity 也可在没有用户输入的情况下启动。例如,通过语音交互启动的另一应用也可发送 intent 来启动语音交互。要确定您的 Activity 是由用户语音查询还是另一语音交互应用启动,请调用 isVoiceInteractionRoot() 方法。如果另一应用启动了您的 Activity,该方法会返回 false。您的应用可能随即提示用户确认其有意执行此操作。


5. 可采用的存储设备

使用此版本时,用户可以采用 SD 卡等外部存储设备。采用外部存储设备可加密和格式化设备,使其具有类似内部存储设备的行为。用户可以利用此特性在存储设备之间移动应用及其私有数据。移动应用时,系统会遵守清单中的 android:installLocation 首选项。

请注意,在内部存储设备与外部存储设备之间移动应用时,如果您的应用访问以下 API 或字段,它们返回的文件路径将会动态变化。强烈建议:在生成文件路径时,请始终动态调用这些 API。请勿使用硬编码文件路径或之前生成的永久性完全限定文件路径。

Context 方法:
getFilesDir()
getCacheDir()
getCodeCacheDir()
getDatabasePath()
getDir()
getNoBackupFilesDir()
getFileStreamPath()
getPackageCodePath()
getPackageResourcePath()
ApplicationInfo 字段:
dataDir
sourceDir
nativeLibraryDir
publicSourceDir
splitSourceDirs
splitPublicSourceDirs


6. 通知
此版本针对通知功能引入了下列 API 变更:
新增了 INTERRUPTION_FILTER_ALARMS 过滤级别,它对应于新增的“仅闹铃”免打扰模式。
新增了 CATEGORY_REMINDER 类别值,用于区分用户安排的提醒与其他事件 (CATEGORY_EVENT) 和闹铃 (CATEGORY_ALARM)。
新增了 Icon 类,您可以通过 setSmallIcon()方法和 setLargeIcon()方法将其附加到通知上。同理,addAction() 方法现在接受 Icon 对象,而不接受可绘制资源 ID。
新增了 getActiveNotifications() 方法,让您的应用能够了解哪些通知目前处于活动状态。要查看使用此功能的应用实现,请参阅 ActiveNotifications 示例。


7.改进的蓝牙低功耗扫描
如果您的应用执行蓝牙低功耗扫描,可以使用新增的 setCallbackType() 方法指定您只希望在下列条件下通知回调:首次找到与设置的 ScanFilter 匹配的播发数据包,或者已过很长时间后才再次看到该数据包。这种扫描方法与旧平台版本中提供的方法相比更加节能。

8.  Hotspot 2.0 第 1 版支持

9.  4K 显示模式

10.主题化 ColorStateList

对于运行 Android 6.0(API 级别 23)的设备,现在支持在 ColorStateList 中使用主题属性。Resources.getColorStateList() 方法和 Resources.getColor() 方法已弃用。如果您要调用这些 API,请改为调用新增的 Context.getColorStateList() 方法或 Context.getColor() 方法。还可在 v4 appcompat 库中通过 ContextCompat 使用这些方法。

11.视频功能

此版本为视频处理 API 添加了新功能,包括:

新增了 MediaSync 类,可帮助应用同步渲染音频流和视频流。音频缓冲区以非锁定方式提交,并通过回调返回。此外,它还支持动态回放速率。
新增了 EVENT_SESSION_RECLAIMED 事件,它表示应用打开的会话已被资源管理器收回。如果您的应用使用 DRM 会话,则应处理此事件,并确保不使用收回的会话。
新增了 ERROR_RECLAIMED 错误代码,它表示资源管理器收回了编解码器使用的媒体资源。出现此异常时,必须释放编解码器,因为它已转入终止状态。
新增了 getMaxSupportedInstances() 接口,用于获取有关支持的编解码器实例最大并发数量的提示。
新增了 setPlaybackParams() 方法,用于设置快动作回放或慢动作回放的媒体回放速率。此外,它还会随视频一起自动拉长或加速音频回放


12.低电耗模式限制
在低电耗模式下,您的应用会受到以下限制:

暂停访问网络。
系统将忽略 wake locks。
标准 AlarmManager 闹铃(包括 setExact() 和 setWindow())推迟到下一维护时段。
如果您需要设置在低电耗模式下触发的闹铃,请使用 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()。
一般情况下,使用 setAlarmClock() 设置的闹铃将继续触发 — 但系统会在这些闹铃触发之前不久退出低电耗模式。
系统不执行 Wi-Fi 扫描。
系统不允许运行同步适配器。
系统不允许运行 JobScheduler。


13. 了解应用待机模式
应用待机模式允许系统判定应用在用户未主动使用它时处于空闲状态。 当用户有一段时间未触摸应用时,系统便会作出此判定,以下条件均不适用:

用户显式启动应用。
应用当前有一个进程位于前台(表现为 Activity 或前台服务形式,或被另一 Activity 或前台服务占用)。
应用生成用户可在锁屏或通知托盘中看到的通知。
当用户将设备插入电源时,系统将从待机状态释放应用,从而让它们可以自由访问网络并执行任何待定作业和同步。 如果设备长时间处于空闲状态,系统将按每天大约一次的频率允许空闲应用访问网络。

14.在设备空闲时使用 GCM 与您的应用交互
Google Cloud Messaging (GCM) 是一项云端至设备的服务,允许您支持在后端服务与 Android 设备上的应用之间实时进行下游消息传递。GCM 提供了单一持久的云连接;所有需要实时传递消息的应用均可共享此连接。此共享连接使多个应用无需消耗电池即可维持自身单独的持久连接,避免快速耗尽电池,从而显著优化电池消耗。 因此,如果应用需要与后端服务进行消息传递集成,我们强烈建议您尽量使用 GCM,而非维持自身持久的网络连接。

GCM 经过优化,可通过高优先级 GCM 消息用于低电耗模式和应用待机模式。GCM 高优先级消息允许您可靠地唤醒应用访问网络,即使用户设备处于低电耗模式或应用处于应用待机模式也不例外。 在低电耗模式或应用待机模式下,系统将传递消息并允许应用临时访问网络服务和部分唤醒锁,然后将设备或应用恢复到空闲状态。

高优先级 GCM 消息不会影响低电耗模式,也不会影响任何其他应用的状态。这意味着您的应用可以使用这些消息进行有效的通信,同时尽可能减少对整个系统和设备的电池影响。

作为一项常规最佳做法,如果您的应用需要下游消息传递,则应使用 GCM。如果您的服务器和客户端已经使用 GCM,请确保服务对关键消息使用高优先级消息,因为即使设备处于低电耗模式,这也会可靠地唤醒应用


15.对其他用例的支持
通过妥善管理网络连接、闹铃、作业和同步并使用 GCM 高优先级消息,几乎所有应用都应该能够支持低电耗模式。对于一小部分用例,这可能还不够。 对于此类用例,系统为部分免除低电耗模式和应用待机模式优化的应用提供了一份可配置的白名单。

在低电耗模式和应用待机模式期间,加入白名单的应用可以使用网络并保留部分 wake locks。 不过,正如其他应用一样,其他限制仍然适用于加入白名单的应用。 例如,加入白名单的应用的作业和同步将推迟(在 API 级别 23 及更低级别中),并且其常规 AlarmManager 闹铃不会触发。通过调用 isIgnoringBatteryOptimizations(),应用可以检查自身当前是否位于豁免白名单中。

用户可以在 Settings > Battery > Battery Optimization 中手动配置该白名单。或者,系统会为应用提供请求用户将应用加入白名单的方式。

应用可以触发 ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS Intent,让用户直接进入 Battery Optimization,他们可以在其中添加应用。
具有 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 权限的应用可以触发系统对话框,让用户无需转到“设置”即可直接将应用添加到白名单。应用将通过触发 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS Intent 来触发该对话框。
用户可以根据需要手动从白名单中移除应用。
在请求用户将应用添加到白名单之前,请确保应用符合加入白名单的可接受用例。


16.在低电耗模式和应用待机模式下进行测试
为了确保用户获得极佳体验,您应在低电耗模式和应用待机模式下全面测试您的应用。

在低电耗模式下测试您的应用
您可按以下步骤测试低电耗模式:

使用 Android 6.0(API 级别 23)或更高版本的系统映像配置硬件设备或虚拟设备。
将设备连接到开发计算机并安装应用
运行应用并使其保持活动状态
关闭设备屏幕。(应用保持活动状态。)
通过运行以下命令强制系统在低电耗模式之间循环切换:
$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
您可能需要多次运行第二个命令。不断地重复,直到设备变为空闲状态。

在重新激活设备后观察应用的行为。确保应用在设备退出低电耗模式时正常恢复。
在应用待机模式下测试您的应用
要在应用待机模式下测试您的应用,请执行以下操作:

使用 Android 6.0(API 级别 23)或更高版本的系统映像配置硬件设备或虚拟设备。
将设备连接到开发计算机并安装应用
运行应用并使其保持活动状态
通过运行以下命令强制应用进入应用待机模式:
$ adb shell dumpsys battery unplug
$ adb shell am set-inactive <packageName> true
使用以下命令模拟唤醒应用:
$ adb shell am set-inactive <packageName> false
$ adb shell am get-inactive <packageName>
观察唤醒后的应用行为。确保应用从待机模式中正常恢复。 特别地,您应检查应用的通知和后台作业是否按预期继续运行

三、ANDROID 7.0

1.行为变更

 Android 7.0 包括旨在延长设备电池寿命和减少 RAM 使用的系统行为变更。这些变更可能会影响您的应用访问系统资源,以及您的应用通过特定隐式 intent 与其他应用交互的方式。

1.低电耗模式

Android 6.0(API 级别 23)引入了低电耗模式,当用户设备未插接电源、处于静止状态且屏幕关闭时,该模式会推迟 CPU 和网络活动,从而延长电池寿命。而 Android 7.0 则通过在设备未插接电源且屏幕关闭状态下、但不一定要处于静止状态(例如用户外出时把手持式设备装在口袋里)时应用部分 CPU 和网络限制,进一步增强了低电耗模式。


2. Project Svelte:后台优化

Android 7.0 移除了三项隐式广播,以帮助优化内存使用和电量消耗。此项变更很有必要,因为隐式广播会在后台频繁启动已注册侦听这些广播的应用。删除这些广播可以显著提升设备性能和用户体验。

移动设备会经历频繁的连接变更,例如在 WLAN 和移动数据之间切换时。目前,可以通过在应用清单中注册一个接收器来侦听隐式 CONNECTIVITY_ACTION 广播,让应用能够监控这些变更。由于很多应用会注册接收此广播,因此单次网络切换即会导致所有应用被唤醒并同时处理此广播。

同理,在之前版本的 Android 中,应用可以注册接收来自其他应用(例如相机)的隐式 ACTION_NEW_PICTURE 和 ACTION_NEW_VIDEO 广播。当用户使用相机应用拍摄照片时,这些应用即会被唤醒以处理广播。

为缓解这些问题,Android 7.0 应用了以下优化措施:

面向 Android 7.0 开发的应用不会收到 CONNECTIVITY_ACTION 广播,即使它们已有清单条目来请求接受这些事件的通知。在前台运行的应用如果使用 BroadcastReceiver 请求接收通知,则仍可以在主线程中侦听 CONNECTIVITY_CHANGE。
应用无法发送或接收 ACTION_NEW_PICTURE 或 ACTION_NEW_VIDEO 广播。此项优化会影响所有应用,而不仅仅是面向 Android 7.0 的应用。
如果您的应用使用任何 intent,您仍需要尽快移除它们的依赖关系,以正确适配 Android 7.0 设备。Android 框架提供多个解决方案来缓解对这些隐式广播的需求。例如,JobScheduler API 提供了一个稳健可靠的机制来安排满足指定条件(例如连入无限流量网络)时所执行的网络操作。您甚至可以使用 JobScheduler 来适应内容提供程序变化。

如需了解有关 Android N 中后台优化以及如何改写应用的详细信息,请参阅后台优化。

3.  权限更改

Android 7.0 做了一些权限更改,这些更改可能会影响您的应用。

系统权限更改

为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问 (0700)。此设置可防止私有文件的元数据泄漏,如它们的大小或存在性。此权限更改有多重副作用:

私有文件的文件权限不应再由所有者放宽,为使用 MODE_WORLD_READABLE 和/或 MODE_WORLD_WRITEABLE 而进行的此类尝试将触发 SecurityException。
注:迄今为止,这种限制尚不能完全执行。应用仍可能使用原生 API 或 File API 来修改它们的私有目录权限。但是,我们强烈反对放宽私有目录的权限。
传递软件包网域外的 file:// URI 可能给接收器留下无法访问的路径。因此,尝试传递 file:// URI 会触发 FileUriExposedException。分享私有文件内容的推荐方法是使用 FileProvider。
DownloadManager 不再按文件名分享私人存储的文件。
旧版应用在访问 COLUMN_LOCAL_FILENAME 时可能出现无法访问的路径。
面向 Android 7.0 或更高版本的应用在尝试访问 COLUMN_LOCAL_FILENAME 时会触发 SecurityException。
通过使用 DownloadManager.Request.setDestinationInExternalFilesDir() 或 DownloadManager.Request.setDestinationInExternalPublicDir() 将下载位置设置为公共位置的旧版应用仍可以访问 COLUMN_LOCAL_FILENAME 中的路径,但是我们强烈反对使用这种方法。对于由 DownloadManager 公开的文件,首选的访问方式是使用ContentResolver.openFileDescriptor()。


4.在应用间共享文件
对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。
要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类。如需了解有关权限和共享文件的详细信息,请参阅共享文件。


5.屏幕缩放
Android 7.0 支持用户设置显示尺寸,以放大或缩小屏幕上的所有元素,从而提升设备对视力不佳用户的可访问性。用户无法将屏幕缩放至低于最小屏幕宽度 sw320dp,该宽度是 Nexus 4 的宽度,也是常规中等大小手机的宽度。

6.无障碍改进
为提高平台对于视力不佳或视力受损用户的易用性,Android 7.0 做出了一些更改。这些更改一般并不要求更改您的应用代码,不过您应仔细检查并使用您的应用测试这些功能,以评估它们对用户体验的潜在影响.

7.NDK 应用链接至平台库
从 Android 7.0 开始,系统将阻止应用动态链接非公开 NDK 库,这种库可能会导致您的应用崩溃。此行为变更旨在为跨平台更新和不同设备提供统一的应用体验。即使您的代码可能不会链接私有库,但您的应用中的第三方静态库可能会这么做。因此,所有开发者都应进行相应检查,确保他们的应用不会在运行 Android 7.0 的设备上崩溃。如果您的应用使用原生代码,则只能使用公开 NDK API。

8.Android for Work
Android 7.0 包含一些针对面向 Android for Work 的应用的变更,包括对证书安装、密码重置、二级用户管理、设备标识符访问权限的变更。如果您是要针对 Android for Work 环境开发应用,则应仔细检查这些变更并相应地修改您的应用
                          

四、Android 8.0

1.行为变更

Android 8.0 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更。本文重点介绍您应该了解并在开发应用时加以考虑的一些主要变更。

其中大部分变更会影响所有应用,而不论应用针对的是何种版本的 Android。不过,有几项变更仅影响针对 Android 8.0 的应用。为清楚起见,本页面分为两个部分:针对所有 API 级别的应用和针对 Android 8.0 的应用。

针对所有 API 级别的应用

这些行为变更适用于 在 Android 8.0 平台上运行的 所有应用,无论这些应用是针对哪个 API 级别构建。所有开发者都应查看这些变更,并修改其应用以正确支持这些变更(如果适用)。

一.  后台执行限制

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

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

现在,在后台运行的应用对后台服务的访问受到限制。
应用无法使用其清单注册大部分隐式广播(即,并非专门针对此应用的广播)。
默认情况下,这些限制仅适用于针对 O 的应用。不过,用户可以从 Settings 屏幕为任意应用启用这些限制,即使应用并不是以 O 为目标平台。

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

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

多个 Android 应用和服务可以同时运行。 例如,用户可以在一个窗口中玩游戏,同时在另一个窗口中浏览网页,并使用第三个应用播放音乐。

同时运行的应用越多,对系统造成的负担越大。 如果还有应用或服务在后台运行,这会对系统造成更大负担,进而可能导致用户体验下降;例如,音乐应用可能会突然关闭。


(1)在很多情况下,您的应用都可以使用 JobScheduler 作业替换后台服务。 例如,CoolPhotoApp 需要检查用户是否已经从朋友那里收到共享的照片,即使该应用未在前台运行。

(2)在 Android 8.0 之前,创建前台服务的方式通常是先创建一个后台服务,然后将该服务推到前台。

Android 8.0 有一项复杂功能;系统不允许后台应用创建后台服务。 因此,Android 8.0 引入了一种全新的方法,即 Context.startForegroundService(),以在前台启动新服务。

在系统创建服务后,应用有五秒的时间来调用该服务的 startForeground() 方法以显示新服务的用户可见通知。

如果应用在此时间限制内未调用 startForeground(),则系统将停止服务并声明此应用为 ANR。

2.广播限制

如果应用注册为接收广播,则在每次发送广播时,应用的接收器都会消耗资源。 如果多个应用注册为接收基于系统事件的广播,这会引发问题;触发广播的系统事件会导致所有应用快速地连续消耗资源,从而降低用户体验。

为了缓解这一问题,Android 7.0(API 级别 25)对广播施加了一些限制,如后台优化中所述。

Android 8.0 让这些限制更为严格。

针对 Android 8.0 的应用无法继续在其清单中为隐式广播注册广播接收器。 隐式广播是一种不专门针对该应用的广播。 例如,ACTION_PACKAGE_REPLACED 就是一种隐式广播,因为它将发送到注册的所有侦听器,让后者知道设备上的某些软件包已被替换。

不过,ACTION_MY_PACKAGE_REPLACED 不是隐式广播,因为不管已为该广播注册侦听器的其他应用有多少,它都会只发送到软件包已被替换的应用。
应用可以继续在它们的清单中注册显式广播。
应用可以在运行时使用 Context.registerReceiver() 为任意广播(不管是隐式还是显式)注册接收器。
需要签名权限的广播不受此限制所限,因为这些广播只会发送到使用相同证书签名的应用,而不是发送到设备上的所有应用。
在许多情况下,之前注册隐式广播的应用使用 JobScheduler 作业可以获得类似的功能。

例如,一款社交照片应用可能需要不时地执行数据清理,并且倾向于在设备连接到充电器时执行此操作。

之前,应用已经在清单中为 ACTION_POWER_CONNECTED 注册了一个接收器;当应用接收到该广播时,它会检查清理是否必要。 为了迁移到 Android 8.0,应用将该接收器从其清单中移除。

应用将清理作业安排在设备处于空闲状态和充电时运行。

注:很多隐式广播当前均已不受此限制所限。 应用可以继续在其清单中为这些广播注册接收器,不管应用针对哪个 API 级别。 有关已豁免广播的列表,请参阅隐式广播例外。

3.迁移指南

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

您可能需要更新应用,使其符合新限制。

了解您的应用如何使用服务。 如果您的应用依赖某些在它处于空闲时于后台运行的服务,您需要替换这些服务。

可能的解决方法包括:

如果处于后台时您的应用需要创建一个前台服务,请使用新的 NotificationManager.startServiceInForeground()

方法,而不是创建一个后台服务,然后尝试将其推到前台。
如果服务容易被用户注意,请将其设为前台服务。 例如,播放音频的服务始终应为前台服务。

使用 NotificationManager.startServiceInForeground()

而不是 startService() 创建服务。
寻找一种使用计划作业实现服务功能的方式。 如果服务未在执行容易立即被用户注意到的操作,一般情况下,您都能够使用计划作业。
发生网络事件时,请使用 FCM 选择性地唤醒您的应用,而不是在后台轮询。
在应用正常处于前台之前,请推迟后台工作。
检查在您应用的清单中定义的广播接收器。 如果您的清单为显式广播声明了接收器,您必须予以替换。 可能的解决方法包括:

通过调用 Context.registerReceiver() 而不是在清单中声明接收器的方式在运行时创建接收器。
使用计划作业检查条件是否会触发隐式广播。

4. Android 后台位置限制
为降低功耗,无论应用的目标 SDK 版本为何,Android 8.0 都会对后台应用检索用户当前位置的频率进行限制。

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

为降低功耗,无论应用的目标 SDK 版本为何,Android 8.0 都会对后台应用检索用户当前位置的频率进行限制。

(1)系统会对前台应用和后台应用进行区分。应用满足以下任一条件即视为前台应用:

它具有可见的 Activity,无论 Activity 处于启动还是暂停状态。
它具有前台服务。
另一个前台应用通过绑定到应用的其中一个服务或使用应用的其中一个内容提供程序与应用相连。
如果以上所有条件均不满足,应用即视为后台应用。

(2)优化应用的位置行为

考虑在您的应用接收位置更新不频繁的情况下其后台运行用例是否根本无法成功。如果属于这种情况,您可以通过执行下列操作之一提高位置更新的检索频率:

将您的应用转至前台。
使用应用中的某个前台服务。激活此服务时,您的应用必须在通知区显示一个持续性的通知。
使用 Geofencing API 的元素(例如 GeofencingApi 接口),这些元素针对最大限度减少耗电进行了专门优化。
使用被动位置侦听器,它可以在后台应用加快位置请求频率时提高位置更新的接收频率。
注:如果您的应用需要访问的位置历史记录包含时间频繁更新,请使用批处理版本的 Fused Location Provider API 元素,例如 FusedLocationProviderApi 接口。当您的应用运行于后台时,此 API 会以高于非批处理版本 API 的频率接收用户的位置。但切记,您的应用批量接收更新的频率仍仅为每小时几次。

(3)受影响的 API

对后台应用位置检索行为的更改影响下列 API:

Fused Location Provider (FLP)
如果您的应用运行在后台,位置系统服务只会根据 Android 8.0 行为变更中定义的间隔,按每小时几次的频率为其计算新位置。即使您的应用请求进行更频繁的位置更新,也仍是如此。
如果您的应用运行在前台,与 Android 7.1.1(API 级别 25)相比,在位置采样率上不会有任何变化。
Geofencing
后台应用可以高于接收 Fused Location Provider 更新的频率接收地理围栏转换事件。
地理围栏事件的平均响应时间是大约每两分钟一次。
GNSS Measurements 和 GNSS Navigation Messages
当您的应用位于后台时,注册用于接收 GnssMeasurement 和 GnssNavigationMessage 输出的回调会停止执行。
Location Manager
提供给后台应用的位置更新只会根据 Android 8.0 行为变更中定义的间隔,按每小时几次的频率提供。

注:如果运行您的应用的设备安装了 Google Play 服务,强烈建议您改用 Fused Location Provider (FLP)。
WLAN 管理器
startScan() 方法对后台应用执行完整扫描的频率仅为每小时数次。如果不久之后后台应用再次调用此方法, WifiManager 类将提供上次扫描所缓存的结果。


2. Android 8.0 API变更


1. 通知

在 Android 8.0 中,我们已重新设计通知,以便为管理通知行为和设置提供更轻松和更统一的方式。这些变更包括:

Android 8.0 中的通知长按菜单。
图 1. 用户可以长按应用启动器图标以查看 Android 8.0 中的通知。

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


2.自动填充框架


帐号创建、登录和信用卡交易需要时间并且容易出错。在使用要求执行此类重复性任务的应用时,用户很容易遭受挫折。

Android 8.0 通过引入自动填充框架,简化了登录和信用卡表单之类表单的填写工作。在用户选择接受自动填充之后,新老应用都可使用自动填充框架。

您可以采取某些措施,优化您的应用使用此框架的方式。如需了解详细信息,请参阅自动填充框架概览。

3.自动调整 TextView 的大小

Android 8.0 允许您根据 TextView 的大小自动设置文本展开或收缩的大小。这意味着,在不同屏幕上优化文本大小或者优化包含动态内容的文本大小比以往简单多了。如需了解有关如何在 Android 8.0 中自动调整 TextView 的大小的详细信息,请参阅自动调整 TextView 的大小。

//ANDROID 8.0
<?xml version="1.0" encoding="utf-8"?>
<TextView
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:autoSizeTextType="uniform" />

//支持库使用app自定义属性可兼容到ANDROID 4.2

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <TextView
      android:layout_width="match_parent"
      android:layout_height="200dp"
      app:autoSizeTextType="uniform" />

</LinearLayout>

4 .自适应图标
Android 8.0 引入自适应启动器图标。自适应图标支持视觉效果,可在不同设备型号上显示为各种不同的形状。要了解如何创建自适应图标,请参阅自适应图标预览功能指南。

5.  最大屏幕纵横比    
Maximum aspect ratio, expressed as (longer dimension / shorter dimension) in decimal form. For example, if the maximum aspect ratio is 7:3, set value to 2.33.        
NOTE: This attribute is ignored if the activity has resizeableActivity set to true, since that means your activity supports any size.  
 如果为多窗口模式的Activity则Maximum aspect ratio属性将生效。
 
 6. 多显示器支持

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

注:如果 Activity 支持多窗口模式,则 Android 8.0 将为该 Activity 自动启用多显示器支持。您应测试您的应用,确保它在多显示器环境下可正常运行。

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

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

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

8. AnimatorSet

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

9.视图默认焦点

在 Android 8.0 中,您可以指定在(重新)创建的操作组件继续运行并且用户按下键盘导航键(例如 Tab 键)之后应接收焦点的 View。要应用“设为默认焦点”设置,请在包含界面元素的布局 XML 文件中将 View 元素的 android:focusedByDefault 属性设置为 true,或者将 true 传递至应用界面逻辑中的 setFocusedByDefault()。

10.JobScheduler 改进

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

JobScheduler 的更新包括:

您现在可以将工作队列与计划作业关联。要将一个工作项添加到作业的队列中,请调用 JobScheduler.enqueue()。当作业运行时,它可以将待定工作从队列中剥离并进行处理。这种功能可以处理之前需要启动后台服务(尤其是实现 IntentService 的服务)的许多用例。
您现在可以通过调用 JobInfo.Builder.setClipData() 的方式将 ClipData 与作业关联。利用此选项,您可以将 URI 权限授予与作业关联,类似于这些权限传递到 Context.startService() 的方式。您也可以将 URI 权限授予用于工作队列上的 intent。
计划作业现在支持多个新的约束条件:
JobInfo.isRequireStorageNotLow()
如果设备的可用存储空间非常低,作业将不会运行。
JobInfo.isRequireBatteryNotLow()
如果电池电量等于或低于临界阈值,作业将不会运行;临界阈值是指设备显示 Low battery warning 系统对话框的电量。
NETWORK_TYPE_METERED
作业需要一个按流量计费的网络连接,比如大多数移动数据网络数据套餐。

setRequiresBatteryNotLow
added in API level 26
public JobInfo.Builder setRequiresBatteryNotLow (boolean batteryNotLow)
Specify that to run this job, the device's battery level must not be low. This defaults to false. If true, the job will only run when the battery level is not low, which is generally the point where the user is given a "low battery" warning.

11 . 连接

WLAN 感知

Android 8.0 新增了对 WLAN 感知的支持,此技术基于周边感知联网 (NAN) 规范。在具有相应 WLAN 感知硬件的设备上,应用和附近设备可以通过 WLAN 进行搜索和通信,无需依赖互联网接入点。我们正在与硬件合作伙伴合作,以尽快将 WLAN 感知技术应用于设备。要了解有关如何将 WLAN 感知集成到您的应用中的信息,请参阅 WLAN 感知。

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

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

在尝试通过蓝牙、BLE 和 WLAN 与配套设备配对时,Android 8.0 提供的 API 允许您自定义配对请求对话框。如需了解详细信息,请参阅配套设备配对。

如需了解有关在 Android 上使用蓝牙的详细信息,请参阅蓝牙指南。有关对蓝牙所作的特定于 Android 8.0 的变更,请参阅 Android 8.0 行为变更页面的蓝牙部分。

13.  智能文本选择

在兼容设备上,Android 8.0 让应用可以帮助用户以更有意义的方式与文本交互。当用户长按某个实体中可识别格式的单词(例如某个地址或餐馆名称)时,系统会选中整个实体。用户会看到一个浮动工具栏,该工具栏包含可以处理所选文本实体的应用。例如,如果系统识别出某个地址,它可以将用户导向地图应用。
系统识别的实体包括地址、网址、电话号码和电子邮件地址。如需了解详细信息,请参阅 TextClassifier

14. 无障碍功能

Android 8.0 支持开发者使用以下无障碍功能创建自己的无障碍服务。如需了解有关如何让您的应用更便于访问的更多信息,请参阅无障碍功能。

15.  独立的音量调整

Android 8.0 引入了 STREAM_ACCESSIBILITY 音量类别,允许您单独控制无障碍服务音频输出的音量,而不会影响设备上的其他声音。
要使用这个新的流类型来控制无障碍服务音量,请在无障碍服务中设置 FLAG_ENABLE_ACCESSIBILITY_VOLUME 选项。然后,您可以使用 adjustStreamVolume() 更改设备的无障碍服务音频音量。

16.  提示文本
Android 8.0 包含可用于与文本可编辑对象的提示文本进行交互的多个函数:
isShowingHintText() 和 setShowingHintText() 函数分别显示和设置节点的当前文本内容是否表示节点的提示文本。如果节点不包含可编辑文本,则它不应包含提示文本。
要访问提示文本本身,请使用 getHintText()。即使某个对象当前未显示提示文本,系统也能成功调用 getHintText()。

17.  安全性与隐私
( 1 ) 权限
Android 8.0 引入了多个与电话有关的新权限:

ANSWER_PHONE_CALLS 允许您的应用通过编程方式接听呼入电话。要在您的应用中处理呼入电话,您可以使用 acceptRingingCall() 函数。
READ_PHONE_NUMBERS 权限允许您的应用读取设备中存储的电话号码。
这些权限均被划分为危险类别,属于 PHONE 权限组。

(2)新的帐号访问和 Discovery API
Android 8.0 对应用访问用户帐号的方式引入多项改进。对于由身份验证器管理的帐号,身份验证器在决定对应用隐藏帐号还是显示帐号时可以使用自己的策略。Android 系统跟踪可以访问特定帐号的应用。
在以前的 Android 版本中,想要跟踪用户帐号列表的应用必须获取有关所有帐号的更新,包括具有不相关类型的帐号。Android 8.0 添加了 addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]) 函数,其允许应用指定应接收帐号变更的帐号类型列表     

(3)Google Safe Browsing API
WebView 类现在添加了一个 Safe Browsing API 来增强网络浏览的安全性。如需了解详细信息,请参阅 Google Safe Browsing API。  

(4)更新构建配置

将 compileSdkVersion、buildToolsVersion、targetSdkVersion 和 Support Library 版本更新为下列版本:

android {
  compileSdkVersion 'android-O'
  buildToolsVersion '26.0.0-rc2'

  defaultConfig {
    targetSdkVersion 'O'
  }
  ...
}
dependencies {
  compile 'com.android.support:appcompat-v7:26.0.0-beta1'
}

// REQUIRED: Google's new Maven repo is required for the latest
// support library that is compatible with Android 8.0
repositories {
    maven {
        url 'https://maven.google.com'
    }
}


五、Android 9.0

行为变更

Android 9 利用人工智能技术,让手机可以为您提供更多帮助。现在,手机变得更智能、更快,并且还可以随着您的使用进行调整

1.  利用 Wi-Fi RTT 进行室内定位

Android 9 添加了对 IEEE 802.11mc Wi-Fi 协议(也称为 Wi-Fi Round-Trip-Time (RTT))的平台支持,从而让您的应用可以利用室内定位功能。

在运行 Android 9 且具有硬件支持的设备上,应用可以使用 RTT API 来测量与附近支持 RTT 的 Wi-Fi 接入点 (AP) 的距离。 设备必须已启用位置服务并开启 Wi-Fi 扫描(在 Settings > Location 下),同时您的应用必须具有 ACCESS_FINE_LOCATION 权限。

设备无需连接到接入点即可使用 RTT。 为了保护隐私,只有手机可以确定与接入点的距离;接入点无此信息。

如果您的设备测量与 3 个或更多接入点的距离,您可以使用一个多点定位算法来预估与这些测量值最相符的设备位置。 结果通常精准至 1 至 2 米。

通过这种精确性,您可以打造新的体验,例如楼内导航、基于精细位置的服务,如无歧义语音控制(例如,“打开这盏灯”),以及基于位置的信息(如 “此产品是否有特别优惠?”)。

2. 显示屏缺口支持
显示各种屏幕缺口尺寸的开发者选项界面
通过使用模拟器测试屏幕缺口。
Android 9 支持最新的全面屏,其中包含为摄像头和扬声器预留空间的屏幕缺口。 通过 DisplayCutout 类可确定非功能区域的位置和形状,这些区域不应显示内容。 要确定这些屏幕缺口区域是否存在及其位置,请使用 getDisplayCutout() 函数。
全新的窗口布局属性 layoutInDisplayCutoutMode 让您的应用可以为设备屏幕缺口周围的内容进行布局。 您可以将此属性设为下列值之一:

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
可以按以下方法在任何运行 Android 9 的设备或模拟器上模拟屏幕缺口:

启用开发者选项。
在 Developer options 屏幕中,向下滚动至 Drawing 部分并选择 Simulate a display with a cutout。
选择屏幕缺口的大小。
注:我们建议您通过使用运行 Android 9 的设备或模拟器测试屏幕缺口周围的内容显示

3. 通知
Android 9 引入了多个通知增强功能,可供以 API 级别 28 及以上版本作为目标平台的开发者使用

将回复另存为草稿:当用户无意中关闭一个短信通知时,您的应用可以检索系统发送的 EXTRA_REMOTE_INPUT_DRAFT。 您可以使用此 extra 预填充应用中的文本字段,以便用户可以完成他们的回复。

确定对话是否为群组对话。您可以使用 setGroupConversation() 以明确确定对话是否为群组对话。

为 Intent 设置语义操作:setSemanticAction() 函数允许您为操作提供语义含义,如“标记为已读”、“删除”和“回复”等。

SmartReply:Android 9 支持在您的短信应用中提供相同的建议回复。 使用 RemoteInput.setChoices() 为用户提供一组标准回复。


4. 多摄像头支持和摄像头更新
在运行 Android 9 的设备上,您可以通过两个或更多物理摄像头来同时访问多个视频流。] 在配备双前置摄像头或双后置摄像头的设备上,您可以创建只配备单摄像头的设备所不可能实现的创新功能,例如无缝缩放、背景虚化和立体成像。 通过该 API,您还可以调用逻辑或融合的摄像头视频流,该视频流可在两个或更多摄像头之间自动切换。

摄像头方面的其他改进还包括附加会话参数和 Surface 共享,前者有助于降低首次拍照期间的延迟,而后者则让摄像头客户端能够处理各种用例,而无需停止并启动摄像头视频流。 我们还针对基于显示屏的 flash 支持和 OIS 时间戳访问新增了一些 API,用以实现应用级的图像稳定化和特效。

在 Android 9 中,多摄像头 API支持单色摄像头,适用于具有 FULL 或 LIMITED 功能的设备。 单色输出通过 YUV_420_888 格式实现,Y 为灰度,U (Cb) 为 128,V (Cr) 为 128。

在受支持的设备上,Android 9 还支持外置 USB/UVC 摄像头。

5. 动画
Android 9 引入了 AnimatedImageDrawable 类,用于绘制和显示 GIF 和 WebP 动画图像


6.HDR VP9 视频、HEIF 图像压缩和 Media API
Android 9 新增了对 High Dynamic Range (HDR) VP9 Profile 2 的内置支持,因此,现在您可以在支持 HDR 的设备上为用户提供来自 YouTube、Play Movies 和其他来源的采用 HDR 的影片。


7.JobScheduler 中的流量费用敏感度
从 Android 9 开始,JobScheduler 可以使用运营商提供的网络状态信号来改善与网络有关的作业处理。

作业可以声明其预估的数据大小、信号预提取,并指定具体的网络要求。 JobScheduler 然后根据网络状态管理工作。 例如,当网络显示拥塞时,JobScheduler 可能会延迟较大的网络请求。 如果使用的是不按流量计费的网络,则 JobScheduler 可运行预提取作业以提升用户体验(例如预提取标题)。

添加作业时,确保使用 setEstimatedNetworkBytes()、setPrefetch() 和 setRequiredNetwork()(如果适用),以帮助 JobScheduler 正确处理工作。 在执行作业时,请确保使用 JobParameters.getNetwork() 返回的 Network 对象。 否则,您将隐式使用设备的默认网络,其可能不符合您的要求,从而导致意外的流量消耗。

8.自动填充框架
Android 9 引入了多项改进,自动填充服务可以利用这些改进进一步增强用户填写表单时的体验。 如需详细了解如何在您的应用中使用自动填充功能,请参阅自动填充框架指南。

9.安全增强功能
Android 9 引入了若干安全功能,详见以下各节摘要说明:

Android Protected Confirmation
运行 Android 9 或更高版本的受支持设备赋予您使用 Android Protected Confirmation 的能力。 使用该工作流时,您的应用会向用户显示提示,请他们批准一个简短的声明。 应用可以通过这个声明再次确认,用户确实想完成一项敏感事务,例如付款。

如果用户接受该声明,Android 密钥库会收到并存储由密钥哈希消息身份验证代码 (HMAC) 保护的加密签名。 Android 密钥库确认消息的有效性之后,您的应用可以使用在可信执行环境 (TEE) 下通过 trustedConfirmationRequired 生成的密钥来签署用户已接受的消息。 该签名具有很高的可信度,它表示用户已看过声明并同意其内容。

注意:Android Protected Confirmation 不会为用户提供安全信息通道。 应用无法承担 Android 平台所提供机密性保证之外的任何其他保证。 尤其是,请勿使用该工作流显示您通常不会显示在用户设备上的敏感信息。

如需获得 Android Protected Confirmation 新增支持方面的指导,请参阅 Android Protected Confirmation 指南。

统一生物识别身份验证对话框
在 Android 9 中,系统代表您的应用提供生物识别身份验证对话框。 该功能可创建标准化的对话框外观、风格和位置,让用户更加确信,他们在使用可信的生物识别凭据检查程序进行身份验证。

如果您的应用使用 FingerprintManager 向用户显示指纹身份验证对话框,请切换到改用 BiometricPrompt。 BiometricPrompt 依赖系统来显示身份验证对话框。 它还会改变其行为,以适应用户所选择的生物识别身份验证类型。

注:在应用中使用 BiometricPrompt 之前,应该先使用 hasSystemFeature()函数以确保设备支持 FEATURE_FINGERPRINT、FEATURE_IRIS 或 FEATURE_FACE。

如果设备不支持生物识别身份验证,可以回退为使用 createConfirmDeviceCredentialIntent() 函数验证用户的 PIN 码、图案或密码。

硬件安全性模块
运行 Android 9 或更高版本的受支持设备可拥有 StrongBox Keymaster,它是位于硬件安全性模块中的 Keymaster HAL 的一种实现。 该模块包含以下组成部分:

自己的 CPU。
安全存储空间。
真实随机数生成器。
可抵御软件包篡改和未经授权线刷应用的附加机制。
检查存储在 StrongBox Keymaster 中的密钥时,系统会通过可信执行环境 (TEE) 证实密钥的完整性。

如需了解有关使用 Strongbox Keymaster 的更多信息,请参阅硬件安全性模块。

10.无障碍功能
Android 9 引入了针对无障碍功能框架的增强功能,让您能够更轻松地为应用的用户提供更好的体验。

11.DEX 文件的 ART 提前转换
在运行 Android 9 或更高版本的设备上,Android 运行时 (ART) 提前编译器通过将应用软件包中的 DEX 文件转换为更紧凑的表示形式,进一步优化了压缩的 Dalvik Executable 格式 (DEX) 文件。 此项变更可让您的应用启动更快并消耗更少的磁盘空间和内存。

这种改进特别有利于磁盘 I/O 速度较慢的低端设备

12.设备端系统跟踪
Android 9 允许您通过设备记录系统跟踪记录,然后与您的开发团队分享这些记录的报告。 该报告支持多种格式,包括 HTML。

通过收集这些跟踪记录,您可以获取与应用进程和线程相关的计时数据,并查看其他类型的具有全局意义的设备状态。

注:您无需设置您的代码来记录跟踪记录,但这样做可以帮助您查看应用代码的哪些部分可能会导致线程挂起或界面卡顿。

Android 9.0行为变更:所有应用
1. 后台对传感器的访问受限
Android 9 限制后台应用访问用户输入和传感器数据的能力。 如果您的应用在运行 Android 9 设备的后台运行,系统将对您的应用采取以下限制:

您的应用不能访问麦克风或摄像头。
使用连续报告模式的传感器(例如加速度计和陀螺仪)不会接收事件。
使用变化或一次性报告模式的传感器不会接收事件。
如果您的应用需要在运行 Android 9 的设备上检测传感器事件,请使用前台服务。

2.限制访问通话记录
Android 9 引入 CALL_LOG 权限组并将 READ_CALL_LOG、WRITE_CALL_LOG 和 PROCESS_OUTGOING_CALLS 权限移入该组。 在之前的 Android 版本中,这些权限位于 PHONE 权限组。

对于需要访问通话敏感信息(如读取通话记录和识别电话号码)的应用,该 CALL_LOG 权限组为用户提供了更好的控制和可见性。

如果您的应用需要访问通话记录或者需要处理去电,则您必须向 CALL_LOG 权限组明确请求这些权限。 否则会发生 SecurityException。

注:因为这些权限已变更组并在运行时授予,用户可以拒绝您的应用访问通话记录信息。 在这种情况下,您的应用应该能够妥善处理无法访问信息的状况。

如果您的应用已经遵循运行时权限最佳做法,则可以处理权限组的变更

3.限制访问电话号码
在未首先获得 READ_CALL_LOG 权限的情况下,除了应用的用例需要的其他权限之外,运行于 Android 9 上的应用无法读取电话号码或手机状态。

与来电和去电关联的电话号码可在手机状态广播(比如来电和去电的手机状态广播)中看到,并可通过 PhoneStateListener 类访问。 但是,如果没有 READ_CALL_LOG 权限,则 PHONE_STATE_CHANGED 广播和 PhoneStateListener 提供的电话号码字段为空。

要从手机状态中读取电话号码,请根据您的用例更新应用以请求必要的权限:

要通过 PHONE_STATE Intent 操作读取电话号码,同时需要 READ_CALL_LOG 权限和 READ_PHONE_STATE 权限。
要从 onCallStateChanged() 中读取电话号码,只需要 READ_CALL_LOG 权限。 不需要 READ_PHONE_STATE 权限。

4.对使用非 SDK 接口的限制

为帮助确保应用稳定性和兼容性,此平台对某些非 SDK 函数和字段的使用进行了限制;无论您是直接访问这些函数和字段,
还是通过反射或 JNI 访问,这些限制均适用。 在 Android 9 中,
您的应用可以继续访问这些受限的接口;该平台通过 toast 和日志条目提醒您注意这些接口。 如果您的应用显示这样的 toast,
则必须寻求受限接口之外的其他实现策略。 如果您认为没有可行的替代策略,您可以提交错误以请求重新考虑此限制

5.现在强制执行 FLAG_ACTIVITY_NEW_TASK 要求
在 Android 9 中,您不能从非 Activity 环境中启动 Activity,除非您传递 Intent 标志 FLAG_ACTIVITY_NEW_TASK。 如果您尝试在不传递此标志的情况下启动 Activity,则该 Activity 不会启动,系统会在日志中输出一则消息。

6.屏幕旋转变更
从 Android 9 开始,对纵向旋转模式做出了重大变更。 在 Android 8.0(API 级别 26)中,用户可以使用 Quicksettings 图块或 Display 设置在自动屏幕旋转和纵向旋转模式之间切换。 纵向模式已重命名为旋转锁定,它会在自动屏幕旋转关闭时启用。 自动屏幕旋转模式没有任何变更。

当设备处于旋转锁定模式时,用户可将其屏幕锁定到顶层可见 Activity 所支持的任何旋转。 Activity 不应假定它将始终以纵向呈现。 如果顶层 Activity 可在自动屏幕旋转模式下以多种旋转呈现,则应在旋转锁定模式下提供相同的选项,根据 Activity 的 screenOrientation 设置,允许存在一些例外情况(见下表)。

请求特定屏幕方向(例如,screenOrientation=landscape)的 Activity 会忽略用户锁定首选项,并且行为与 Android 8.0 中的行为相同。

可在 Android Manifest 中,或以编程方式通过 setRequestedOrientation() 在 Activity 级别设置屏幕方向首选项。

旋转锁定模式通过设置 WindowManager 在处理 Activity 旋转时使用的用户旋转首选项来发挥作用。 用户旋转首选项可能在下列情况下发生变更。 请注意,恢复设备的自然旋转存在偏差,对于外形与手机类似的设备通常设置为纵向:

当用户接受旋转建议时,旋转首选项变为建议方向。
当用户切换到强制纵向应用(包括锁定屏幕或启动器)时,旋转首选项变为纵向。
下表总结了常见屏幕方向的旋转行为:

屏幕方向    行为
未指定、user    在自动屏幕旋转和旋转锁定下,Activity 可以纵向或横向(以及颠倒纵向或横向)呈现。 预期同时支持纵向和横向布局。
userLandscape    在自动屏幕旋转和旋转锁定下,Activity 可以横向或颠倒横向呈现。 预期只支持横向布局。
userPortrait    在自动屏幕旋转和旋转锁定下,Activity 可以纵向或颠倒纵向呈现。 预期只支持纵向布局。
fullUser    在自动屏幕旋转和旋转锁定下,Activity 可以纵向或横向(以及颠倒纵向或横向)呈现。 预期同时支持纵向和横向布局。

旋转锁定用户将可选择锁定到颠倒纵向,通常为 180o。
sensor、fullSensor、sensorPortrait、sensorLandscape    忽略旋转锁定模式首选项,视为自动屏幕旋转已启用。 请仅在例外情况下并经过仔细的用

7.Apache HTTP 客户端弃用影响采用非标准 ClassLoader 的应用
在 Android 6.0 中,我们取消了对 Apache HTTP 客户端的支持。
此变更对大多数不以 Android 9 或更高版本为目标的应用没有任何影响。 不过,此变更会影响使用非标准 ClassLoader 结构的某些应用,即使这些应用不以 Android 9 或更高版本为目标平台。
如果应用使用显式委托到系统 ClassLoader 的非标准 ClassLoader,则应用会受到影响。
 在 org.apache.http.* 中查找类时,这些应用需要委托给应用 ClassLoader。 如果它们委托给系统 ClassLoader,则应用在 Android 9 或更高版本上将失败并显示 NoClassDefFoundError,因为系统 ClassLoader 不再识别这些类。 为防止将来出现类似问题,一般情况下,应用应通过应用 ClassLoader 加载类,而不是直接访问系统 ClassLoader。
 
 8.枚举相机
在 Android 9 设备上运行的应用可以通过调用 getCameraIdList() 发现每个可用的摄像头。 应用不应假定设备只有一个后置摄像头或只有一个前置摄像头。

例如,如果您的应用有一个用来切换前置和后置摄像头的按钮,则设备可能有多个前置或后置摄像头可供选择。 您应浏览一下摄像头列表,检查每个摄像头的特征,然后决定向用户显示哪些摄像头。


-----------------------------------------Android 9 targetSdkVersion 为28+ 应用行为变更----------------------------------------------------------
Android 9(API 级别 28)向 Android 系统引入了多项变更。 
以下行为变更仅影响以 API 28 或更高级别为目标的应用。 
将 targetSdkVersion 设为 API 28 或更高级别的应用必须进行修改,以便正确支持这些行为(如果适用)

1.前台服务
针对 Android 9 或更高版本并使用前台服务的应用必须请求 FOREGROUND_SERVICE 权限。 这是普通权限,因此,系统会自动为请求权限的应用授予此权限。

如果针对 Android 9 或更高版本的应用尝试创建一个前台服务且未请求 FOREGROUND_SERVICE,则系统会引发 SecurityException。

2.隐私权变更
如果您的应用以 Android 9 为目标平台,您应牢记以下行为变更。 对设备序列信息和 DNS 信息进行的这些更新可增强用户隐私保护。

构建序列号弃用
在 Android 9 中,Build.SERIAL 始终设置为 "UNKNOWN" 以保护用户的隐私。

如果您的应用需要访问设备的硬件序列号,您应改为请求 READ_PHONE_STATE 权限,然后调用 getSerial()。

3.DNS 隐私
以 Android 9 为目标平台的应用应采用私有 DNS API。 具体而言,当系统解析程序正在执行 DNS-over-TLS 时,应用应确保任何内置 DNS 客户端均使用加密的 DNS 查找与系统相同的主机名,或停用它而改用系统解析程序

4.Apache HTTP 客户端弃用
在 Android 6.0 中,我们取消了对 Apache HTTP 客户端的支持。 从 Android 9 开始,默认情况下该内容库已从 bootclasspath 中移除且不可用于应用。

要继续使用 Apache HTTP 客户端,以 Android 9 及更高版本为目标的应用可以向其 AndroidManifest.xml 添加以下内容:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>
注:拥有最低 SDK 版本 23 或更低版本的应用需要 android:required="false" 属性,因为在 API 级别低于 24 的设备上,org.apache.http.legacy 库不可用。 (在这些设备上,Apache HTTP 类在 bootclasspath 中提供。)

作为使用运行时 Apache 库的替代,应用可以在其 APK 中绑定自己的 org.apache.http 库版本。 如果进行此操作,您必须将该库重新打包(使用一个类似 Jar Jar 的实用程序)以避免运行时中提供的类存在类兼容性问题。

5.界面变更
视图焦点
0 面积的视图(即宽度或高度为 0)再也不能被聚焦。

此外,Activity 不再隐式分配触摸模式下的初始焦点。 而是由您显式请求初始焦点(如若需要的话)。

6.暂停应用的通知
在 Android 9 之前,暂停的应用发出的通知会被取消。 从 Android 9 开始,暂停的应用发出的通知将被隐藏,直至应用继续运行。

7.对非 SDK 接口的限制    现已禁止访问特定的非 SDK 接口,无论是直接访问,还是通过 JNI 或反射进行间接访问。尝试访问受限制的接口时,会生成 NoSuchFieldException 和 NoSuchMethodException 之类的错误。详情请参阅对非 SDK 接口的限制。
移除加密提供程序    从 Android 9 开始,Crypto JCA 提供程序已被移除。调用 SecureRandom.getInstance("SHA1PRNG", "Crypto") 将会引发 NoSuchProviderException。
更严格的 UTF-8 解码器    在 Android 9 中,针对 Java 语言的 UTF-8 解码器比以往更严格,并且遵循 Unicode 标准。
禁止空闲应用访问相机、麦克风和传感器    在应用处于空闲状态时,不能再访

8.前台服务权限    现在,想要使用前台服务的应用必须首先请求 FOREGROUND_SERVICE 权限。这是普通权限,因此,系统会自动为请求权限的应用授予此权限。在未获得此权限的情况下启动前台服务将会引发 SecurityException。
弃用 Bouncy Castle 加密    Android 9 弃用了几个来自 Bouncy Castle 提供程序中的加密技术,代之以由 Conscrypt 提供程序提供的加密技术。调用请求 Bouncy Castle 提供程序的 getInstance() 时,会生成 NoSuchAlgorithmException 错误。要解决这些错误,请不要在 getInstance() 中指定提供程序(也就是请求默认实现)。
移除对 Build.serial 的直接访问    现在,需要 Build.serial 标识符的应用必须请求 READ_PHONE_STATE 权限,然后使用 Android 9 中新增的新 Build.getSerial() 函数
不允许共享 WebView 数据目录    现在,不允许应用在不同进程之间共享一个 WebView 数据目录。如果您的应用有多个进程使用 WebView、CookieManager 或 android.webkit 软件包中的任何其他 API,则在第二个进程调用 WebView 函数时,您的应用将会崩溃。
SELinux 禁止访问应用的数据目录    系统强制每个应用的 SELinux 沙盒对每个应用的私有数据目录强制执行逐个应用的 SELinux 限制。现在,不允许直接通过路径访问其他应用的数据目录。应用可以继续使用进程间通信 (IPC) 机制(包括通过传递 F

猜你喜欢

转载自blog.csdn.net/gaoxiaoweiandy/article/details/83216001