Android各个版本的Feature变更

Posted 火山石

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android各个版本的Feature变更相关的知识,希望对你有一定的参考价值。

Android 8.0 相关变更
        后台执行限制改动默认只只针对Android8.0及以上,不过用户可以设置将该改动作用于任何应用。 处于后台的应用不在允许创建后台服务了,如果创建会抛出一个IllegalStateException异常。
        应用进入后台应用时会有一个时间窗,在该时间窗之内应用的后台服务还是在运行且可以创建后台服务,该事件窗口结束之后系统会将后台服务结束。
        应用在后台可以在任何时候通过NotificationManager.startServiceInForeground()创建前台服务,startService() 不能使用,bindService()没有限制。
        移除了大部分的隐式广播,只保留了少许隐式广播。保留的隐式广播
        主要是去除和应用本身无关的广播,例如ACTION_PACKAGE_REPLACED。只针对自己应用的广播还是有效,例如ACTION_MY_PACKAGE_REPLACED。
        官方建议使用 JobScheduler代替以上大部分需求场景。
        后台位置限制改动针对所有API级别 
处于后台的应用每隔几小时接收几次位置更新。
前台应用行为不变
官方建议使用前台服务、 Geofencing API 的元素(例如 GeofencingApi 接口)保证位置实时性。
提醒窗口变更针对android8.0及以上 
新增一个Window Type,TYPE_APPLICATION_OVERLAY。 
显示在 
TYPE_PHONE 
TYPE_PRIORITY_PHONE 
TYPE_SYSTEM_ALERT 
TYPE_SYSTEM_OVERLAY 
TYPE_SYSTEM_ERROR 
… 
这些窗口之上。
TYPE_APPLICATION_OVERLAY感觉是google 专门用来给开发者做悬浮窗的。
WebView 
        应用的 WebView 对象将在多进程模式下运行。网页内容在独立的进程中处理,此进程与包含应用的进程相隔离,以提高安全性。
        Android 自动填充框架提供对自动填充功能的内置支持,因此有关表单数据的保存、清楚、获取方法无效(WebSettings:getSaveFormData() setSaveFormData() 和 WebViewDatabase: clearFormData() hasFormData() )。
        ANDROID_ID 
        对于安装在运行 Android 8.0 的设备上的应用,ANDROID_ID 的值现在将根据应用签署密钥和用户确定作用域。应用签署密钥、用户和设备的每个组合都具有唯一的 ANDROID_ID 值。因此,在相同设备上运行但具有不同签署密钥的应用将不会再看到相同的 Android ID(即使对于同一用户来说,也是如此)
        权限申请变更只针对Android8.0及以上 
        之前动态申请权限的时候,如果用户同意了某个权限的申请,系统会将该权限同组的所有权限都授予给应用。8.0开始只会授予申请的那个权限,不过之后如果应用在申请之前授权权限同组的权限时,系统会自动授予不会提醒用户进行授权。
原生库变动针对 Android 8.0及以上 
        如果原生库包含任何可写且可执行的加载代码段,则不会再加载原生库。
        集合的处理变动针对 Android 8.0及以上 
为了利用优化的 List.sort(),在 Android 8.0 中,Collections.sort() 是在 List.sort() 的基础上实现的。

 

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

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

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

后台执行限制 
        Android O 为提高电池寿命而引入的变更之一是,当您的应用进入已缓存状态时,如果没有活动的组件,系统将解除应用具有的所有唤醒锁。

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

此类变更会影响以下 API:

Fused Location Provider (FLP) 
Geofencing 
GNSS Measurements 
Location Manager 
Android O 还对特定方法做出了以下变更:

        NotificationManager.startServiceInForeground() 方法将启动一个前台服务。启动前台服务的老办法将不再奏效。 
现在,如果针对 Android O 的应用尝试在限制服务的情况下使用 startService() 方法,则该方法将引发一个 IllegalStateException。 
为确保您的应用按预期方式运行,请完成以下步骤:

查看您的应用的逻辑,并确保您使用的是最新的位置 API。 
测试您的应用是否在每个用例中都表现出预期行为。 
考虑使用 Fused Location Provider (FLP) 或地理围栏来处理依赖于用户当前位置的用例。 
如需了解此类变更的详细信息,请参阅后台位置限制。

