Services

Table of Contents

  1. Introduction
  2. Started service as IntentService
    1. Sending local broadcast message
    2. Listening for a local broadcast message
  3. Started service as Service
  4. Bound service with Binder class
  5. Bound service with Messanger
  6. Bound service with AIDL

Introduction

A service is an application component that can perform long-running operations in the background and does not provide a user interface. A service can essentially take two forms:

Started
A service is “started” when an application component (such as an activity) starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller.
Bound
A service is “bound” when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.

Any service can work both ways—it can be started (to run indefinitely) and also allow binding. It’s a matter of whether we implement a necessary callback methods onStartCommand() to allow components to start it and onBind() to allow binding.

Simple in theory, Android services are quite complicated in practise mainly because service can be realized in many different ways.

Service as an IntentService
IntentService is a simple type of service that can be used to handle asynchronous work off the main thread by way of Intent requests. Each intent is added to the IntentService’s queue and handled sequentially. An operation running on an IntentService can’t be interrupted. IntentService is one of the simplest ways to offload the UI thread of application. To do this we have to define service (as IntentService), package up an intent with the appropriate data we want to send for processing, and start the service. To send data back to the application we broadcast the result as an Intent object, and use a broadcast receiver to catch the result within the app.
Service as a Service
Using IntentService makes an implementation of a service very simple. If, however, we require to perform multi-threading (instead of simply processing start requests through a work queue), then we can extend the base Service class to handle each intent.
Bound service
When creating a service that provides binding, we must provide an IBinder that provides the programming interface that clients can use to interact with the service. There are three ways we can define the interface:

  1. Extending the Binder class. If the service is private to the application and runs in the same process as the client (which is very common), we should create an interface by extending the Binder class and returning an instance of it from onBind() method. The client receives the Binder and can use it to directly access public methods available in either the Binder implementation or even theService. This is the preferred technique when the service is merely a background worker for an application. The only reason we would not create an interface this way is because the service is used by other applications or across separate processes.
  2. If we need the interface to work across different processes, we can create an interface for the service with a messenger (Messenger). In this manner, the service defines a handler (Handler) that responds to different types of message objects. This handler is the basis for a messenger that can then share an IBinder with the client, allowing the client to send commands to the service using Message objects. Additionally, the client can define a Messenger of its own so the service can send messages back. This is the simplest way to perform interprocess communication, because the messenger queues all requests into a single thread so that we don’t have to design the service to be thread-safe.
  3. Using AIDL (Android Interface Definition Language) performs all the work to decompose objects into primitives that the operating system can understand and marshall them across processes to perform IPC. The previous technique, using a messenger, is actually based on AIDL as its underlying structure. As mentioned above, the messenger creates a queue of all the client requests in a single thread, so the service receives requests one at a time. If, however, we want the service to handle multiple requests simultaneously, then we can use AIDL directly. In this case, the service must be capable of multi-threading and be built thread-safe. To use AIDL directly, we must create an .aidl file that defines the programming interface. The Android SDK tools use this file to generate an abstract class that implements the interface and handles IPC, which we can then extend within the service.

Service as an IntentService

To use IntentService we have to implement only one method: onHandleIntent(). This method is where processing occurs. Any data necessary for processing request can be packaged in the intent extras.

Do not forget to declare service in manifest. Add a <service> element as a child of the <application> element. For example:

Now we can start the service from application activity and delegate the processing to the service.

That is all. The question is how to return some results to application from IntentService? Thers is no any dedicated mechanism for this. Standard approach is to broadcast the result as an Intent object, and use a broadcast receiver to catch the result within the app.

However we can consider to use LocalBroadcastManager. This has a number of advantages over sending global broadcasts with standard sendBroadcast(Intent):

  • We know that the data we are broadcasting won’t leave our app, so don’t need to worry about leaking private data.
  • It is not possible for other applications to send these broadcasts to our app, so we don’t need to worry about having security holes they can exploit.
  • It is more efficient than sending a global broadcast through the system.

