How to properly unbind services
Asked Answered
G

1

6

I have a Service that is binded with BIND_AUTO_CREATE to my Activity and is started with START_STICKY. I do not explicitly call startService().

Since the onDestroy() method is not always called when my Activity get killed and the onStop() method is not viable since I don't want my Service to stop when the user simply presses the Home button, I don't know when to unbind my Service.

Here are my questions :

  1. If I want my Service to run when my Activity is alive and to stop when my Activity get killed, where should I unbind my Service?

  2. When the onDestroy() method is currently called and I call unbindService(), the Service's onUnbind() method isn't triggered. Why?

Gingham answered 8/4, 2014 at 14:16 Comment(3)
Good question. But is it really necessary to bind to a service? I really like the IntentService pattern. There the service shuts down as soon as it has finished it's task. Communication is done via Broadcasts and IntentReceivers.Portion
Actually, I have 2 services that uses an alarm manager to wake up every x seconds to execute their task. I guess I could juste use my Activity's context instead of using a service! If I understand well, Services should only be used when they must remain active when the Activity get killed?Gingham
If you have AlarmManager you can live without a service by implementing a broadcast receiver that will react to your alarms. You may need a service if you'd like some long running operation (i.e. sync with server, update DB) ongoing without UI.Vermin
V
4

I do not explicitly call startService()

In that case it doesn't make sense to override onStartCommand (and return START_STICKY) as it won't be called.

1.If I want my Service to run when my Activity is alive and to stop when my Activity get killed, where should I unbind my Service?

if you don't want to do it in onPause, you can unbind in onDestroy, that is fine. In a rare situation when your activity gets killed without onDestroy it will be unbound by Android, (so your service will be unbound & destroyed properly too), as stated here :

When your client is destroyed, it will unbind from the service

As for

2.When the onDestroy() method is currently called and I call unbindService(), the Service's onUnbind() method isn't triggered. Why?

I suggest that you have someone else bound to it, otherwise onUnbind should be called. Try putting a breakpoint in this method and verify it gets hit. Also, verify that your service onDestroy is called in this situation.

Vermin answered 8/4, 2014 at 15:25 Comment(4)
The onStartCommand of my Service is called because I explicitly call it in the onServiceConnected() method of my ServiceConnection. I just read its Javadoc asking to not call the method directly... If a binded Service should unbind automatically when its client is destroyed, I guess it is OK to unbind it in the onDestroy method. You are right, I actually have another Service bound to my first Service. I thought it would be simpler to have it that way, but it looks like it complicates the unbinding process.Gingham
Actually, after more testing, I've seen some strange behavior from my app. When I swipe it away from the list of previously opened apps, the Log.d() of my Activity's onDestroy method is called, but the rest of the code inside isn't. It's like Android wanted to kill my app as fast as possible. I don't have the time to unbind my services (that are both binded to my Activity's context). And, unlike the source you stated, my Services aren't unbound as my Activity is destroyed... I made sure there was no startService called, and the onStartCommand is not called neither.Gingham
"my Services aren't unbound as my Activity is destroyed" -> it will be unbound eventually from killed activity by android as documentation I refer to explains. You mention that you have two services, perhaps one still remains bound to it ? And lastly, can you confirm that your service "onDestroy" was called after everything was unbound from it. I did simple test and everything works as expected.Vermin
I think I am starting to understand, my Services were destroyed (without passing through their onUnbind or onDestroy methods) and only their alarm broadcast receivers were still alive. But since I can't detect the destruction of my Services, I can't cancel the AlarmManager repeating tasks from my inside my Services. The solution I found was to verify if my Activity's context was still alive, and if it wasn't, I would cancel the alarm broadcast receiver from inside itself. I don't think this is a clean way of stopping it, I should probably just not use Services for this purpose.Gingham

© 2022 - 2024 — McMap. All rights reserved.