Android development blog
Tutorials about Android dev topics

Android Service Tutorial

by Francesco Azzola, January 2, 2014
Topics covered

Android Service

Android IntentService

Android Broadcast receiver and Service

In this post, we want to talk about Android Service. This is a key component in developing Android app. Differently from Activity, Service in Android runs in background, they don’t have an interface and have a life-cycle very different from Activities. Using Service we can implement some background operation, for example we can suppose we want to load a web page from a remote server. Using a Service we can implement multitask in Android.

Service Overview

We already know that Android Activity can be started, stopped, destroyed if the system resources become too low and maybe can be recreated, a Service are designed to have a longer life. A Service in Android can be started from an Activity, from a Broadcast receiver and other services too.
We have to notice that using Service we don’t create automatically new threads, so if we implement a simple logic inside our Service, that doesn’t require long time processing we don’t need to run it a separate thread, but if we have to implement complex logic, with long time processing, we have to take care of creating a new thread, otherwise the service runs on the main thread and it could cause ANR problem.
In Android a Service is used for two main reason:
  • Implement multi-task
  • Enable Inter-Process-Communication (IPC)
A typical example of the first case is an app that required to download data from a remote server, in this case we can have Activity that interacts with a user and starts a service that accomplishes the work in background while the user can use the app and maybe when the service finishes sends a message to the user.
In the second case, we want to “share” some common functions so that different app can re-use them. For example, we can suppose we have a service that sends an email and we want to share this service among several apps so that we don’t have to rewrite the same code. In this case we can use IPC so that the service exposes a “remote” interface that can be called by other app.
In this post, we cover the first case, in this case we have a local service, local means that the service can be seen just inside our apk.



Service basic

Now we know more about Service, we want to create it. In Android to create a Service we have to extend Service class.
public class TestService extends Service {

    @Override
    public IBinder onBind(Intent arg0) {        
        return null;
    }

}
As we can see, we have to implement only one method called onBind. In our case, we are using local service, so this method should return null. As we mentioned before, a Service has its lifecycle and we can override some callback methods so that we can handle its different states:
public class TestService extends Service {

    @Override
    public void onCreate() {        
        super.onCreate();
    }

    @Override
    public void onDestroy() {        
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {        
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent arg0) {        
        return null;
    }

}
The first method onCreate is called only one time when the Service has to created. If the Service is already running this method won’t be called. We don’t call it directly but it is the OS that calls it.
OnStartCommand is the most important method because it is called when we required to start the Service. In this method we have the Intent passed at time we run the Service, in this way we can exchange some information with the Service. In this method, we implement our logic that can be execute directly inside this method if it isn’t time expensive otherwise we can create a thread. As you can see this method requires we return an Integer as result. This integer represents how the Service should be handled by the OS:

  • START_STICKY : Using this return value, if the OS kills our Service it will recreate it but the Intent that was sent to the Service isn’t redelivered. In this way the Service is always running
  • START_NOT_STICKY: If the SO kills the Service it won’t recreate it until the client calls explicitly onStart command
  •  START_REDELIVER_INTENT: It is similar to the START_STICKY and in this case the Intent will be redelivered to the service.

OnDestroy is the method called by the OS when the Service will be destroyed.

Once we have our service class, we have to declare it in the Manifest.xml so that we can use it:
<service android:name=".TestService" 
         android:enabled="true"/>

Start and Stop Service

As we know a Service has to be started and eventually stopped so that it can accomplish its task. We can suppose to start it from an activity and we could pass to the service some information using Intent. We can suppose that our Activity has two buttons one to start and one to stop the Service:
btnStart.setOnClickListener(new View.OnClickListener() {
    
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        i.putExtra("name", "SurvivingwithAndroid");        
        MainActivity.this.startService(i);        
    }
});


btnStop.setOnClickListener(new View.OnClickListener() {
    
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        MainActivity.this.stopService(i);
    }
});

In the code above at line 5, we create an Intent passing the class name that handles our Service, moreover we set some params like name and then we start the Service at line 7. In the same way, at line 17 we stop the service.

android_service

Clicking on Start button we get in the Log:

android_service_start_log
We can notice that the onCreate method is called because it is the first time we start the service, if we click again on start button the OS doesn’t call onCreate method. When we click on stop button the OS destroy the service.

IntentService

As we mentioned before a service runs on the main thread, so we have to be very careful when we implement some logic in this service. We have to consider that if this logic is a blocking operation or it requires long time to finish a ANR problem could occur. In this case we have to move our logic to a separate thread, meaning we have to create a thread in onStartCommand method and run it.
There is another class called IntentService derived from Service that simplify our life. This class is useful when we don’t need to handle multiple requests at the same time. This class creates a worker thread to handle different requests. This class performs this operation:
  • create a separate thread to handle the request
  • create a request queue and pass one Intent at time
  • create a default implementation of onStartCommand
  • stop the service when all the requests are processed
If we want to create a IntentService we have to extend IntentService class instead of Service:
public class TestIntentService extends IntentService {
        
    public TestIntentService() {
        super("TestIntentService");        
    }

    @Override
    protected void onHandleIntent(Intent intent) {
       
        
    }

}
In this case we have only one method to implement called onHandleIntent. Here we implement out logic without caring if this is operation requires long time or not, because this method is called in a separate thread.

Starting service automatically

Many times we want to start our service automatically, for example at boot time. We know to start a Service we need a component to start it. How can we do it? Well, we could use a Broadcast receiver that starts our service. If for example we want to start it at the smartphone boot time, we create first a Broadcast receiver that listens to this event and then it starts the service.
public class BootBroadcast extends BroadcastReceiver {

    @Override
    public void onReceive(Context ctx, Intent intent) {        
        ctx.startService(new Intent(ctx, TestService.class));
        
    }

}
and in the Manifest.xml
<receiver android:name=".BootBroadcast">    
    <intent-filter >
        <action android:name="android.intent.action.BOOT_COMPLETED"/>                
    </intent-filter>
</receiver>

No comments:

Post a Comment

Related Posts with Thumbnails