Just An Application

February 16, 2011

The Android Intent Based APIs: Part Five – Services And Intents

1.0 A Service/Intent Model

  • A Service is an Application component capable of executing without a UI.

  • A Service can be used to implement functionality for use by other Application Components in the same or other Applications.

  • A Service can be started and stopped.

  • A client can bind to a Service to obtain a handle to use to access the functionality provided by that Service.

  • A client can unbind from a Service that it has previously bound to.

  • An Application can statically register one or more Services

  • A Service can be registered with one or more IntentFilters which specify the Intents which can be used to start, stop, and bind to it.

  • A Service can be registered with an associated permission that an Application must have been granted in order to access that Service.

  • The System will automatically create an instance of a Service Component and a process to run it if necessary.

2.0 Services And Intent Resolution

If an Intent explicitly specifies a component then the Intent resolves to that Component even if it is not a Service or does not exist.

Otherwise a search is made for all those Services with an associated Intent Filter which matches the Intent, as defined by the IntentFilter.match() method.

If the Intent specifies a package then the search is confined to the Services in that Application package.

If more than one Service is found then the Intent resolves to the Service with the highest priority as defined by the associated Intent Filter(s).

An Application can determine what Service, if any, an Intent resolves to using an implementation of the android.content.pm.PackageManager

    public abstract ResolveInfo resolveService(Intent intent, int flags)

method.

An Application can obtain a list of all Services which can handle a given Intent by using an implementation the android.content.pm.PackageManager

    public abstract List<ResolveInfo> queryIntentServices(Intent intent, int flags)

method.

If the list is not empty then it is ordered from most to least specific with the Service to which the Intent will actually resolve being the first element.

3.0 Starting A Service

A Service can be started by using an implementation of the android.content.Context

    public abstract ComponentName startService(Intent service)

method.

The Intent passed as the service argument specifies the Service to start.

If the given Intent resolves to a Service then the method returns a ComponentName which identifies it. If the identified Service is not already running then the System will run it creating a process if necessary and an instance of the Service component.

If the given Intent does not resolve to a Service the method returns null.

If the given Intent resolves to a Service but the Application calling the method has not been granted the permission necessary to access it then a SecurityException is thrown.

The method is asynchronous in the sense that if the Service is not already running the method will return before the System has actually started it.

4.0 Stopping A Service

A Service can be stopped by using an implementation of the android.content.Context

    public abstract boolean stopService(Intent service)

method.

The Intent passed as the service argument specifies the Service to stop.

The method returns true if the given Intent resolves to a running Service, false otherwise.

If the given Intent resolves to a running Service but the Application calling this method has not beeen granted the permission necessary to access it a SecurityException is thrown.

The method is asynchronous in the sense that the method can return true before the Service is stopped.

5.0 Binding To A Service

A client can bind to a Service using an implementation of the android.content.Context

    public abstract boolean bindService(Intent service, ServiceConnection conn, int flags)

method.

The Intent passed as the service argument specifies the Service to bind to.

The conn argument is used to specify an object which represents the binding to the Service and which implements the android.content.ServiceConnection interface.

This interface defines two methods

    public abstract void onServiceConnected(ComponentName name, IBinder service)

and

    public abstract void onServiceDisconnected(ComponentName name)

which are invoked asynchronously when the binding to the Service is set-up and broken-down respectively.

The flags argument is used to specify zero or more bit-flags. Probably the most useful of these is specified by the android.content.Context class-constant

    BIND_AUTO_CREATE

If this flag is set then the System will if necessary create an instance of the Service Component and, again if necessary, a process to run it in.

The method returns true if the given Intent resolves to a Service, otherwise false.

If the given Intent resolves to a Service but the Application calling the method has not been granted the permission necessary to access it then a SecurityException is thrown.

The effects of successfully binding to a Service are dependent upon the state of the Service at that point.

5.1 Binding To A Running Service

If the Service is already running then once the method has returned the binding object’s implementation of the onServiceConnected() method will be invoked with the name of the Service that has been bound to and an instance of IBinder that can be used to interact with that Service.

5.2 Binding To A Service That Is Not Running

The effects of sucessfully binding to a Service that is not running are dependent upon whether the BIND_AUTO_CREATE flag is set in the flags argument.

5.2.1 When BIND_AUTO_CREATE Is Set

