Services – An Android Component

As an android developer you must have know the major components of android in very detailed manner. If not don’t worry!!

 

Today I am writing here to help you guys to get through one of the major component of Android i.e. “Service”. If you are a beginner you would probably think why we would need services in our coding. If this is the case you might becomes the services FAN 😉 by the end of this tutorial.

 

You will understand how important role a service will play for a developer. Eventually you will come to know that they always play a important role in designing when you integrate them with web services, or have an application logic which will bound you beyond the UI i.e. If you need to start long running tasks in response to user input, then you should not expect the UI to wait for the result.

user interface image

A service is an application component that implements and performs long running operations in the background without any need to interact with the user. Services also handle the background processing associated with the application. A service started by an application will be continuing to running in background even when user switches to another application component.

 

While developing services, you must always have few key questions in your mind like:

 

 

    • How to communicate with the service from an Activity/Fragment?
    • How to communicate with the Activity/Fragment from a service?
    • How to keep my service from being killed?

     

    You will get the answers of all these questions by the end of this tutorial. I will explain each in a very good detail.

     

    In android we have following two states that are essentially taken by a service.

     

    • Started startService()
    • Bound bindService()

     

    Lets see these states in a bit more detail:

     

    Started: A service is started with calling startService() by an application component (such as an activity). A service is once started it will keep running in the background for indefinite time even if the component that started is destroyed. A single operation is performed by a started service and it doesn’t return any result to the caller.

     

    Bound: A service is bound by an application component by calling bindService( ). A bound service allows an application component to interact with service by offering a client-server interface that enables a component to send requests, get results and even do so across processes with inter-process communication (IPC). A bound service runs as long as another application component bound to it. Multiple components can be bind to a service but when all of them unbind, the service is destroyed.

     

    In the remaining tutorial I will be going to explain you how to start, stop and create a service and the service life cycle. Let’s have a look on each one by one.

     

    How to Start a service

     

    A service can be started from an activity or other application by passing an intent (specifying the service to start) to startService(). The android system calls the service’s onStartCommand() method and passes it the intent. onStartCommand() can be never called directly. Following is an example shows that an activity can start the example service in the previous section (HelloService) using an explicit intent with startServie().

     

 

Intent intent = new Intent(this, HelloService.class);
startService(intent);

 

If there are multiple requests to start the service then it results 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.

 

How to Stop a service:

 

A started service must manage its own lifecycle. It means the system doesn’t stop or destroy the service unless it must recover system memory and service continues to run after onStartCommand() returns. So the service must stop itself by calling stopSelf() or another component can stop it by calling stopService(). System will destroy the service as soon as possible once it requested to stop with stopSelf() or stopService().

 

How to Create a service (unBounded):

 

  • In android a service can be created by extending the service class and adding a service tag to Android Manifest. You must override the method onCreate(), onStart(),  onStartCommand(), and onDestroy() after extending the class.
  • onStart() and onStartCommand() methods are essentially similar, the only which differs both is that onStart() method has been deprecated in API level 5 and above. J
  • If context.startService() is used to create a service by the system. The method onCreate() is called just before onStart() or onStartCommand().
  • If the service is bound with a call to context.bindService() method, the onCreate() method is called just before the onbind() method.onStart() and  onStartCommand() are not called in this case.

 

Creating a started services

 

A started service can be defined as the service which another component starts by calling startService(), results in a call to service’s onStartCommand() method. This started service has a lifecycle that is independent of the component that started it and service will keep running in background for indefinite time ,even the component is destroyed that started the service. When its job is completed it should stop itself by calling stopSelf() or another component will stop it by calling stopService().

 

The service can be started by an application component such as an activity by calling startService() and passing an intent that specifies the service and includes any data for service’s use. This intent is received by service onStartCommand() method.

 

For instance some data needs to be store on online database by an activity. Then activity can start an associated service and deliver the data to save by passing an intent to startService(). The intent is received by the service in onStartCommand(), which connects to the internet and perform a database transaction. Service will stop itself and destroyed when the transaction is completed.

command

 

 

NOTE: By default a service runs in the same process as the application and main thread of the application by which it is declared, so if this service performs extensive or obstructing operation while a user is interacting with an activity in same application then this service will slow down the activity performance. A new thread should be start inside the service in order to avoid impact on application performance.

 

Conventionally there are following two types of classes that can be extend to create a started service:

 

Service: Service class is the base class for all the services. Its important to create a new thread in which you should do all the services work. Because service uses main thread of your application by default which can cause slow performance of an activity your application is running.

 

IntentService: This class can be defined as the subclass of services. A worker thread is used by this subclass to handle all start requests one at a time. It is a best option for you, if you don’t want your service to handle multiple requests simultaneously. So now you need to do is implement onHandleIntent(), which will receive intent for each start requests so you can do the background work.

 

Creating a bound service

A bound service can be defined as a service which allows application component to bind it by calling bindService(). It creates a long standing connection and generally doesn’t allow component to start it by calling startService().

 

Bound service should be created when you want to interact with service from an activity and other components of your application or to expose some of your application’s functionality to other application through inter-process communication (IPC).

 

For the creation of bound service, on implementing the onBind() call back method, it returns an iBinder for defining an interface for communication with service and then other application components can call bindService(). There service only serves to the application which is bound to it, so when there are no components bound to the service, it destroyed by the system. If any service started through onStartCommand() you must stop the service in the way whereas you don’t need to stop a bound service in the way.

 

The first thing you must do is define the interface that specifies how a client can communicate with the service while creating a bound service. This interface between the service and a client must be implemented by IBinder  and it should be what your service must return from the onBind() callback method. Client can begin interacting with the service through the interface once the client receives the ibinder.

 

Multiple clients can bind to the service at a time. When a client’s interaction with service is done, it calls unbindService() to unbind. If there are no clients bound to the service , the system destroys the service.

 

Sending notification to the user

If any service is running, it can give the notification to the user of events using Toast notification or Status Bar Notification.

 

A toast notification can be defined as the message which appears on the surface of current window for a moment then disappears.

 

Status Bar Notification can be defined as a message which appears in the status bar with a message, which the user can select in order to take an action such as start an activity.

 

Generally status bar notification is a best technique, it can be used when some background work has been completed like as download completed, so the user can take an action on it. When the user selects a notification from the expanded view then it starts an activity such as showing downloaded file.

 

Running a service in the foreground

A foreground service can be defined as the service that is considered to be the service the user is actively aware about. Foreground service must provide a notification for the status bar, which is placed under the ongoing heading. It means unless the service is either stopped or removed from the background, the notification can not be dismissed.

 

For example, a music player that plays music from a service should be set to run in the foreground, because the user is explicitly aware about its operation. The notification in the status bar might indicate the current song and allow the user to launch an activity to interact with the music player.

 

If you want your service to run in the foreground it can be requested by calling startForeground(). This method takes only two parameters one is integer that is used to identify the notification and the notification for the status bar.

 

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
        System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
        getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

 

Note: – The integer id given to startForeground() must not be 0.

 

The service from the foreground may be removed by calling stopForeground(), this method takes a Boolean , which indicates whether to remove the status bar notification as well. The service doesn’t stop by this method, however if service is stopped, it is still running in the foreground and the notification is also removed.

 

Service life cycle

 

A service has lifecycle callback methods that can be implemented to monitor the changes in the service’s state so that you can perform work at the appropriate stage. The following diagram illustrates a lifecycle of service. Left side of diagram shows the lifecycle when the service is created by calling startService() and the right side of  diagram shows the lifecycle when the service is created by calling bindService().

 

service

 

 

The service base class defines variety of methods and most important methods are given below. There is no any need of implement all the callback methods, however it’s important to understand each method and implement those that ensure your application’s behavior according to the user’s expectations. Following are the lifecycle methods.

 

  • Oncreate()
  • onStartCommand()/onStart()
  • onBind()
  • on unbind()
  • on rebid()
  • on destroy()

 

The code below will describe how you can define a service and its methods in coding:

 

public class ExampleService extends Service {

@Override

public void onCreate() {

...

}

@Override

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

...

}