蓝牙 
        Android O 对 ScanRecord.getBytes() 方法检索的数据长度做出了以下变更:

        getBytes() 方法对于所接收的字节数不作任何假定。因此,应用不应受所返回的任何最小或最大字节数的影响。相反,应用应当计算所返回数组的长度。 
兼容蓝牙 5 的设备返回的数据长度可能会超出之前最大 60 个字节的限制。 
如果远程设备未提供扫描响应,则也可能返回少于 60 个字节的数据。 
输入和导航 
        随着 Android 应用出现在 Chrome 操作系统和平板电脑等其他大尺寸设备上,我们看到,用户在 Android 应用中又重新开始使用键盘导航。在 Android O 中,我们又再次使用键盘作为导航输入设备,从而为基于箭头和标签的导航构建了一种更可靠并且可预测的模型。

如需了解如何在您的应用中改善对键盘导航的支持,请阅读支持键盘导航指南。

无障碍功能 
现在,无障碍服务可识别应用的 TextView 对象内部的所有 ClickableSpan 实例。

如需了解有关如何让您的应用更便于访问的更多信息,请参阅无障碍功能。

安全性 
Android O 包含以下与安全性有关的变更:

此平台不再支持 SSLv3。 
在与未正确实现 TLS 协议版本协商的服务器建立 HTTPS 连接时,HttpsURLConnection 不再尝试回退到之前的 TLS 协议版本并重试的权宜方法。 
        Android O 将使用安全计算 (SECCOMP) 过滤器来过滤所有应用。允许的系统调用列表仅限于通过 bionic 公开的系统调用。此外,还提供了其他几个后向兼容的系统调用,但我们不建议使用这些系统调用。 
现在,您的应用的 WebView 对象将在多进程模式下运行。网页内容在独立的进程中处理,此进程与包含应用的进程相隔离,以提高安全性。 
如需了解与使用原生库有关的安全性增强的信息,请参阅原生库。 
有关提升应用安全性的其他准则,请参阅面向 Android 开发者的安全性。

隐私性 
Android O 对平台做出了以下与隐私性有关的变更。

现在,平台改变了标识符的处理方式。 
        现在,根据应用(而不是根据用户)来确定 ANDROID_ID 的值范围。应用软件包名称、签名、用户和设备的每个组合都具有唯一的 ANDROID_ID 值。同一个设备上运行的两个应用不再出现 Android ID 相同的情况,因此不可能建立关联。 
只要软件包名称和签名密钥相同,在软件包卸载或重新安装时 ANDROID_ID 的值不会改变。 
如果软件包签名密钥是因为更新而发生改变,那么,ANDROID_ID 的值不会改变。 
Widevine ID 的范围根据应用来确定。 
        对于在 OTA 之前安装的应用,除非卸载并重新安装,否则,ANDROID_ID 的值将保持不变。 
如果您要继续将 Android ID 用于与设备绑定的免费试用保护,您可以这么做。请确保软件包名称和签名相一致。 
要借助一个简单的标准系统实现应用获利,请使用广告 ID。广告 ID 是 Google Play 服务针对广告服务提供的唯一 ID,此 ID 可由用户重置。 
查询 net.hostname 系统属性返回的结果为空。 
您无法再假定 APK 驻留在名称以 -1 或 -2 结尾的目录中。应用应使用 sourceDir 获取此目录,而不能直接使用目录格式。 
网络连接和 HTTP(S) 连接 
Android O 对网络连接和 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 O 废除了此权宜方法;系统对格式错误的 URI 会返回 null。 
Android O 在实现 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 O 之前的版本,即使 send() 调用成功,后续的 recv() 调用也会引发 SocketException。为确保一致性,现在这两个调用均会引发 SocketException。 
在回退到 TCP Echo 协议之前,InetAddress.isReachable() 会尝试执行 ICMP。 
对于某些屏蔽端口 7 (TCP Echo) 的主机(例如 google.com),如果它们接受 ICMP Echo 协议,现在也许能够访问它们。 
对于确实无法访问的主机,此项变更意味着调用需要两倍的时间才能返回结果。 
记录未捕获的异常 
        如果某个应用安装的 Thread.UncaughtExceptionHandler 未移交给默认的 Thread.UncaughtExceptionHandler,则当出现未捕获的异常时,系统不会终止应用。从 Android O 开始,在此情况下系统将记录异常堆栈跟踪情况;在之前的平台版本中,系统不会记录异常堆栈跟踪情况。

       我们建议,自定义 Thread.UncaughtExceptionHandler 实现始终移交给默认处理程序处理;遵循此建议的应用不受 Android O 此项变更的影响。

