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

时间:2019-01-23 09:14:25

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

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

  • 该服务应在用户看到任何活动后立即启动。

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

  • 当UI(无论活动是什么)发送到后台时,服务应运行2-3秒,然后停止运行。干净关闭服务需要2-3秒。

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

在我看来,绑定服务就是要使用的绑定服务。但是我不清楚我的要求如何与Bound Service模型相适应。有没有对此有任何经验的人,可以为我指出正确的方向?

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

1 个答案:

答案 0 :(得分:2)

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

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

在您的Service中的任何一个可见的情况下,使用“绑定Service模型”保持Activities不变。很简单;在bindService()中呼叫Activity.onStart(),在unbindService()中呼叫Activity.onStop()。如果您担心Service在两个Activities之间过渡的短暂瞬间被毁,请不要这么做; Android足够聪明,可以等待不同应用程序组件的生命周期更改“解决”,然后再决定Service是未引用/不需要的。

对于所有BIND_AUTO_CREATE呼叫,都应使用bindService()标志。请记住,调用Service不会立即创建bindService();这需要花费几毫秒的时间,并且您必须小心,通过从当前使用的任何生命周期方法(例如onStart())中返回来将控制权返回给框架。只有这样,您才能调用{{1} }。

您需要手动跟踪onServiceConnected()上绑定了多少Activities,以便确定何时开始2-3秒的清理逻辑。有关有效方法,请参见this answer。不必担心Service在上一次Service调用期间会被同步破坏,就像unbindService()一样,实际生命周期状态更改会“延迟”。

现在的问题是,在这一点上(如何确定bindService()的数量已降至0)?好吧,您可以简单地致电Service。您甚至可以从Activities子类中的方法调用它;只要您有有效的startService(),就没有关系。 Service向系统指示您要保留Context,而不管绑定到多少startService()(或其他客户端)。在这种情况下,Service不会重新启动-它已经在运行!

清理完成后,您可以致电Activities,也可以致电Service。这实际上取消了stopService()调用,并告诉操作系统“我完成了”。预计此后不久会致电stopSelf()

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

请注意,在奥利奥(Oreo)及更高版本上,该系统对于杀死背景为Service的应用程序可能会非常激进。根据{{​​3}}的说法,与用户进行互动会使您进入白名单的时间为“数分钟”,因此我认为2-3秒就可以了。同样,如果您要处理“高优先级FCM消息”(我认为这是“推送”消息的意思),则您将被列入白名单,并等待几分钟来执行{ {1}}(这次使用startService()方法)。