Android 服务 运行 仅当 UI 处于活动状态时
Android Service Running only when UI is active
似乎 Android 在最近的版本中引入了对后台 运行ning 服务的多重限制,这当然对我们设备的电池寿命来说是个好消息。我的目标是创建一个应用程序,只要用户与应用程序交互(这似乎是他们的目标),就只需要 运行 提供服务即可。但我不清楚如何正确实施它。我的要求如下:
服务应在任何 Activity 对用户可见后立即启动。
当用户与应用程序交互(在活动之间浏览)时,服务应保持 不间断 运行ning 状态。
当 UI(不管 activity 是什么)被发送到后台时,服务应该 运行 2-3 秒然后停止自己。干净关闭服务需要 2-3 秒。
当应用程序在后台(或关闭)时,可以通过推送消息启动该服务,以便随时处理传入的事件。该服务然后注册到远程服务器,并检查更新。如果有更新,则会向用户发出通知。然后服务在 inactivity.
的 2-3 秒后再次关闭
对我来说,绑定服务似乎就是要使用的。但我不清楚我的要求如何适合绑定服务模型。有没有人有这方面的经验,谁能给我指明正确的方向?
编辑:本例中的 "Service" 是本地进程内服务,不打算从外部访问。
(这个答案假设一个本地的,"in-process" Service
,这无疑是你打算使用的。)
对于您的用例,您实际上使用了多种技术的组合来保持 Service
运行。
使用 "bound Service
model" 保持 Service
在您的任何一个 Activities
可见的情况下。这很简单;在 Activity.onStart()
中调用 bindService()
,在 Activity.onStop()
中调用 unbindService()
。如果您担心 Service
在两个 Activities
之间的短暂过渡时刻被破坏,请不要担心; Android 足够聪明,可以等待不同应用程序组件的生命周期更改为 "settle",然后再决定 Service
是 unreferenced/unneeded。
您应该为所有 bindService()
调用使用 BIND_AUTO_CREATE
标志。请记住 Service
并不是在调用 bindService()
时立即创建的;它需要几毫秒,你必须小心 return 控制框架,通过 returning 从你当前所在的任何生命周期方法(例如,onStart()
)。只有这样你接到 onServiceConnected()
.
的电话
您需要手动跟踪有多少 Activities
绑定到您的 Service
,以确定何时开始您的 2-3 秒清理逻辑。有关有效方法,请参阅 this answer。不要担心 Service
在上次 unbindService()
调用期间被同步销毁——就像 bindService()
一样,实际的生命周期状态变化是 "delayed."
现在的问题是,如何让 Service
在这额外的 2-3 秒内保持活动状态,此时(您确定打开 Activities
的数量已下降到 0)?那么,您可以简单地调用 startService()
。您甚至可以从 Service
子类中的方法调用它;只要您有可用的有效 Context
,这并不重要。 startService()
向系统表明您希望保留 Service
,而不管有多少 Activities
(或其他客户端)可能绑定到它。在这种情况下,Service
不会重新启动——它已经是 运行!
清理完成后,您可以调用 stopService()
,或者更好的是,调用 stopSelf()
。这有效地取消了 startService()
调用,并告诉 OS、"I'm done"。预计此后不久将致电 Service.onDestroy()
。
请记住,您的 Activities
之一可能会异步弹出,并在清理完成之前重新绑定到 Service
。这是一种边缘情况,但很容易处理。 Service
只有在以下两个条件都为真时才会被销毁:1.) 没有客户端是 binding/bound,以及 2.) 不存在对 startService()
的未取消调用。
请注意,在 Oreo 及更高版本上,系统可能会非常积极地终止具有背景的应用程序 Services
。根据 this doc,与用户交互会使您进入 "several minutes" 的白名单,所以我认为 2-3 秒就可以了。类似地,如果您正在处理 "high-priority FCM message"(我假设您的意思是 "push" 消息),您将被列入白名单,并允许再花几分钟时间执行 Service
(这次使用 startService()/stopSelf()
方法)。
似乎 Android 在最近的版本中引入了对后台 运行ning 服务的多重限制,这当然对我们设备的电池寿命来说是个好消息。我的目标是创建一个应用程序,只要用户与应用程序交互(这似乎是他们的目标),就只需要 运行 提供服务即可。但我不清楚如何正确实施它。我的要求如下:
服务应在任何 Activity 对用户可见后立即启动。
当用户与应用程序交互(在活动之间浏览)时,服务应保持 不间断 运行ning 状态。
当 UI(不管 activity 是什么)被发送到后台时,服务应该 运行 2-3 秒然后停止自己。干净关闭服务需要 2-3 秒。
当应用程序在后台(或关闭)时,可以通过推送消息启动该服务,以便随时处理传入的事件。该服务然后注册到远程服务器,并检查更新。如果有更新,则会向用户发出通知。然后服务在 inactivity.
的 2-3 秒后再次关闭
对我来说,绑定服务似乎就是要使用的。但我不清楚我的要求如何适合绑定服务模型。有没有人有这方面的经验,谁能给我指明正确的方向?
编辑:本例中的 "Service" 是本地进程内服务,不打算从外部访问。
(这个答案假设一个本地的,"in-process" Service
,这无疑是你打算使用的。)
对于您的用例,您实际上使用了多种技术的组合来保持 Service
运行。
使用 "bound Service
model" 保持 Service
在您的任何一个 Activities
可见的情况下。这很简单;在 Activity.onStart()
中调用 bindService()
,在 Activity.onStop()
中调用 unbindService()
。如果您担心 Service
在两个 Activities
之间的短暂过渡时刻被破坏,请不要担心; Android 足够聪明,可以等待不同应用程序组件的生命周期更改为 "settle",然后再决定 Service
是 unreferenced/unneeded。
您应该为所有 bindService()
调用使用 BIND_AUTO_CREATE
标志。请记住 Service
并不是在调用 bindService()
时立即创建的;它需要几毫秒,你必须小心 return 控制框架,通过 returning 从你当前所在的任何生命周期方法(例如,onStart()
)。只有这样你接到 onServiceConnected()
.
您需要手动跟踪有多少 Activities
绑定到您的 Service
,以确定何时开始您的 2-3 秒清理逻辑。有关有效方法,请参阅 this answer。不要担心 Service
在上次 unbindService()
调用期间被同步销毁——就像 bindService()
一样,实际的生命周期状态变化是 "delayed."
现在的问题是,如何让 Service
在这额外的 2-3 秒内保持活动状态,此时(您确定打开 Activities
的数量已下降到 0)?那么,您可以简单地调用 startService()
。您甚至可以从 Service
子类中的方法调用它;只要您有可用的有效 Context
,这并不重要。 startService()
向系统表明您希望保留 Service
,而不管有多少 Activities
(或其他客户端)可能绑定到它。在这种情况下,Service
不会重新启动——它已经是 运行!
清理完成后,您可以调用 stopService()
,或者更好的是,调用 stopSelf()
。这有效地取消了 startService()
调用,并告诉 OS、"I'm done"。预计此后不久将致电 Service.onDestroy()
。
请记住,您的 Activities
之一可能会异步弹出,并在清理完成之前重新绑定到 Service
。这是一种边缘情况,但很容易处理。 Service
只有在以下两个条件都为真时才会被销毁:1.) 没有客户端是 binding/bound,以及 2.) 不存在对 startService()
的未取消调用。
请注意,在 Oreo 及更高版本上,系统可能会非常积极地终止具有背景的应用程序 Services
。根据 this doc,与用户交互会使您进入 "several minutes" 的白名单,所以我认为 2-3 秒就可以了。类似地,如果您正在处理 "high-priority FCM message"(我假设您的意思是 "push" 消息),您将被列入白名单,并允许再花几分钟时间执行 Service
(这次使用 startService()/stopSelf()
方法)。