【问题标题】:Android Service Running only when UI is activeAndroid 服务仅在 UI 处于活动状态时运行
【发布时间】:2019-01-23 09:14:25
【问题描述】:

Android 在最近的版本中似乎对在后台运行服务引入了多项限制,这对于我们设备的电池寿命当然是个好消息。我的目标是创建一个应用程序,只要用户正在与应用程序交互(这似乎是他们的目标),只运行一项服务即可。但对我来说,如何正确实现这一点还不是很清楚。我的要求如下:

  • 只要有任何 Activity 对用户可见,就应该启动服务。

  • 当用户与应用交互(在活动之间浏览)时,服务应保持不间断处于运行状态。

  • 当 UI(无论何种活动处于活动状态)被发送到后台时,服务应运行 2-3 秒,然后自行停止。完全关闭服务需要 2-3 秒。

  • 当应用程序处于后台(或关闭)时,可以通过推送消息启动服务,以便随时处理传入事件。然后该服务注册到远程服务器,并检查更新。如果有更新,则会向用户发出通知。然后服务在 2-3 秒不活动后再次关闭。

对我来说,似乎要使用绑定服务。但我不清楚我的要求将如何适应绑定服务模型。有没有人有这方面的经验,谁能指出我正确的方向?

编辑:在这种情况下,“服务”是本地的进程内服务,不打算从外部访问。

【问题讨论】:

    标签: android service android-lifecycle activity-lifecycle battery-saver


    【解决方案1】:

    (这个答案假定一个本地的“进程中”Service,这无疑是您打算使用的。)

    对于您的用例,您实际上使用了多种技术组合来保持Service 运行。

    使用“绑定Service 模型”来保留Service,而您的任何Activities 都可见。这很简单;在Activity.onStart() 中调用bindService(),在Activity.onStop() 中调用unbindService()。如果您担心Service 在您的两个Activities 之间的短暂过渡时刻被破坏,请不要担心; Android 足够聪明,可以等待不同应用程序组件的生命周期变化“解决”,然后再决定 Service 未被引用/不需要。

    您应该为所有bindService() 调用使用BIND_AUTO_CREATE 标志。请记住,Service 不会在调用 bindService() 时立即创建;这需要几毫秒,并且您必须小心地将控制权返回给框架,方法是从您当前所在的任何生命周期方法(例如,onStart())返回。只有这样,您才会收到对 onServiceConnected() 的调用。

    您需要手动跟踪有多少Activities 绑定到您的Service,以确定何时开始您的 2-3 秒清理逻辑。有关有效方法,请参阅this answer。不要担心Service 在您最后一次调用unbindService() 期间被同步销毁——就像bindService() 一样,实际的生命周期状态更改是“延迟的”。

    现在的问题是,此时如何让Service 在这额外的 2-3 秒内保持活动状态(您确定打开的Activities 的数量已降至 0)?好吧,您可以直接致电startService()。您甚至可以从 Service 子类中的方法调用它;只要您有一个有效的Context 可用,这并不重要。 startService() 向系统表明您希望保留Service,无论有多少Activities(或其他客户端)可能绑定到它。在这种情况下,Service 不会重新启动——它已经在运行了!

    清理完成后,您可以致电stopService(),或者更好的是stopSelf()。这有效地取消了startService() 调用,并告诉操作系统,“我完成了”。预计不久后将致电Service.onDestroy()

    请记住,您的Activities 之一可能会异步弹出,并在清理完成之前重新绑定到Service。这是一种边缘情况,但很容易处理。 Service 只有在以下两个条件都为真时才会被销毁:1.) 没有绑定/绑定客户端,以及 2.) 不存在对 startService() 的未取消调用。

    请注意,在 Oreo 及更高版本上,系统可能会非常积极地杀死具有背景 Services 的应用程序。根据this doc 的说法,与用户交互会将您列入白名单“几分钟”,所以我认为 2-3 秒就可以了。同样,如果您正在处理“高优先级 FCM 消息”(我假设您的意思是“推送”消息),您将被列入白名单,并允许再过几分钟执行 @ 987654364@(这次使用startService()/stopSelf() 方法)。

    【讨论】:

    • 这种方法有效。主要问题是跟踪绑定活动的数量,因为我希望在绑定数量为 0 时调用 onUnbind()。但是,这不起作用,因为这是在活动转换期间调用的。我确实觉得奇怪的是,Android API 没有以更简单的方式促进这一点。毕竟,Oreo 中的限制似乎强制执行了这种服务行为,所以我觉得很奇怪,它很难遵守(而且绝不是显而易见的)。无论如何,谢谢你:-)
    猜你喜欢
    • 1970-01-01
    • 2015-11-07
    • 1970-01-01
    • 1970-01-01
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 2013-09-12
    相关资源
    最近更新 更多