集合的处理 
        现在,AbstractCollection.removeAll() 和 AbstractCollection.retainAll() 始终引发 NullPointerException;之前,当集合为空时不会引发 NullPointerException。此项变更使行为符合文档要求。

语言区域和国际化 
        Android 7.0(API 级别 24)引入能指定默认类别语言区域的概念,但是某些 API 在本应使用默认 DISPLAY 类别语言区域时,仍然使用不带参数的通用 Locale.getDefault() 方法。现在,在 Android O 中,以下方法使用 Locale.getDefault(Category.DISPLAY) 来代替 Locale.getDefault():

Currency.getDisplayName() 
Currency.getSymbol() 
Locale.getDisplayScript() 
当为 Locale 参数指定的 displayScript 值不可用时,Locale.getDisplayScript(Locale) 同样回退到 Locale.getDefault()。

与语言区域和国际化有关的其他变更如下:

        调用 Currency.getDisplayName(null) 会引发 NullPointerException,以与文档规定的行为保持一致。 
        改变了时区名称的分析方法。之前,Android 设备使用在启动时取样的系统时钟值,缓存用于分析日期时间的时区名称。因此,如果在启动时或其他较为罕见的情况下系统时钟出错,可能对分析产生负面影响。 
现在,一般情况下,在分析时区名称时分析逻辑将使用 ICU 和当前系统时钟值。此项变更可提供更加准确的结果,如果您的应用使用 SimpleDateFormat 等类,此结果可能与之前的 Android 版本不同。 
Android O 将 ICU 的版本更新至版本 58。 
联系人提供程序使用情况统计方法的变更 
        在之前版本的 Android 中,联系人提供程序组件允许开发者获取每个联系人的使用情况数据。此使用情况数据揭示了与某个联系人相关联的每个电子邮件地址和每个电话号码的信息,包括与该联系人联系的次数以及上次联系该联系人的时间。请求 READ_CONTACTS 权限的应用可以读取此数据。

        如果应用请求 READ_CONTACTS 权限,它们仍可以读取此数据。从 Android O 开始,使用情况数据查询会返回近似值,而不是精确值。不过,Android 系统内部仍然会保留精确值,因此,此变更不会影响 auto-complete API。

此行为变更会影响以下查询参数:

TIMES_CONTACTED 
TIMES_USED 
LAST_TIME_CONTACTED 
LAST_TIME_USED 
应用快捷键 
Android O 对应用快捷键做出了以下变更:

        com.android.launcher.action.INSTALL_SHORTCUT 广播不再会对您的应用有任何影响,因为它现在是私有的隐式广播。相反,    您应使用 ShortcutManager 类中的 requestPinShortcut() 方法创建应用快捷键。 
现在,ACTION_CREATE_SHORTCUT Intent 可以创建可使用 ShortcutManager 类进行管理的应用快捷键。此 Intent 还可以创建不与 ShortcutManager 交互的旧版启动器快捷键。在以前,此 Intent 只能创建旧版启动器快捷键。 
        现在,使用 requestPinShortcut() 创建的快捷键和在处理 ACTION_CREATE_SHORTCUT Intent 的 Activity 中创建的快捷键均已转换为功能齐全的应用快捷键。因此,应用现在可以使用 ShortcutManager 中的方法来更新这些快捷键。 
旧版快捷键仍然保留了它们在旧版 Android 中的功能,但您必须在应用中手动将它们转换成应用快捷键。 
如需了解有关应用快捷键变更的更多信息,请参阅固定快捷键和小部件预览功能指南。

提醒窗口 
如果应用使用 SYSTEM_ALERT_WINDOW 权限并且尝试使用以下窗口类型之一来在其他应用和系统窗口上方显示提醒窗口:

TYPE_PHONE 
TYPE_PRIORITY_PHONE 
TYPE_SYSTEM_ALERT 
TYPE_SYSTEM_OVERLAY 
TYPE_SYSTEM_ERROR 
…那么,这些窗口将始终显示在使用 TYPE_APPLICATION_OVERLAY 窗口类型的窗口下方。如果应用针对的是 Android O,则应用会使用 TYPE_APPLICATION_OVERLAY 窗口类型来显示提醒窗口。

