广播
Android N为优化内存使用和电量消耗,移除部分隐式广播:
- CONNECTIVITY_ACTION :网络变化 (不能静态注册,动态注册还可以)
- ACTION_NEW_PICTURE :添加新图片
- ACTION_NEW_VIDEO : 添加新视频
Android O做了更进一步的优化:
针对 Android O 的应用无法继续在其清单中为隐式广播注册广播接收器。 隐式广播是一种不专门针对该应用的广播。 例如,ACTION_PACKAGE_REPLACED 就是一种隐式广播,因为它将发送到注册的所有侦听器,让后者知道设备上的某些软件包已被替换。 不过,ACTION_MY_PACKAGE_REPLACED不是隐式广播,因为不管已为该广播注册侦听器的其他应用有多少,它都会只发送到软件包已被替换的应用。
应用可以继续在它们的清单中注册显式广播。
应用可以在运行时使用 [Context.registerReceiver()](https://developer.android.com/reference/android/content/Context.html#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter)) 为任意广播(不管是隐式还是显式)注册接收器。
注1:这些限制仅适用于针对 Android O 的应用。 针对 API 级别 25 或更低级别的应用不受影响。
注2:很多隐式广播当前均已不受此限制所限。 应用可以继续在其清单中为这些广播注册接收器,不管应用针对哪个 API 级别。 有关已豁免广播的列表,请参阅隐式广播例外。
虽然上面android o的第一条优化只有在targetSdkVersion >=26才能生效,但随着android对后台任务、广播的进一步收紧,最好从现在起就不要使用静态注册的广播。相关的需求,可以考虑使用Android L推出的JobScheduler
来实现(JobScheduler只支持Android L以及以上的系统,如果你的app的minSdkVersion小于21,则有类似API的库提供向后兼容,正式推荐的是FirebaseJobDispatcher。)
Android O的后台服务改动
系统可以区分 前台 和 后台 应用。 (用于服务限制目的的后台定义与内存管理使用的定义不同;一个应用按照内存管理的定义可能处于后台,但按照能够启动服务的定义又处于前台。)如果满足以下任意条件,应用将被视为处于前台:
- 具有可见 Activity(不管该 Activity 已启动还是已暂停)。
- 具有前台服务。
- 另一个前台应用已关联到该应用(不管是通过绑定到其中一个服务,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的服务,那么该应用处于前台:
- IME
- 壁纸服务
- 通知侦听器
- 语音或文本服务
如果以上条件均不满足,应用将被视为处于后台。
处于前台时,应用可以自由创建和运行前台服务与后台服务。 进入后台时,在一个持续数分钟的时间窗内,应用仍可以创建和使用服务。 在该时间窗结束后,应用将被视为处于空闲状态。 此时,系统将停止应用的后台服务,就像应用已经调用服务的 Service.stopSelf() 方法一样。(注:被其他组建bind的service不会受到影响)
在这几种情况下:
- 处理一条高优先级 Firebase 云消息传递 (FCM) 消息。
- 接收广播,例如短信/彩信消息。
- 从通知执行 PendingIntent。
后台应用将被置于一个临时白名单中并持续数分钟。 位于白名单中时,应用可以无限制地启动服务,并且其后台服务也可以运行。处理对用户可见的任务时,应用将被置于白名单中。
在很多情况下,应用都可以使用 JobScheduler作业替换后台服务。 例如,CoolPhotoApp 需要检查用户是否已经从朋友那里收到共享的照片,即使该应用未在前台运行。 之前,应用使用一种会检查其云存储的后台服务。 为了迁移到 Android O,开发者使用一个计划作业替换了这种后台服务,该作业将按一定周期启动,查询服务器,然后退出。
在 Android O 之前,创建前台服务的方式通常是先创建一个后台服务,然后将该服务推到前台。 在 Android O 中,如果应用当前无法创建后台服务,这种方式将失败。 因此,Android O 引入了一种全新的方法,即 NotificationManager.startServiceInForeground()。 调用此方法等同于调用 startService()在后台中创建一个服务,然后立即调用该服务的 [startForeground()](https://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)) 方法将其推到前台。 不过,由于新服务在任何情况下都不会处于后台,它不适用后台服务的限制。
权限
在 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,则系统会立即授予该权限,而不会提示用户。
WebView修改
Android N 在开发者模式中提供了多进程webview的选项,开启后网页内容将在独立的进程中处理,此进程与包含应用的进程相隔离,以提高安全性。而在 Android O上,这项设置已经成为了默认设置,也就是说默认webview就是在独立进程中。现在很多App都有大量的hybird页面,可能会造成影响,需要多做测试。
记录未捕获的异常
如果某个应用安装的 Thread.UncaughtExceptionHandler 未移交给默认的 Thread.UncaughtExceptionHandler,则当出现未捕获的异常时,系统不会终止应用。从 Android O 开始,在此情况下系统将记录异常堆栈跟踪情况;在之前的平台版本中,系统不会记录异常堆栈跟踪情况。
官方建议,自定义 Thread.UncaughtExceptionHandler 实现始终移交给默认处理程序处理;遵循此建议的应用不受 Android O 此项变更的影响
集合的处理
现在,)” target=”_blank”>AbstractCollection.removeAll() 和 )” target=”_blank”>AbstractCollection.retainAll() 始终引发 NullPointerException;之前,当集合为空时不会引发 NullPointerException。此项变更使行为符合文档要求。
仅列了几项感觉比较重要的,全部特性请见官方文档.