Android 服务仅在 UI 处于 Activity 状态时运行

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

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

  • 一旦任何 Activity 对用户可见,就应启动服务。

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

  • 当 UI(无论什么 Activity 处于 Activity 状态)发送到后台时,服务应运行 2-3 秒,然后自行停止。彻底关闭服务需要 2-3 秒。

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

对我来说,似乎应该使用绑定(bind)服务。但我不清楚我的需求如何适应绑定(bind)服务模型。有没有人有这方面的经验,可以指出我正确的方向?

编辑:本例中的“服务”是本地进程内服务,不适合从外部访问。

最佳答案

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

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

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

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

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

现在的问题是,此时(您已确定打开的 Activities< 数量),如何在这额外的 2-3 秒内保持 Service 处于 Activity 状态 已降至 0)?那么,您只需调用 startService() 即可。您甚至可以从 Service 子类中的方法调用它;只要您有有效的Context可用,这并不重要。 startService() 向系统指示您希望保留 Service,无论可能绑定(bind)多少 Activities(或其他客户端)到它。在这种情况下,Service 将不会重新启动 - 它已经在运行!

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

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

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

关于Android 服务仅在 UI 处于 Activity 状态时运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54323680/

相关文章:

安卓图片上传: Use Activity or Service?

java - list screenOrientation 属性与 setRequestedOrientation

android - 如何在gradle构建脚本中预生成sqlite数据库

android - 索引 2 超出范围 JSON

windows - 服务启动的进程无法分配内存

android - Activity 无法转换为 LifecycleOwner

android - ( Activity 娱乐) : what to do with a backstack built on invalidated data?

android - notifyItemMoved() 在迁移到 ListAdapter Android 时不起作用

android - 文件输入输出不工作

node.js - 服务器不断运行更新缓存的功能,它会阻止所有其他服务器功能吗?