33

How can I make sure that only one instance of Service is created?

I have checked some functions with logging (WeatherService is the class who extends Service):

Log.i(TAG, "Start  Id:" + WeatherService.this.hashCode());
Log.i(TAG, "End Id:" + WeatherService.this.hashCode());

It gives different hash codes even when I am sure that the same function is running twice (downloading):

09-12 01:00:55.195: INFO/WeatherService(7222): Start  Id:1137653208
09-12 01:00:57.235: INFO/WeatherService(7222): Start  Id:1137654296
09-12 01:00:59.035: INFO/WeatherService(7222): Start  Id:1138806536
09-12 01:01:39.085: INFO/WeatherService(7222): End Id:1137654296
09-12 01:01:39.265: INFO/WeatherService(7222): Start  Id:1137654296
09-12 01:02:22.175: INFO/WeatherService(7222): End Id:1137653208
09-12 01:02:24.815: INFO/WeatherService(7222): End Id:1138806536
09-12 01:02:24.836: INFO/WeatherService(7222): Start  Id:1138806536
09-12 01:02:40.275: INFO/WeatherService(7222): End Id:1137654296

I am binding a Activity to the service with:

bindService(new Intent(getApplicationContext(),  WeatherService.class)
                               ,mServiceConnection, BIND_AUTO_CREATE);

And the service can run for minutes until it is completed, therefore the service can be binded to/created by many Activities

Torstein I. Bø
  • 1,359
  • 4
  • 14
  • 33
  • Also see this page, which I feel has a helpful explanation as well: http://stackoverflow.com/questions/2518238/does-startservice-create-a-new-service-instance-or-using-the-existing-one –  Apr 25 '13 at 13:37

2 Answers2

32

How can I make sure that only one instance of Service is created?

There can only be one instance of a given Service.

It gives different hash codes even when I am sure that the same function is running twice (downloading).

Then this is not the Service. Or, the service had been destroyed and recreated between logs.

And the service can run for minutes until it is completed, therefore the service can be binded to/created by many Activities

Then the Service is probably being destroyed and recreated. If you need the service to run for minutes, you need to use startService() and stopSelf() in addition to your bindService() and unbindService() calls. Or, perhaps you do not need to bind at all, in which case you might consider using an IntentService, since that automatically gives you a background thread on which to do your downloads.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • When the job is finished i call a callback to the activity, this is why I use bindService (using AIDL). I have now tried to log at the start and at the end, and it is clear that it is not completed/destroyed before a new instance is created. I also used WeatherService.this.hashCode(), where WeatherService is the class who extends Service. – Torstein I. Bø Sep 11 '10 at 22:54
  • oh so it means it's only one service will be started? if it's recalled again oncreate wont be call but only onstart – Sunil Pandey May 02 '11 at 11:26
  • 10
    Btw do you have any sources that supports "There can only be one instance of a given Service." ? – Pacerier Mar 05 '12 at 02:54
  • 6
    I disagree with this answer. I have experienced cases where multiple services with different hash codes exist at the same time, and all of them are active and alive. It generally happens after a service has been unbound and then rebound, but the original service appears to live on for a time. I've been unable to figure out how to handle the scenario differently. – Peter Gaultney Oct 14 '15 at 18:36
  • @PeterGaultney: "I have experienced cases where multiple services with different hash codes exist at the same time, and all of them are active and alive" -- you are welcome to post a sample project demonstrating this behavior. – CommonsWare Oct 14 '15 at 18:43
  • This answer is still wrong in 2022, as I'm sitting here watching two overlapping instances of my service being created and clashing with one another. Two instances are constructed in the same process, then onStartCommand is called on each instance. Hogun's answer fixed it for me: at least if you're binding to a service that runs in the same process as the application, bind to it with the application context. – Glenn Maynard Dec 22 '22 at 05:16
  • @GlennMaynard: "Two instances are constructed in the same process, then onStartCommand is called on each instance" -- perhaps one was destroyed, but you leaked a thread, and that thread is continuing to run. As I wrote 7 years ago, you are welcome to post a sample project demonstrating your purported behavior. – CommonsWare Dec 22 '22 at 11:50
  • @GlennMaynard: "at least if you're binding to a service that runs in the same process as the application" -- every Android SDK process has its own `Application` singleton instance, so by definition, every service runs in the same process as the `Application`. That being said, binding with the `Application` singleton is still a good idea. – CommonsWare Dec 22 '22 at 11:51
14

I experienced situation similar.
If you have been written as follow, instance can be created over one .

bindService(new Intent(getApplicationContext(),  WeatherService.class), mServiceConnection, BIND_AUTO_CREATE);

Try to write once as follows.

getApplicationContext().bindService(new Intent(getApplicationContext(), WeatherService.class),mServiceConnection, BIND_AUTO_CREATE);
Hogun
  • 602
  • 6
  • 9
  • 1
    This was exactly what was missing to me, because, it seems that you CAN launch a service multiple times (I had a sevice supposed to show toasts every five second, and it was showing 2, 3 and more toast a second until I used this trick, everytime I used bindService) Thanks! – liltof Aug 23 '15 at 16:02