代码之家  ›  专栏  ›  技术社区  ›  Johnny Egeland

Android服务仅在用户界面处于活动状态时运行

  •  1
  • Johnny Egeland  · 技术社区  · 7 年前

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

    • 一旦用户看到任何活动,就应该立即启动服务。

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

    • 当UI(不管活动是什么)发送到后台时,服务应该运行2-3秒,然后自行停止。完全关闭服务需要2-3秒。

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

    对我来说,似乎一个绑定服务就是要使用的。但我不清楚我的需求如何与绑定服务模型相适应。有没有人有这方面的经验,谁能给我指明正确的方向?

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

    1 回复  |  直到 7 年前
        1
  •  2
  •   greeble31    7 年前

    (此答案假定本地“正在处理” Service ,这无疑是您打算使用的。)

    对于您的用例,您实际上使用了多种技术组合来保持 服务 跑步。

    使用“绑定” 服务 模型“保持 服务 当你的任何一个 Activities 是可见的。很简单;打电话 bindService() 在里面 Activity.onStart() unbindService() 在里面 Activity.onStop() . 如果你担心 服务 在你们之间短暂的过渡时刻被摧毁 活动 ,不要这样做;Android足够聪明,可以等待不同应用程序组件的生命周期更改“解决”,然后再决定 服务 未被引用/不需要。

    你应该使用 BIND_AUTO_CREATE 为所有您的 绑定服务() 电话。记住 服务 调用时未立即创建 绑定服务() ;这需要几毫秒的时间,您必须小心地通过从任何生命周期方法(例如, onStart() )你现在在。只有那时你才能接到电话 onServiceConnected() .

    您需要手动跟踪 活动 与您的 服务 ,以确定何时开始2-3秒清理逻辑。见 this answer 为了一个有效的方法。别担心 服务 在你最后一次被同步摧毁 UNBIN Service() 打电话——就像打电话一样 绑定服务() ,实际生命周期状态更改为“延迟”。

    现在的问题是,你如何保持 服务 在这一点上(你已经确定了打开的次数 活动 已降至0)?好吧,你可以打电话 startService() . 您甚至可以从 服务 子类;只要你有一个有效的 Context 有空,没关系。 启动服务() 指示要保留的系统 服务 大约,不管有多少 活动 (或其他客户)可能受其约束。在这种情况下, 服务 不会重新启动--它已经在运行!

    清理完成后,您可以致电 stopService() 或者,更好的是, stopSelf() . 这实际上取消了 启动服务() 打电话告诉操作系统“我完了”。期待来电 Service.onDestroy() 不久之后。

    记住你的 活动 可能会异步弹出,并重新绑定到 服务 ,在清理完成之前。这是一个边缘案件,但很容易处理。这个 服务 只有当这两个条件都为真时才会被销毁:1.)没有客户端绑定/绑定,2.)没有取消对 启动服务() 存在。

    请注意,在Oreo和更高版本上,系统可能会非常积极地杀掉后台应用程序。 Services . 根据 this doc 与用户互动会让你进入白名单“几分钟”,所以我认为2-3秒就可以了。同样,如果您处理的是“高优先级FCM消息”(我假设您的意思是“推送”消息),那么您将被置于白名单中,并允许在接下来的几分钟内执行 服务 (这次使用 startService()/stopSelf() 方法)。