15

I'm still fresh to Android and Id think the below config works for launching my service when the app launches.

    <service android:name=".PlaylistUpdaterService">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </service>

But this is not the case. What did I miss?

Teo Choong Ping
  • 12,512
  • 18
  • 64
  • 91

2 Answers2

25

Wrong! extend the Application class (IE make your own), then in the onCreate() method do this.

//Service is below
Intent serviceIntent = new Intent(getApplicationContext(), PlaylistUpdaterService.class);
startService(serviceIntent);

And take that intent filter crap out of your declaration in the manifest file. Leave it as

<service android:name=".PlaylistUpdaterService">

The intent filter following needs to be in your home activity only

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> 

The reason you do this is because the Application class is started up as soon as the app is, and acts as kind of a global class the the android framework manages.

Actually if you want the service to run every time you go back to your home screen, you should start the service in your home classes onResume(). Putting it in the applications onCreate() will only start the service if the user is launching for the first time, or after the running process has been killed. Or you could put it in your home classes onCreate() but that is not even guaranteed to run every time.

Redwolf
  • 540
  • 4
  • 17
Danuofr
  • 1,661
  • 19
  • 25
  • You say wrong, but you also set intent filter category.LAUNCHER for the Activity as I do. Besides that, your approach is correct as well. – Zelimir Jan 11 '13 at 22:37
  • This isn't the appropriate approach if you want your service to be started only once (at start up). The service gets started every time the user changes orientation. I'm looking for a solution for this too. – DerpyNerd Oct 31 '13 at 20:52
  • 4
    @RobbieVercammen - If a service is running, calling start a second time will do nothing. This is the default behavior. – Aaron T Harris Jul 07 '15 at 21:31
  • 2
    @AaronTHarris while you are partly correct in this case it does not apply, because on orientation change events (I.E. screen rotation) do not apply to Android's Application class. Application.onCreate() is only ever called once on application start, and again if app is killed and relaunched. – Danuofr Jul 13 '15 at 18:12
  • @Danuofr - what do you mean Im partly correct? I'm absolutely correct. Robbie Vercammen was concerned about starting the service multiple times during activity.onResume since onResume is called multiple times (after an onPause or onOrientationChange). Im pointing out that multiple starts will not be a problem since redundancy is dealt with by the system. However, app.onCreate is still the preferred place to start (IMO), but your post mentioned starting the service when visiting the home page and app.onCreate doesnt easily do that except maybe if you hook into app.startIntent which is messy. – Aaron T Harris Jul 14 '15 at 20:22
  • @AaronTHarris my instructions on this post specifically stated to put this in the Application.onCreate()... – Danuofr Jul 15 '15 at 01:17
  • btw your wrong because if the service finishes before the next rotation, it will run again. – Danuofr Jul 15 '15 at 01:18
  • @Danuofr I'm not wrong. I'm talking about simultaneous instances as I said "multiple times during onResume" and as I said in my original post, "if a service is RUNNING, calling start a second time will do nothing". I am pointing out that Android will not allow the same service to start while an instance is already running. – Aaron T Harris Sep 14 '15 at 18:50
  • 1
    @AaronTHarris I think you might notice it already because this is a yesteryear discussion but just to make sure. It seems that you don't get Danuofr point here. Your statement is partly correct but his implementation does not work that way. Please note the keyword Application in Danuofr comments. He never work with any Activity so orientation change won't effect his implementation in the first place. There is no onResume for Application but Activity. The last paragraph of his answer is about some rare unusual case. – Curious Sam Mar 21 '16 at 20:02
  • Haha wow, I randomly ran into this thread while doing a search. Funny to revisit such an old debate. Now 3 years later, just catching up... yep... Still correct. "Calling startService on a service that is already running will do nothing." @Danuofr, your comment about rotation doesn't make sense. As you said -- if the service finished it will run again, of course it will because if it has finished, its not running :P I think people on stackoverflow like to argue just for the sake of arguing. – Aaron T Harris Aug 20 '18 at 18:25
  • @CuriousSam I understand what you're saying, but my comment was just to point out that "Calling startService on a service that is already running will do nothing" and Danuofr says thats partly correct when in fact its entirely correct. I make no claims about the correctness of any other part of anyone else's other statements :) – Aaron T Harris Aug 20 '18 at 18:27
9

Correct me if I am wrong, but android.intent.category.LAUNCHER is valid only for Activity. So, does not look like valid way to start Service. The same you can achieve if you do the following:

  • create transparent Activity that will be used only to start Service
  • for that Activity, you do not need to specify GUI layout. So, you do not need to setContentView() in the activity's onCreate(). The only thing you need is to put

@android:style/Theme.NoDisplay

under Theme tag for this Activity in AndroidManifest.xml.

  • start Service from onCreate() of your Activity.
  • call finish() in onStart() of your Activity to close it.

So, your Activity will be invisible to the user, last shortly and nobody will notice that it was used to start the service.

Zelimir
  • 11,008
  • 6
  • 50
  • 45
  • 1
    This method kind of locks the UI as the activity is running but since it is set to translucent,One cannot do anything.Is there a way to avoid this UI locking – Akhil Latta Jan 10 '13 at 22:56
  • @Noble6 - updated my answer to make it more clear. Thanks for valuable comment. – Zelimir Jan 11 '13 at 08:43
  • 4
    No need to use an activity, this will just slow down the perceived startup time of the app due to the overhead of starting and stopping an activity. The below approach of overriding an app is better. However if you really wanted to start it from the activity, it'd be better to have a base activity that starts the service as a default behavior if the service has not already been started and then have all activities extend that base activity. – Aaron T Harris Jul 07 '15 at 21:34
  • True. Fully agree. Long time ago abandoned this naive approach. – Zelimir Jul 08 '15 at 05:30