背景
为了支持端上网络库内部组件获取App状态,以便使用合适的策略,例如如果当前App在后台,网络库便不再去主动解析DNS结果,这样可以节省对移动端设备的资源消耗。
因此项目需要做一个移动端前后台状态判断及通知机制。由于我们支持iOS和Android,因此这个特性也分别针对双端做,上层用一个抽象类封装。
概要设计
- 初始化:网络库启动时,会初始化Notifier实例,但会根据不同的端实例化不同的子类。Notifier用于探测当前App状态并通过回调方式通知下游用户。
- 用户注册:我们提供了标准的用户回调抽象类,下游用户通过继承并实现具体的抽象方法生成新的实例,并将该实例注册进Notifier。
- 在状态发生变更时,Notifier会轮询一遍所有等待回调的用户(第2步注册进来的)触发用户自定义动作。
逻辑架构图
运行架构图(以Android为例)
详细设计
前后台状态分类
前后台状态获取方式
- iOS
使用iOS的消息通知组件NSNotification,以回调方法的形式注册进去。 Android
安卓的情况比较复杂,Android前后台 - EFFMX.COM上对获取安卓前后台状态做了一些可行性方法的介绍。
通过一些调研分析,我们可以得出的一些结论是:
a.安卓在前后台状态方面没有一个像iOS那样统一的消息组件。
b.由于我们是作为一个基础组件SDK提供给App方,在安卓上能操作的能力很有限,比如文章中介绍的Activity回调方式就无法在SDK上做。除此之外,在跟我们的客户(Android端 App研发团队)接触后发现,我们的客户已经在App里通过Activity回调实现了前后台状态的通知机制。
因此在Android上,最终我们选择的方式是:在SDK接入层提供一个通知接口,由App负责将状态变更通过API传递给我们。
安全策略
这里的安全策略主要是考虑到,安卓端可能会长时间收不到正确的状态变更通知,这种情况可能是由于上游App出现异常或漏推送状态导致。
因此我们做了一个兜底机制,用来防止上游App出现这种情况。
策略设计
首先,策略是基于Android前后台 - EFFMX.COM里的方法5,主动去扫描进程信息,从而获取当前App状态。
这个方法不被官方承认,并且对资源消耗会比较大(涉及循环扫描进程),因此应该尽量少用,这里只使用它用于兜底,正常状态不会被触发。
在java层实现进程扫描方法,可通过主动获取系统锁屏及进程信息方法获取到当前的app是否为前台。在Notifier中内置定时器,默认定时时间为10分钟,即如果超过10分钟未收到状态变更通知则触发保护机制。
计时器到点了以后,将会出现四种可能的情况。
- 如果当前已经处于后台状态了,考虑到这种情况已经不会额外消耗用户的资源了,不做处理了。以下三种都是当前已经在前台的情况下。
- 发起扫描,如果结果是前台状态,则认为当前确实是在前台,不做处理,重新计时。
- 发起扫描,如果结果是在后台,则表明端上出现异常,则推送后台状态给用户。
- 发起扫描,如果扫描进程的过程发生java层可捕获的异常,则当前无法确认准确状态,推送unknown状态给用户。
接口及样例
注册回调
主动拉取状态