As some of you, I am an amateur Android developer, who is getting better and better. For work it’s good to have demos of certain projects running on a phone and it is always useful to have actual implementation results when submitting a paper. I learned Android literally in 2 days because I was already decent in Java and because, as in Java, pretty much everything is done for you and you just have to put pieces together. I am able to code simple apps with all types of functionalities.

(At this point I want to take a quick break to share the fact that I am listening to Don’t Tread On Me by Metallica, an awesome song, and it is thanks to the glorious agreement between Metallica and Spotify)

So far I had been able to, with a decent amount of work and time, figure out everything I needed for all kind of apps. However, I needed to move on and have things running in the background as a service. It took me 3 days of struggle and headaches to get it done. And the Android developer guide did not help at all. So I have decided to share this with whoever is interested. This is how you have a simple service running in the background. Adding any extra code and functionality to this should be trivial.

Simple background service in Android step by step

(Note that most of the functions and code is from the official Android sample files. I am not giving any proprietary code or anything that is my new creation. I just explain well step by step how to put all the pieces from Android sample code together. Android’s developer site does a very poor job at it.)

(Note that this is a simple amateur way to do it. I am sure there are other ways that are way more efficient)

  • You should have an activity already coded and working well
  • Create a new class that extends service. In this example we will call it TestService.java
  • In the app’s Android manifest file add this after </activity>:

<service android:enabled="true"
             android:exported="false"
             android:label="TestService"
             android:name=".TestSecService">
</service>

  • Add to your activity the following variables:

private static final String TAG = "testService"; //For debugging

private boolean serviceOn; //Boolean that logs if the service is ON or OFF

Messenger messengerToService = null; //To send messages to the service

//Class for interacting with the main interface of the service (Extracted from <a href="http://developer.android.com/tools/samples/index.html">the official Android sample code</a>)
private ServiceConnection mConnection = new ServiceConnection() {
     public void onServiceConnected(ComponentName className, IBinder service) {
          // This is called when the connection with the service has been
          // established, giving us the object we can use to
          // interact with the service.  We are communicating with the
          // service using a Messenger, so here we get a client-side
          // representation of that from the raw IBinder object.
          messengerToService = new Messenger(service);

          Log.e(TAG, "+++ Connected to service +++");
     }

     public void onServiceDisconnected(ComponentName className) {
          // This is called when the connection with the service has been
          // unexpectedly disconnected -- that is, its process crashed.
          messengerToService = null;

          Log.e(TAG, "+++ Disconnected from service +++");
     }
};

  • Implement the following methods in your activity:

void doBindService() {
         // Establish a connection with the service.  We use an explicit
         // class name because there is no reason to be able to let other
         // applications replace our component.
         bindService(new Intent(this,TestService.class), mConnection, Context.BIND_AUTO_CREATE);
         serviceOn = true;
         Log.e(TAG, "+++ Binding to service +++");
     }

void doUnbindService() {
     if (serviceOn) {
          // If we have received the service, and hence registered with
          // it, then now is the time to unregister.

          // Detach our existing connection.
          unbindService(mConnection);
          serviceOn = false;
          Log.e(TAG, "+++ Unbinding from service +++");
     }
}

  • Now you just have to add the following code where you want to turn ON or OFF your service. Note that the service will run in the background until you either turn it off manually with this code or your activity is destroyed. In other words, the service still runs in the background even if you minimze the activity or you open another app or whatnot. However, I am sure that this is not really efficient so do not use it for an app you want to make commercial. This is mostly an “amateur” solution.

//Bind to service (To turn service ON)
if (serviceOn == false){
     if(D) Log.e(TAG, "+++ Executing doBindService +++");
     doBindService();
}else{
     mConversationArrayAdapter.add("WEIRD.Already connected...");
}

//Unbind from service (To turn service OFF)
if (serviceOn == true){
       doUnbindService();
}else{
       mConversationArrayAdapter.add("WEIRD.Already disconnected...");
}

  • Now let’s look at the service class you created. You will need the following variables:

private static final String TAG = "testService"; //For debugging

//Target we publish for clients to send messages to IncomingHandler.
final Messenger mMessenger = new Messenger(new IncomingHandler());

//CODES (the messages you want to be able to send from the activity to the service. I am showing 2 examples, but they could be anything)
static final int MSG_SAY_HELLO = 1;
static final int MSG_SAY_BYE = 2;

  • These are the methods you will need:

@Override
public void onCreate () {
    //One-time set-up procedures
    Log.e(TAG, "+++ SERVICE ON CREATE +++");

}

@Override
public void onDestroy () {
    //Close files, disconnect stuff, etc
    //If the service wants to autodestroy itself, the code should call stopSelf()
    Log.e(TAG, "+++ SERVICE onDestroy +++");

    // Tell the user we stopped.
    Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
}

@Override
public IBinder onBind(Intent intent) {
    Log.e(TAG, "+++ SERVICE onBind +++");
    return mMessenger.getBinder();
}

private void handleCommand(Intent intent) {
    // TODO Auto-generated method stub

}

class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
    switch (msg.what) {
        case MSG_SAY_HELLO:
            Log.e(TAG, "+++ SERVICE received order to say hello +++");
            Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
            break;
        case MSG_SAY_BYE:
            Log.e(TAG, "+++ SERVICE received order to say bye +++");
            Toast.makeText(getApplicationContext(), "bye!", Toast.LENGTH_SHORT).show();
            break;
        default:
            super.handleMessage(msg);
    }
    }
}

  • And that’s it. Now, when you do doBindService() in your activity the service starts. To stop it, just use doUnbindService() in your activity.
  • To send a message to the service to make it say hello or by (as per the example used here), just use this code in your activity:

if (serviceOn){
    Message msg = Message.obtain(null, TestService.MSG_SAY_HELLO, 0, 0);
    try {
        messengerToService.send(msg);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

And that’s it. Simple and easy.

(The Struggle Within is playing now… have a nice weekend everyone!)

Advertisements