Monday 24 February 2014

Binding Services – part 1

In this tutorial I’ll explain the basics of binding Services. For more information about what Services are and what they are used for please refer to my previous tutorial, IntentServices in Android, that you can find here.


Services in Android can be activated in two ways:
  • you can start a Service through the Context.startService() method;
  • or you can bind to a Service through the Context.bindService() method.

The main difference is that if you bind to a Service, the Service will stay alive until the last client disconnects. In addition to that, if you bind to a Service, instead of starting it, you have a reference to the Service class that can be used to easily call the Service’s methods.
In this first tutorial about binding Services we’ll see how you have to set up your Service class to allow other components to be able to bind to it. To do this you have to implement the onBind method of the Service class, which must return an IBinder object.
In the following example we create an inner class, called MyBinder (extending the Binder class – please note that the Binder class implements the IBinder interface), and we return an object of this class in the onBind method (we can do so because, as already said, the Binder class implements the IBinder interface).

In our MyBinder class we create a method returning a reference to our Service class, which is used in the clients binding to the Service:

public class MyService extends Service {
   //the content of the Service is omitted for brevity
   public void startBackgroundTask() {
      ...
   }
   ...

   //MyBinder class extending Binder
   public class MyBinder extends Binder {
      public MyService getReference() {
         return MyService.this;
      }
   }

   //create an instance of our MyBinder class
   private MyBinder myBinder = new MyBinder();

   //onBind method, returning an instance of our MyBinder
   @Override
   public IBinder onBind(Intent intent) {
return myBinder;
}
}

Now that we have implemented the onBind method in our Service, we can easily bind to the Service through the Context.bindService method.
To begin with, our Activity (or other component binding to the Service) must implement the ServiceConnection interface. The ServiceConnection interface provides a callback method, onServiceConnected, called when a valid connection to the Service is established.

public class MyActivity extends Activity implements ServiceConnection {
...
}

To bind to MyService we can use the following code, typically in the onResume method (this refers to the component, our Activity in this example, that implements the ServiceConnection interface):

Intent intent = new Intent(this, MyService.class);
bindService(intent, this, BIND_AUTO_CREATE);

To unbind from MyService the code is the following (typically in the onPause method):

unbindService(this);

Finally we have to override the onServiceConnected and onServiceDisconneted methods of the ServiceConnection interface. These methods are called, respectively, when MyService is connected/disconnected to/from our Activity.

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
   MyService myService = ((MyService.MyBinder) iBinder).getReference();
   myService.startBackgroundTask();
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
   ...
}

As you can see in the onServiceConnected method we have an IBinder parameter, of the type MyService.MyBinder, because in the onBind method of our Service we return an object of this type (MyService.MyBinder extends Binder and implements the IBinder interface).
Using the iBinder reference, casting it to MyService.Binder and calling the method getReference we obtain a reference to our MyService class. You can then use this reference to call specific methods of MyService, omitted here for brevity, to perform background operations (you have of course to use different threads to perform background tasks, because all methods of the Service class run in the UI thread).

To be continued...

No comments:

Post a Comment