0

I have a bit of a general question about services. Say I have a service that does this:

private void finishCountdown() {
    playFinishSound();
    broadcastFinishedEvent();
    logFinishedEventToDatabase();
    stopSelf(); // has to stop itself because it's a started service,
                // and may need to run again immediately.
}

Is the stopSelf() call always going to wait until the previous statements are done with whatever they were doing? Does it have to wait, or is simply making these calls enough to make sure they're done regardless of what happens to the service? There are some strange things happening with my app ("A SQLiteConnection object was leaked!", sound gets cut off sometimes and says "Media player finalized before being released", etc) and I'm wondering if maybe this is the reason.

If this is something I shouldn't do, then what would be the best way to have all these things (broadcast, play sound, write to database) initiated by the service (which should be stopped as soon as possible)? If I call another service to do this thing and then destroy the original service, how do I make sure the other service waits until all those things were done before stoping itself?

PFort
  • 485
  • 2
  • 6
  • 15
  • How are you using the Service? Is it local? If so, why do you feel the need to stop it (because it doesn't have it's own thread and no other app can access it...)? Also, are those methods you are calling synchronous? I am guessing the database call isn't, so you should wait for it to finish. – Dave Oct 10 '13 at 03:30
  • Yes, it's a local service and I need to stop it immediately because it may have to run again immediately (for reasons too complicated to explain). As for synchronous methods, I don't know what that means but it sounds like something I should learn about. But even if I don't have to stop the service immediately, since it's a started service, I have to stop it at some point, so when? – PFort Oct 10 '13 at 03:32
  • Are you binding to the Service or sending it an Intent? – Dave Oct 10 '13 at 03:34
  • Both, it's started with an intent and then bound to provide continuous updates to an activity (the countdown timer). So even if the activity unbinds, I still have to stop the service, and since the activity might be destroyed in the meantime, I can't rely on it to stop the service. – PFort Oct 10 '13 at 03:36
  • You don't need an Intent to start the Service. Binding will take care of that. Unbinding will allow it to destroy itself. From where are you binding if not an Activity? – Dave Oct 10 '13 at 03:57
  • But what if the activity gets destroyed while the service is running? The service shouldn't stop just because the activity that started it was destroyed. And if there are no bindings to a service that is not started, the service will be stopped, won't it? – PFort Oct 10 '13 at 04:00

1 Answers1

0

A local Service's lifecycle is tied to Intents being processed and other objects binding to it. It is created when an Intent is received or an object binds to it. If there are no more bound objects and no Intents to process, it is destroyed. It will process Intents in the order they are received. You don't need to call stopSelf() (or stop it in any other way) to send another Intent. It will be running on the main thread, so you don't have to worry about successive Intents being processed at the same time.

If your database is a Sqlite database on the device, there is probably nothing else to worry about. Those calls should be synchronous, so simply don't call stopSelf().

If your database is remote and there are asynchronous calls being made, you may want to ensure those calls are sent in order by using a queue of some sort.

Edit:

I don't completely understand why your app needs the Service to be explicitly stopped, but I won't worry about that. The warnings you mentioned look like things aren't being properly cleaned up.

I am guessing you are calling release() on the MediaPlayer object in the onCompletion callback. If not, you probably should be. The MediaPlayer does things asynchronously, so it will not be finished immediately after returning from your playFinishSound() method. You should not call stopSelf() on the Service until the call to onCompletion has been made and release() has been called.

The SQLite problem may be a bit different. I'd have to see your code to say anything more, but maybe this will help.

Community
  • 1
  • 1
Dave
  • 4,282
  • 2
  • 19
  • 24
  • Not calling `stopSelf()` completely messes up my app because it's relying on the service not running any more... again, for reasons that are too complicated to explain here... so it needs to stop as soon as the timer reaches zero. – PFort Oct 10 '13 at 04:09