The LocalBroadcastManager used to send local broadcast messages is not part of the “normal” Android API.  It is part of the Android Support package.  In order to add the Android Support package to your Android application environment, open the Android SDK Manager, find the “Extras” folder and select Android Support package for installation. Once the Support package is part of your environment, make sure the package is available to your project.

Sending local broadcast message

Listening for a local broadcast message

Service as a Service

To use Service we have to override some callback methods that handle key aspects of the service lifecycle and provide a mechanism for components to bind to the service, if appropriate. The most important callback methods we should override are:

onStartCommand()
The system calls this method when another component, such as an activity, requests that the service be started, by callingstartService(). Once this method executes, the service is started and can run in the background indefinitely. If we implement this, it is our responsibility to stop the service when its work is done, by calling stopSelf() or stopService(). In case we want only to provide binding, we don’t need to implement this method.
onBind()
The system calls this method when another component wants to bind with the service, by calling bindService(). In our implementation of this method, we must provide an interface that clients use to communicate with the service, by returning an IBinder. We must always implement this method, but if we don’t want to allow binding, then we should return null.
onCreate()
The system calls this method when the service is first created, to perform one-time setup procedures, before it calls either onStartCommand() or onBind(). If the service is already running, this method is not called.
onDestroy()
The system calls this method when the service is no longer used and is being destroyed. The service should implement this to clean up any resources such as threads, registered listeners, receivers, etc. This is the last call the service receives.

 

Notice that the onStartCommand() returns an integer startMode. The integer is a value that describes how the system should continue the service in the event that the system kills it. The return value fromonStartCommand() must be one of the following constants:

START_NOT_STICKY
If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.
START_STICKY
If the system kills the service after onStartCommand() returns, recreate the service and callonStartCommand(), but do not redeliver the last intent. Instead, the system calls onStartCommand() with a null intent, unless there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
START_REDELIVER_INTENT
If the system kills the service after onStartCommand() returns, recreate the service and callonStartCommand() with the last intent that was delivered to the service. Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.

Finally do not forget to declare service in manifest.

Now we can start the service from application activity and delegate the processing to the service as we did it for IntenService

The startService() method returns immediately. If the service is not already running, the system first calls onCreate(), then calls onStartCommand().

If the service does not also provide binding, the intent delivered with startService() is the only mode of communication between the application component and the service. However, if we want the service to send a result back, then we can use again approach described in IntentService.

Multiple requests to start the service result in multiple corresponding calls to the service’s onStartCommand(). However, only one request to stop the service (with stopSelf() or stopService()) is required to stop it.

Bound service with Binder class

If the service is used only by the local application and does not need to work across processes, then we can implement Binder class which provides the client direct access to public methods in the service. This works only if the client and service are in the same application and process.

To use this approach we have to:

  1. In the service, create an instance of Binder that either:
    • contains public methods that the client can call
    • returns the current Service instance, which has public methods the client can call
    • or, returns an instance of another class hosted by the service with public methods the client can call
  2. Return this instance of Binder from the onBind() callback method.
  3. In the client, receive the Binder from the onServiceConnected() callback method and make calls to the bound service using the methods provided.

The LocalBinder provides the getService() method for clients to retrieve the current instance of ServiceWithBind. This allows clients to call public methods in the service. The code below shows how the client binds to the service using an implementation of ServiceConnection and the onServiceConnected() callback.

Clients can bind to a service by calling bindService(). The system then calls the service’s onBind() method, which returns an IBinder for interacting with the service. The binding is asynchronous. bindService() returns immediately and does not return the IBinder to the client. To receive the IBinder, the client must create an instance of ServiceConnection and pass it to bindService(). The ServiceConnection includes a callback method that the system calls to deliver the IBinder.

So, to bind to a service from your client, we have to:

  1. Implement ServiceConnection and override two callback methods:
    onServiceConnected()
    The system calls this to deliver the IBinder returned by the service’s onBind() method.
    onServiceDisconnected()
    The system calls this when the connection to the service is unexpectedly lost, such as when the service has crashed or has been killed. This is not called when the client unbinds.
  2. Call bindService(), passing the ServiceConnection implementation.
  3. When the system calls onServiceConnected() callback method, we can begin making calls to the service, using the methods defined by the interface.
  4. To disconnect from the service, call unbindService().When the client is destroyed, it will unbind from the service, but we should always unbind when we are done interacting with the service or when the activity pauses so that the service can shutdown while its not being used.

Only activities, services, and content providers can bind to a service. It is not possible to do this from a broadcast receiver.

Bound service with Messanger

In case we want the service to communicate with remote processes, then we can use a Messenger to provide the interface for the service. This technique allows to perform interprocess communication (IPC) without the need to use AIDL.

To use a Messenger we have to:

  • Implements in the service a Handler that receives a callback for each call from a client.
  • The Handler is used to create a Messenger object (which is a reference to the Handler).
  • The Messenger creates an IBinder that the service returns to clients from onBind().
  • Clients use the IBinder to instantiate the Messenger (that references the service’s Handler), which the client uses to send Message objects to the service.
  • The service receives each Message in its Handler‘s handleMessage() method.

From the above we can see that, there are no “methods” for the client to call on the service. Instead, the client delivers “messages” (Message objects) that the service receives in its Handler.

Let’s take a look into the following example of server.

All that a client needs to do is create a Messenger based on the IBinder returned by the service and send a message using send().

Notice that with Messenger we create only one direction connection (in this case from the client to the service). If we want the service to respond, then we need to also create a Messenger in the client. Then when the client receives the onServiceConnected() callback, it sends a Message to the service that includes the client’s Messenger in the replyTo parameter of the send() method.

Bound service with AIDL

This is the most advanced (complicated) tehinque. Services with AIDL are quite well described in http://developer.android.com/guide/components/aidl.html

Broadcast Receiver

Table of Contents

  1. Introduction
  2. Creating the broadcast receiver
  3. Registering broadcast receiver
  4. Creating and registering broadcast receiver dynamically
  5. Broadcasting Custom Intents
  6. Broadcast methods
  7. sendBroadcast() with permissions
  8. sendOrderedBroadcast() to get feedback from receivers
  9. Force the bradcast receive order
  10. Restrictions for defining broadcast receiver
  11. Asynchronous processing
  12. Examples of system generated events
  13. Working example

Introduction

A broadcast receiver is an Android component which allows you to register for system or application messages called also events or intents. All receivers registered for a given message (event) are notified by the Android runtime once this event happens.For example, applications can register for the SMS_RECEIVED event which is fired once the sms messsage is recieved. Broadcast receiver is this who will intercept this event and will initiate appropriate action.

We can register for predefined events but, what is more important, we can also defined and emmit our own events.

Generaly there are two steps to make broadcast receiver works for the systen broadcasted intents:

  1. Creating the Broadcast Receiver.
  2. Registering Broadcast Receiver

There is one additional steps in case you are going to implement your custom events then you will have to create and broadcast those events.

Creating the Broadcast Receiver

A broadcast receiver is implemented as a subclass of BroadcastReceiver class and overriding the onReceive() method where each message is received as a Intent object parameter.

Registering Broadcast Receiver

A receiver can be registered via the AndroidManifest.xml file.

Creating and registering broadcast receiver dynamically

Alternatively to the static registration, you can also create and register a receiver dynamically via the Context.registerReceiver() method.

Notce that dynamic registration allows to listen for events only when our application is active. When receiver is registered with manifest file, our applicarion would be executed even when is inactive (in oher words, we listen for events all the time).

Broadcasting Custom Intents

If you want your application itself can generate and send custom events. You have to create and send such an events by using the sendBroadcast() method inside your activity class.

The event some.unique.url.CUSTOM_EVENT can also be regsitered in similar way as we have regsitered system generated events so far. Remember to use unique name for your event (best practice is to use url in reverse oreder).

Broadcast methods

There are few different methods which allows to broadcast events.

  1. sendBroadcast(Intent intent) This is the simplest form of broadcast sending method. Broadcast the given intent to all interested BroadcastReceivers.
  2. sendBroadcast(Intent intent, String receiverPermission) Broadcast the given intent to all interested BroadcastReceivers, allowing an optional required permission to be enforced.
  3. sendOrderedBroadcast(Intent intent, String receiverPermission) Broadcast the given intent to all interested BroadcastReceivers, delivering them one at a time to allow more preferred receivers to consume the broadcast before it is delivered to less preferred receivers.
  4. sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) Version of sendBroadcast(Intent) that allows you to receive data back from the broadcast.

When a broadcast intent is sent using the sendBroadcast() method, there is no way for the initiating activity to receive results from any broadcast receivers that pick up the broadcast. If the return results are required, it is necessary to use the sendOrderedBroadcast() method instead. When a broadcast intent is sent using this method, it is delivered in sequential order to each broadcast receiver with a registered interest.The sendOrderedBroadcast() method is called with a number of arguments including a reference to another broadcast receiver (sendOrderedBroadcast(..., BroadcastReceiver resultReceiver, ...)), known as the result receiver, which is to be notified when all other broadcast receivers have handled the intent, together with a set of data references into which those receivers can place result data. When all broadcast receivers have been given the opportunity to handle the broadcast, the onReceive() method of the result receiver is called and passed the result data.

sendBroadcast() with permissions

Sending broadcats with permissions is not complicated

More important is to correctly controll the permissions. In one application, tipically broadcast sender, we have to define permissions

while in other, typically receiver(s), we have to ask for a permission(s) that the application must be granted in order for it to operate correctly.

Note that we may also declare the element in both apps, so the order of their installation does not matter. Otherwise, the app has to be installed before the app.

sendOrderedBroadcast() to get feedback from receivers

See the complete example below for  details about sendOrderedBroadcast()

Force the broadcast receive order


Code above allows us to define the order in which receivers would be called. Always the last receiver is the receiver which is registered dinamically.

Restrictions for defining broadcast receiver

As of Android 3.1 the Android system excludes all receiver from receiving intents by default if the corresponding application has never been started by the user or if the user explicitly stopped the application via the the application manager on the device. This is an additional security feature as the user can be sure that only the applications he started will receive broadcast intents. This does not mean the user has to start the application again after a reboot. The Android system remembers that the user already started it. Only one start is required without a forced stop by the user. To get around this, however, a flag can be added to the intent before it is sent to indicate that the intent is to be allowed to start a component of a stopped application. This flag is FLAG_INCLUDE_STOPPED_PACKAGES

Asynchronous processing

Before API level 11, you could not perform any asynchronous operation in the onReceive() method, because once this method had been finished, the Android system was allowed to recycle that component. In such a case if you have potentially long running operations, you should trigger a service instead.Since Android API 11 you can call the goAsync() method. This method returns an object of the PendingResult type. The Android system considers the receiver as alive until you call the PendingResult.finish() on this object. With this option you can trigger asynchronous processing in a receiver. As soon as that thread has completed, its task calls finish() to indicate to the Android system that this component can be recycled.

Examples of system generated events

Event Constant Description
android.intent.action.BATTERY_CHANGED Sticky broadcast containing the charging state, level, and other information about the battery.
android.intent.action.BATTERY_LOW Indicates low battery condition on the device.
android.intent.action.BATTERY_OKAY Indicates the battery is now okay after being low.
android.intent.action.BOOT_COMPLETED This is broadcast once, after the system has finished booting.
android.intent.action.BUG_REPORT Show activity for reporting a bug.
android.intent.action.CALL Perform a call to someone specified by the data.
android.intent.action.CALL_BUTTON The user pressed the “call” button to go to the dialer or other appropriate UI for placing a call.
android.intent.action.DATE_CHANGED The date has changed.
android.intent.action.POWER_CONNECTED Power got connected to the device.
android.intent.action.POWER_DISCONNECTED Power got disconnected to the device.
android.intent.action.REBOOT Have the device reboot.
android.intent.action.TIME_TICK Event send every minute to indicate that time has changed.
android.provider.Telephony.SMS_RECEIVED Indicates the SMS was received.

Working example