If the BIND_AUTO_CREATE flag is set then the System will automatically run the Service, and once the method has returned the binding
object’s implementation of the onServiceConnected() method will be invoked with the name of the Service that has been bound to and an instance of IBinder that can be used to interact with that Service.

5.2.1 When BIND_AUTO_CREATE Is Not Set

If the BIND_AUTO_CREATE flag is not set then once the method returns nothing further will happen. The binding object’s implementation of the onServiceConnected() method will not be called unless and until the Service is run for another reason, for example, in response to an Application’s call to startService().

6.0 Associating Services And Intents

An Application can specify the Intents that can be used to interact with a given Service by defining one or more intent-filter elements as children of the service element used to define the Service itself.

For example,

    <service 
        android:name = "Malin">
        <intent-filter 
            android:priority = "4">
            <action 
                android:name = "xper.service.intent.SERVICE_MALIN_INTENT"/>
            <action 
                android:name = "xper.service.intent.SERVICE_SEA_AREA_INTENT"/>
        </intent-filter>
    </service>

7.0 Service Implementation And Intents

7.1 Starting

Each time the startService() method is called and a matching Service is found, then that Service’s

    public int onStartCommand(Intent intent, int flags, int startId)

method is invoked.

A Service implementation can override the default implementation of this method to access the Intent used to start it.

This makes it possible to pass arguments to a Service when starting it, and/or use the startService() method as a one-way IPC mechanism.

7.2 Stopping

There is no way for a Service implementation to access the Intent used to stop it.

7.3 Binding

Each time the bindService() method is called and a matching Service is found then that Service’s implementation of the android.app.Service

    public abstract IBinder onBind(Intent intent)

method is invoked at some point.

Hence the Intent used to bind to a Service is always accessible to the Service implementation.

8.0 Interacting With A Specific Service

It is possible to start, stop, or bind to a specific Service by explicitly specifying the Service Component in the Intent being used to perform the operation.

For example, if the following is defined

    <service 
        android:name = "Rockall">
        <intent-filter>
            <action 
                android:name = "xper.service.intent.SERVICE_ROCKALL_INTENT"/>
            <action 
                android:name = "xper.service.intent.SERVICE_SEA_AREA_INTENT"/>
        </intent-filter>
    </service>

in the Application package

    xper.service.rockall

then the Service can be started by executing the following

    startService(
        new Intent(
                "xper.service.intent.NON_EXISTENT_SERVICE_INTENT").
            setClassName(
                "xper.service.rockall", 
                "xper.service.rockall.Rockall").
            setType(
                "nonexistent/type"));

Note that the presence of an explicit component in an Intent overrides everything else in the Intent.

One quite interesting implication of this is that any Service which is not explicitly protected by a permission and whose Component name can be discovered can be sent an Intent containing absolutely anything.

9.0 “Anonymous” Services

It is possible to specify a Service without any associated IntentFilters, for example,

    <service android:name = "AnonymousService"/>

The Service can still be started, stopped, and bound to by using an Intent with an explicit component name as described above.

For example, assuming the Service above is defined in the Application package xper.app.anonymousservice, then it can be started like this

    startService(
        new Intent().
            setClass(
                "xper.app.anonymousservice",
                "xper.app.anonymousservice.AnonymousService"))

but only from within the Application that defines the Service. Attempting to interact with the Service from anywhere else will result in a SecurityException.


Copyright (c) 2011 By Simon Lewis. All Rights Reserved.

Advertisements

5 Comments »

  1. […] The transient nature of a statically registered BroadcastReceiver means that its onReceive() method cannot use any functionality which is asynchronous, for example, binding to a Service. […]

    Pingback by The Android Intent Based APIs: Part Six – Broadcast Intents « Just An Application — February 17, 2011 @ 2:52 pm

  2. […] well as being used in conjunction with Activites and Services Intents can also be used as broadcast […]

    Pingback by The Android Intent Based APIs: Part Six – Broadcast Intents « Just An Application — February 17, 2011 @ 2:52 pm

  3. […] Android Service must pass an instance of a class which implements this interface when it calls the bindService() […]

    Pingback by Adventures In Distributed Garbage Collection: Part Two – Setting The Scene: Interfaces And Base Classes « Just An Application — May 14, 2012 @ 6:15 pm

  4. […] start that Service explicitly, or […]

    Pingback by Adventures In Distributed Garbage Collection: Part Six – Service Creation « Just An Application — May 17, 2012 @ 12:13 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: