starting android service using explicit vs implicit intent

user504342 picture user504342 · Sep 20, 2013 · Viewed 16.6k times · Source

According to the standard Android documentation, the prefered way to start a service (started service that is) is to use an explicit intent like this:

// Using explicit intent:
Intent serviceIntent = new Intent(getApplicationContext(), MyService.class);
// or:
Intent serviceIntent = new Intent(this, MyService.class);
startService(serviceIntent);

You can also start/stop a service using an implicit intent with an action string specified in the manifest, like this:

// Using implicit intent:
static final String serviceAction = "com.example.my.app.services.MYSERVICE";
Intent serviceIntent = new Intent(serviceAction);
startService(serviceIntent);

// AndroidManifest.xml:
<service android:name="com.example.my.app.services.MyService"
   android:exported="false" android:process=":services" >
   <intent-filter>
      <!-- Start/Stop service -->
      <action android:name="com.example.my.app.services.MYSERVICE" />
   </intent-filter>
</service>

When the service is used only locally (third party applications are not allowed to start or bind to it), the documentation says that you should not include an intent-filter in the manifest service tag and you should set the exported tag to false.

Note: the activities and services run in separate processes (:application and :services processes). The communication between activity and service is done by implementing AIDL interfaces (this is done because only AIDL remote interfacing allows me to do multi-threading within the service that needs to handle IPC simultanously, not only between activities but mostly between services running within the :services process).

My questions are:

Q1: When the activities and services I use in my app are run in two different processes, do I need to use implicit intents over explicit intents to start and stop the services?

Q2: When the :application process is gone (destroyed, not in memory anymore) and the :services process is running in the background, how do I connect again from a new :application process to the already running :services process? Somehow I need to get a reference to the :services process again so that I can stop the running service inside that process. This cannot be done using AIDL afaik.

The problem is that Android can and will destroy the :application process easily when out of resources, and that is fine by me as long as the :services process keeps running. (Yes, I know about influencing the process by setting the service as a foreground service, etc. I too can read manuals ;) but that is not my problem).

I cannot find any information or answers related to my questions when the activities and services are in separated processes and use AIDL, AND when the :application process needs to "find" the :services process again after it has been killed by Android or when the user enters the app again (after he/she left the app before).

Any expert-level advise is welcome.

Answer

Santosh picture Santosh · Nov 20, 2013

A1 : Even though your activity and service run in different processes they still belong to same Application. You can still use explicit intent, I don't see any specific advantage of using implicit intent here (let me know if find any :) )

A2 : let me list down few facts here

  • Life cycle of "Started" service (rather than "Bind"ed service) is independent of the life cycle of Activity which has started this service. This is true irrespective whether both are running in the same process or not.
  • Only one instance of Service will be alive at any point of time. when your activity calls startService() , service instance will be created if it is not already running (in this case you service will receive onCreate() callback as well). But if Service is already running, Framework would simply call onStartCommand() callback on already running process(No onCreate() callback in this case). Again all this is true irrespective of activity and service are running on same process or different processes.

Now to answer your question, if you service is still running (because of startService() call by previous activity), then bindService()/startService() will make sure to connect to existing service.

Hope this is of some help to you. Let me know if you have any other specific questions.