如需了解详细信息,请参阅针对 Android O 的应用的行为变更内的提醒窗口的常用窗口类型部分。

企业中的 Android 
Android O 包含会影响企业应用的变更。如果您正在为企业构建应用,包括 DPC(设备规范控制器),您应查阅企业中的 Android 页面中介绍的变更,并相应修改您的应用。

针对 Android O 的应用 
        这些行为变更专门应用于针对 O 平台或更高平台版本的应用。针对 Android O 或更高平台版本进行编译,或将 targetSdkVersion 设为 Android O 或更高版本的应用开发者必须修改其应用以正确支持这些行为(如果适用)。

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

现在,在后台运行的应用对后台服务的访问受到限制。 
应用无法使用其清单注册大部分隐式广播(即,并非专门针对此应用的广播)。 
如需了解详细信息,请参阅后台执行限制。

安全性 
        如果您的应用的网络安全性配置选择退出对明文流量的支持,那么,您的应用的 WebView 对象无法通过 HTTP 访问网站。每个 WebView 对象必须转而使用 HTTPS。

有关提升应用安全性的其他准则,请参阅面向 Android 开发者的安全性。

隐私性 
以下变更影响 Android O 的隐私性。

        系统属性 net.dns1、net.dns2、net.dns3 和 net.dns4 不再可用,此项变更可加强平台的隐私性。 
要获取 DNS 服务器之类的网络连接信息,具有 ACCESS_NETWORK_STATE 权限的应用可以注册 NetworkRequest 或 NetworkCallback 对象。这些类在 Android 5.0(API 级别 21)及更高版本中提供。 
从 Android O 开始,不再支持 Build.SERIAL,此字段将返回一个未定义的值。需要知道硬件序列号的应用应改为使用新的 Build.getSerial() 方法,该方法要求具有 READ_PHONE_STATE 权限。 
        LauncherApps API 不再允许托管配置文件应用获取有关主配置文件的信息。当某个用户在托管配置文件中时,LauncherApps API 的行为就像同一配置文件组的其他配置文件中未安装任何应用一样。和之前一样,尝试访问无关联的配置文件会引发 SecurityExceptions。 
权限 
        在 Android O 之前,如果应用在运行时请求权限并且被授予该权限,系统会错误地将属于同一权限组并且在清单中注册的其他权限也一起授予应用。

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

        例如,假设某个应用在其清单中列出 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE。应用请求 READ_EXTERNAL_STORAGE,并且用户授予了该权限。如果该应用针对的是 API 级别 24 或更低级别,系统还会同时授予 WRITE_EXTERNAL_STORAGE,因为该权限也属于同一 STORAGE 权限组并且也在清单中注册过。如果该应用针对的是 Android O,则系统此时仅会授予 READ_EXTERNAL_STORAGE;不过,如果该应用后来又请求 WRITE_EXTERNAL_STORAGE,则系统会立即授予该权限,而不会提示用户。

媒体 
        框架会执行音频闪避。进行 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK 时,应用不会失去焦点。新的 API 适用于需要暂停而不是闪避的应用。不过,Android O 中未提供此行为。 
当用户打电话时,活动的媒体流将在通话期间静音。 
音频流类型应仅用于音量控制;所有其他流类型的使用(例如 AudioTrack 构造函数)仍有效,但系统会将其作为错误记录下来。 
        所有与音频相关的 API 均使用 AudioAttributes 来描述音频播放用例。 
        使用 AudioTrack 时,如果应用请求了足够大的音频缓冲区,则框架将尝试使用深度缓冲区输出(如果可用)。 
原生库 
        在针对 Android O 的应用中,如果原生库包含任何可写且可执行的加载代码段,则不会再加载原生库。倘若某些应用的原生库包含不正确的加载代码段,则此变更可能会导致这些应用停止工作。这是一种安全加强措施。