@Override

public IBinder onBind(Intent intent) {

...

}

@Override

public boolean onUnbind(Intent intent) {

...

}

@Override

public void onRebind(Intent intent) {

...

}

@Override

public void onDestroy() {

}

 

The entire lifetime of a service can be defined as the time difference between the time onCreate() ,is called and the time onDestroy() returns.

 

  • onCreate() and onDestroy() method is called for all services whether they are started by startService()  or bindService().
  • A service does its initial setup in onCreate() and releases all remaining resources in onDestroy(). For example, a music playback service could create a thread where the music will be played in onCreate(), and all threads will end in onDestroy().
  • The active lifetime of service begins with the call to either onStartCommand() or onBind(). Each method that is handed to intent , will pass to either startService() or bindService() respectively.
  • The service is still active even after startCommand ()returns. If the service is bound, the active lifetime ends when unbind() returns.

 

Managing the lifecycle of service

 

The difference between the times from when a service is created to the time when it is destroyed is known as the lifecycle of a service.

 

The life cycle of a service is much simpler than that of an activity. However it is much more important to pay a close attention to the lifecycle of services because it tells you when your service is created and when your service is destroyed. Usually the service runs in the background without letting the user know about it.

 

  • The started service is created when another component calls startService(). The service then runs indefinitely and stop itself by calling stopSelf(). Another component can stop this service by calling stopService(). Service is destroyed once it is stopped.

 

  • A bound service is defined as the service is created when a client (it may be another component) calls bindService(). IBinder interface allows clients to communicate with service. Multiple client can bind to the same service and system destroys the service when all of the clients unbind.(the service doesn’t need to stop itself)

 

  • The above two points are not completely separate i.e. you can bind to a service that was already started with startService(). For example a background music service could be started by calling startService( ) with an Intent that identifies the music to play. Later when a user wants to get some control over the player or get information about the current song, bindService( ) will be used to bind an activity to the service by calling bindService(). In such cases a service can not be stop by calling stopService() or stopSelf() until all clients

 

Implementation of lifecycle callbacks

 

Like an activity, a service has lifecycle callback methods. These methods can be implemented to monitor the changes in state of service and perform work at appropriate times. Following is the demonstration of each of the lifecycle callback methods in skeleton services.

public class ExampleService extends Service {
    int mStartMode;       // indicates how to behave if the service is killed
    IBinder mBinder;      // interface for clients that bind
    boolean mAllowRebind; // indicates whether onRebind should be used

    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return mAllowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

 

Service and android manifest

 

I hope you enjoyed the lifecycle details and will try the service very soon next time whenever you code. Let us now have a look on how you can define your service in the manifest file son that your activity and your application must know that a service is going to be handled soon!!!!

 

Make sure you must declare your manifest into the manifest otherwise your app will got crash and it won’t run.

 

  • All services must be declared in your android system’s manifest. A system will not recognize the service if it has not been declared in the android manifest using <service tag>.
  • To enable a service, a service name can also be defined in XML block.
  • <service>——</service> element is a child of <application>…</application>
  • There are other attributes which can be included in <service>…</service> element to define properties like as permission required to start the service and the process in which a service would run.
  • The android:name attribute is only required attribute which is used to define the class name of service.
  • Once an application has published it should not be change, if you do this you can risk of breaking the code due to dependency on explicit intents to start or bind the service.

 

 

 

 

I will explain this to you with a short example. Try the code given below:

 

 

<manifest ... >
  ...
  <application ... >
      <service android:name=".ServiceExample" />
      ...
  </application>
</manifest>

 

This is how you declare your service in manifest file.

 

  • You should always use an explicit content while starting or binding your service, Use of an implicit intent filter for a service is not a good practice.

 

If it is a critical case in which you are uncertain as to which service should start first ,intent filter can be a good option. But you must set the package of the intent with setPackage(), which provides sufficient certainties for target service. Furthermore you can ensure that your service is available to only your app by including the android: exported attribute and setting it to “false”. It prevents other apps from starting your service adequately even when you are using an explicit intent.

 

That’s it!!! 🙂

Leave a Comment: