[Tutorial] Developing Android Background Services

Welcome!

In this post, I’ll show you how to develop background services on Android Studio. We’ll see two type of services: Service and IntentService.

Let’s check !

Android Studio Tutorial

I - About Android Tutorials

I’ll be creating a big number of Android tutorials, showing you how to use nice libraries, UI, tips, and more.

I’ll be using Android Studio and Gradle in all tutorials.

If you need some help with any Android lib or feature, feel free to comment here and if possible, I can write a new tutorial about it :)

Source Codes:

Get updates Follow @aron-bordin
Star it: Star
Contribute: Fork
Download: Download

II - Android Background Services

You may want to use a background service when you are developing some feature that doesn’t requires a user interface or interaction, maybe running a continuous service that check a server status, downloading a file, installing android packages, etc.

Android provides two types of services: IntentService and Service.

Service is the base class for any Android background service. This class provides you some methods to execute and kill your background service. It runs on your main thread, so it’s recommended to start a new thread to avoid UI blocking.

IntentService is a simpler Service that already runs in a separated thread and self destroy after processing everything.

Let’s implement the two services and see it in action.

III - Creating an Android Studio Project

Start creating a simple Android Studio project with a Blank Activity. We’ll use the same project to test both Service and IntentService.

Plese, take a look in the official documentation for more information about lifecycle and these classes.

IV - Implementing an IntentService

In the IntentService we’ll simulate a cpu-blocking task, such as processing a file, compressing an image, etc.

Start creating a new class, TutorialIntentService that extends the IntentService.

Implementing the required methods, you should have something like this:

public class TutorialIntentService extends IntentService{

  public TutorialIntentService() {
     this(TutorialIntentService.class.getName());
  }


  /**
   * Creates an IntentService.  Invoked by your subclass's constructor.
   *
   * @param name Used to name the worker thread, important only for debugging.
   */
  public TutorialIntentService(String name) {
      super(name);
  }

  @Override
  protected void onHandleIntent(Intent intent) {

  }
}

The Intent service is a simpler service. When this service is executed, the onHandleIntent method will be executed. It’s already running on a new thread, so you can execute cpu-blocking tasks here.

Let’s just simulate a file compression that takes 10 seconds

@Override
protected void onHandleIntent(Intent intent) {
   showToast("Starting IntentService");
   try {
       Thread.sleep(10000);
   } catch (InterruptedException e) {
       Thread.currentThread().interrupt();
   }
   showToast("Finishing IntentService");
}

The service may not be running in the same UI context, so to show the toast(interact with the Android UI) we may need to run it on the same UI thread. We do it in the showToast method:

protected void showToast(final String msg){
    //gets the main thread
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            // run this code in the main thread
            Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
        }
    });
}

Let’s see now how to create a Service.

V - Implementing a Service

In the Service we’ll simulate a task that will be running continuously on the System.

Start creating a new class, TutorialIntentService that extends the IntentService.

Implementing some methods and adding a thread handler, we have:

package com.rhesoft.blog.backgroundservice;

import android.app.Service;
import android.content.Intent;
import android.os.*;
import android.os.Process;
import android.widget.Toast;

public class TutorialService extends Service {

  private Looper mServiceLooper;
  private ServiceHandler mServiceHandler;

  @Override
  public void onCreate() {
      // To avoid cpu-blocking, we create a background handler to run our service
      HandlerThread thread = new HandlerThread("TutorialService",
                                Process.THREAD_PRIORITY_BACKGROUND);
      // start the new handler thread
      thread.start();

      mServiceLooper = thread.getLooper();
      // start the service using the background handler
      mServiceHandler = new ServiceHandler(mServiceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show();

      // call a new service handler. The service ID can be used to identify the service
      Message message = mServiceHandler.obtainMessage();
      message.arg1 = startId;
      mServiceHandler.sendMessage(message);

      return START_STICKY;
  }

  protected void showToast(final String msg){
    //gets the main thread
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            // run this code in the main thread
            Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
        }
    });
  }

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

  // Object responsible for
  private final class ServiceHandler extends Handler {

      public ServiceHandler(Looper looper) {
          super(looper);
      }

      @Override
      public void handleMessage(Message msg) {
          // Well calling mServiceHandler.sendMessage(message); from onStartCommand,
          // this method will be called.

          // Add your cpu-blocking activity here
      }
  }
}

The code above will start a new background thread and run services in this thread. Each service will run on ServiceHandler class, and you need to add your background tasks on handleMessage.

Just as an example, my service will wait 5 seconds before finishing.

@Override
public void handleMessage(Message msg) {
    // Well calling mServiceHandler.sendMessage(message);
    // from onStartCommand this method will be called.

    // Add your cpu-blocking activity here
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    showToast("Finishing TutorialService, id: " + msg.arg1);
    // the msg.arg1 is the startId used in the onStartCommand,
    // so we can track the running sevice here.
    stopSelf(msg.arg1);
}

VI - Registering a Service

Android uses the application manifest to identify app’s services. To register these two services, add the following code to AndroidManifest.xml:

<service android:name=".TutorialIntentService" />
<service android:name=".TutorialService" />

inside <application tag. Please, check this documentation for more information about how to configure services in the manifest.

VII - Starting the Background Services

You can start both services in the same way. To keep this tutorial simple, I’m starting them with the MainActivity created by blank project.

I hope this tutorial helped you :), and I’ll bring more advanced topics about it soon.

Thanks for reading,

Aron Bordin.

Aron Bordin

Aron Bordin
Computer Science Student and AI researcher. Always coding something fun :)

[Tutorial] Android Material Icon Library

Welcome!In this post, I’ll show you how to use Material Icon Library.This is a really good library that can help you choosing over 1000 f...… Continue reading