如需了解详细信息,请参阅可写且可执行的代码段。

        与早期的开发者预览版相同,Android O 还有助于更轻松地发现所有与链接器有关的问题。链接器的变更绑定到应用的目标 API 级别。如果应用的目标 API 级别发生链接器变更,则该应用无法加载该库。如果您的目标 API 级别低于发生链接器变更的 API 级别,则 logcat 会显示一条警告消息。在预览版期间,与链接器有关的问题不仅会显示在 logcat 中,也会以 toast 的形式显示。对于特定的 API 级别,警告可能会变成错误,此变更有助于提前发现此类问题。

集合的处理 
        在 Android O 中,Collections.sort() 是在 List.sort() 的基础上实现的。在 Android 7.x(API 级别 24 和 25)中,则恰恰相反。在过去,List.sort() 的默认实现会调用 Collections.sort()。

此项变更使 Collections.sort() 可以利用优化的 List.sort() 实现,但具有以下限制:

        List.sort() 的实现不能调用 Collections.sort(),因为这会导致堆栈因无限递归而溢出。相反,如果您需要 List 实现的默认行为,应避免重写 sort()。 
如果父类以不适当的方法实现 sort() ,通常最好使用在 List.toArray()、Arrays.sort() 和 ListIterator.set() 的基础上构建的实现重写 List.sort()。例如:

@Override
public void sort(Comparator<? super E> c)
  Object[] elements = toArray();
  Arrays.sort(elements, c);
  ListIterator<E> iterator = (ListIterator<Object>) listIterator();
  for (Object element : elements)
    iterator.next();
    iterator.set((E) element);
 


在大多数情况下,您也可以使用根据 API 级别委托给其他默认实现的实现重写 List.sort()。例如:

@Override
public void sort(Comparator<? super E> comparator)
  if (Build.VERSION.SDK_INT <= 25)
    Collections.sort(this);
  else
    super.sort(comparator);
 


        如果您选择后者只是因为您希望开发一种适用于所有 API 级别的 sort() 方法,可以考虑赋予其一个唯一的名称,例如 sortCompat(),而不是重写 sort()。 
        现在,Collections.sort() 只是对调用 sort() 的 List 实现进行的一项结构性修改。例如,在 Android O 之前的平台版本中,如果通过调用 List.sort() 进行排序,则当迭代处理 ArrayList 以及在迭代过程中调用 sort() 时,会引发 ConcurrentModificationException。而 Collections.sort() 则不会引发异常。 
此项变更使平台行为更加一致:现在,两种方法都会引发 ConcurrentModificationException。 
帐号访问和可检测性 
        除非身份验证器拥有用户帐号或用户授予访问权限,否则,应用将无法再访问用户帐号。仅拥有 GET_ACCOUNTS 权限尚不足以访问用户帐号。要获得帐号访问权限,应用应使用 AccountManager.newChooseAccountIntent() 或特定于身份验证器的方法。获得帐号访问权限后,应用可以调用 AccountManager.getAccounts() 来访问帐号。

        Android O 已弃用 LOGIN_ACCOUNTS_CHANGED_ACTION。相反,应用在运行时应使用 addOnAccountsUpdatedListener() 获取帐号更新信息。

        有关新增 API 和增加的帐号访问和可检测性方法的信息,请参阅此文档的“新增 API”部分中的帐号访问和可检测性。

提醒窗口 
        使用 SYSTEM_ALERT_WINDOW 权限的应用无法再使用以下窗口类型来在其他应用和系统窗口上方显示提醒窗口:

TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR

相反,应用必须使用名为 TYPE_APPLICATION_OVERLAY 的新窗口类型。

使用 TYPE_APPLICATION_OVERLAY 窗口类型显示应用的提醒窗口时,请记住新窗口类型的以下特性:

        应用的提醒窗口始终显示在状态栏和输入法等关键系统窗口的下面。 
        系统可以移动使用 TYPE_APPLICATION_OVERLAY 窗口类型的窗口或调整其大小,以改善屏幕显示效果。 
通过打开通知栏,用户可以访问设置来阻止应用显示使用 TYPE_APPLICATION_OVERLAY 窗口类型显示的提醒窗口。 
内容变更通知 
Android O 更改了 ContentResolver.notifyChange() 和 registerContentObserver(Uri, boolean, ContentObserver) 在面向针对 Android O 的应用中的行为方式。

现在,这些 API 需要在所有 URI 中为颁发机构定义一个有效的 ContentProvider。使用相关权限定义一个有效的 ContentProvider 可帮助您的应用防范来自恶意应用的内容变更,并防止将可能的私密数据泄露给恶意应用。
 

Android 6.0 变更

运行时权限
低电耗模式和应用待机模式
取消支持 Apache HTTP 客户端
BoringSSL
硬件标识符访问权
通知
音频管理器变更
文本选择
浏览器书签变更
Android 密钥库变更
WLAN 和网络连接变更
相机服务变更
运行时
APK 验证
USB 连接
Android for Work 变更
API 差异
API 级别 22 至 23 »

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

如果您之前发布过 Android 应用,请注意您的应用可能受到这些平台变更的影响。

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

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

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

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

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

取消支持 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'

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

硬件标识符访问权
        为给用户提供更严格的数据保护,从此版本开始,对于使用 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 地址。

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

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

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

文本选择

        现在,当用户在您的应用中选择文本时,您可以在一个浮动工具栏中显示“剪切”、“复制”和“粘贴”等文本选择操作。其在用户交互实现上与为单个视图启用上下文操作模式中所述的上下文操作栏类似。

要实现可用于文本选择的浮动工具栏,请在您的现有应用中做出以下更改:

        在 View 对象或 Activity 对象中,将 ActionMode 调用从 startActionMode(Callback)更改为 startActionMode(Callback, ActionMode.TYPE_FLOATING)。改为使用 ActionMode.Callback 的现有实现扩展 ActionMode.Callback2。
替代 onGetContentRect() 方法,用于提供 Rect 内容对象(如文本选择矩形)在视图中的坐标。
如果矩形的定位不再有效,并且这是唯一需要声明为无效的元素,请调用 invalidateContentRect() 方法。
        请注意,如果您使用 Android 支持库 22.2 修订版,浮动工具栏不向后兼容,默认情况下 appcompat 会获得对 ActionMode 对象的控制权。这会禁止显示浮动工具栏。要在 ActionMode 中启用 AppCompatActivity 支持,请调用 getDelegate(),然后对返回的 setHandleNativeActionModesEnabled() 对象调用 AppCompatDelegate,并将输入参数设置为 false。此调用会将 ActionMode 对象的控制权交还给框架。在运行 Android 6.0(API 级别 23)的设备上,框架可以支持 ActionBar 模式或浮动工具栏模式;而在运行 Android 5.1(API 级别 22)或之前版本的设备上,框架仅支持 ActionBar 模式。

浏览器书签变更
        此版本移除了对全局书签的支持。android.provider.Browser.getAllBookmarks() 和 android.provider.Browser.saveBookmark() 方法现已移除。同样,READ_HISTORY_BOOKMARKS 权限和 WRITE_HISTORY_BOOKMARKS 权限也已移除。如果您的应用以 Android 6.0(API 级别 23)或更高版本为目标平台,请勿从全局提供程序访问书签或使用书签权限。您的应用应改为在内部存储书签数据。

Android 密钥库变更
        从此版本开始,Android 密钥库提供程序不再支持 DSA。但仍支持 ECDSA。

        停用或重置安全锁定屏幕时(例如,由用户或设备管理员执行此类操作时),系统将不再删除需要闲时加密的密钥,但在上述事件期间会删除需要闲时加密的密钥。

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

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

        根据客户端应用进程的“优先级”授予对相机子系统资源的访问权,包括打开和配置相机设备。带有对用户可见 Activity 或前台 Activity 的应用进程一般会被授予较高的优先级,从而使相机资源的获取和使用更加可靠;
        当高优先级的应用尝试使用相机时,系统可能会“驱逐”正在使用相机客户端的低优先级应用。在已弃用的 Camera API 中,这会导致系统为被驱逐的客户端调用 onError()。在 Camera2 API 中,这会导致系统为被驱逐的客户端调用 onDisconnected();
在配备相应相机硬件的设备上,不同的应用进程可同时独立打开和使用不同的相机设备。但现在,如果在多进程用例中同时访问相机会造成任何打开的相机设备的性能或能力严重下降,相机服务会检测到这种情况并禁止同时访问。即使并没有其他应用直接尝试访问同一相机设备,此变更也可能导致低优先级客户端被“驱逐”。
        更改当前用户会导致之前用户帐户拥有的应用内活动相机客户端被驱逐。对相机的访问仅限于访问当前设备用户拥有的用户个人资料。举例来说,这意味着,当用户切换到其他帐户后,“来宾”帐户实际上无法让使用相机子系统的进程保持运行状态。
运行时
        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) 调用返回的问题描述文本。要详细了解如何处理文本重定位,请参阅此指南。

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

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

Android for Work 变更
此版本包含下列针对 Android for Work 的行为变更:

个人上下文中的工作联系人。Google 拨号器通话记录现在会在用户查看通话记录时显示工作联系人。将 setCrossProfileCallerIdDisabled() 设置为 true 可在 Google 拨号器通话记录中隐藏托管配置文件联系人。仅当您将 setBluetoothContactSharingDisabled() 设置为 false 时,才可以通过蓝牙将工作联系人随个人联系人一起显示给设备。默认情况下,它设置为 true。
        WLAN 配置删除:现在,当删除某个托管配置文件时,将会移除由配置文件所有者添加的 WLAN 配置(例如,通过调用 addNetwork() 方法添加的配置)。
        WLAN 配置锁定:如果 WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN 不为零,则用户无法再修改或删除任何由活动设备所有者创建的 WLAN 配置。用户仍可创建和修改其自己的 WLAN 配置。活动设备所有者拥有编辑或删除任何 WLAN 配置(包括并非由其创建的配置)的权限。
        通过添加 Google 帐户下载设备规范控制器:向托管环境以外的设备添加需要通过设备规范控制器 (DPC) 应用管理的 Google 帐户时,帐户添加流程现在会提示用户安装相应的 WPC。在设备初始设置向导中通过 Settings > Accounts 添加帐户时,也会出现此行为。
对特定 DevicePolicyManager API 行为的变更:
        调用 setCameraDisabled() 方法只会影响调用该方法的用户的相机;从托管配置文件调用它不会影响主用户运行的相机应用。此外,setKeyguardDisabledFeatures() 方法现在除了可供设备所有者使用外,还可供配置文件所有者使用。
配置文件所有者可设置以下键盘锁限制:
KEYGUARD_DISABLE_TRUST_AGENTS 和 KEYGUARD_DISABLE_FINGERPRINT,它们影响配置文件上级用户的键盘锁设置。
KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS,它只影响应用在托管配置文件中生成的通知。
DevicePolicyManager.createAndInitializeUser() 方法和 DevicePolicyManager.createUser() 方法已弃用。
当给定用户的应用在前台运行时,setScreenCaptureDisabled() 方法现在也会屏蔽辅助结构。
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM 现在默认为 SHA-256。出于向后兼容性考虑,仍然支持 SHA-1,但未来将会取消该支持。EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM 现在只接受 SHA-256。
Android 6.0(API 级别 23)中曾经存在的 Device initializer API 现已删除
EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS 已删除,因此 NFC 占位配置无法通过编程解锁受恢复出厂设置保护的设备
您现在可以使用 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE extra 在对托管设备进行 NFC 配置期间向设备所有者应用传递数据。
Android for Work API 针对 M 运行时权限(包括 Work 配置文件、辅助层及其他内容)进行了优化。新增的 DevicePolicyManager 权限 API 不会影响 M 之前版本的应用。
当用户退出通过 ACTION_PROVISION_MANAGED_PROFILE 或 ACTION_PROVISION_MANAGED_DEVICE intent 发起的设置流程的同步部分时,系统现在会返回 RESULT_CANCELED 结果代码。
对其他 API 的变更:
流量消耗:android.app.usage.NetworkUsageStats 类已重命名为 NetworkStats。
对全局设置的变更:
这些设置不再通过 setGlobalSettings() 进行设置:
BLUETOOTH_ON
DEVELOPMENT_SETTINGS_ENABLED
MODE_RINGER
NETWORK_PREFERENCE
WIFI_ON
这些全局设置现在可通过 setGlobalSettings() 进行设置:
WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN
 


 

以上是关于Android各个版本的Feature变更的主要内容,如果未能解决你的问题,请参考以下文章

Android7.0 之 行为变更

android 7.0低电耗Doze模式

android 7.0变化

Android 进阶——性能优化之电量优化全攻略及实战小结

Android 进阶——性能优化之电量优化全攻略及实战小结

Android 进阶——性能优化之电量优化全攻略及实战小结