Android Local Service Sample, bindservice(), and ServiceConnection()

Marie picture Marie · Jun 19, 2011 · Viewed 26.7k times · Source

I have a question which is related to this question that was asked by @mnish about a year ago.

Please have a look at his question and code. He implements a ServiceConnection() and passes it to bindService(). This follows the Local Service Sample in the Service documentation near the top.

I want to implement the Local Service Sample, so I am trying to add some details from @mnish question/answer. In ServiceConnection() @mnish has this line that confuses me:

mService = ILocService.Stub.asInterface(iservice);

I understand @mnish wrote this code, but does anybody have any idea what ILocService is and any idea how I might go about creating my own ILocService? Where is this construct documented and do I need it? Also where does the value for IBinder iservice come from?

Answer

Tosa picture Tosa · Jun 19, 2011

He is probably using Android Interface Definition Language (AIDL) http://developer.android.com/guide/components/aidl.html

Therefore he has to use a stub of the server side implementation like documented:

 // This is called when the connection with the service has been
 // established, giving us the service object we can use to
 // interact with the service.  We are communicating with our
 // service through an IDL interface, so get a client-side
 // representation of that from the raw service object.
 mService = IRemoteService.Stub.asInterface(service);

The iservice reference is coming from the onServiceConnected method which is called after binding the service to your activity. The call bindService gets passed the ServiceConnection which implements the onServiceConnected method.

You don't need the "IRemoteService.Stub.asInterface(service)" when your implementation of the service is local, then you can just cast the service to you local service.

The local service sample does this in the service:

public class LocalService extends Service {
    private NotificationManager mNM;

    // Unique Identification Number for the Notification.
    // We use it on Notification start, and to cancel it.
    private int NOTIFICATION = R.string.local_service_started;

    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
        return LocalService.this;
        }
    }

    ...

}

And this in the Activity in the ServiceConnection class:

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 service object we can use to
        // interact with the service.  Because we have bound to a explicit
        // service that we know is running in our own process, we can
        // cast its IBinder to a concrete class and directly access it.
        mBoundService = ((LocalService.LocalBinder)service).getService();

        // Tell the user about this for our demo.
        Toast.makeText(Binding.this, R.string.local_service_connected,
                Toast.LENGTH_SHORT).show();
    }

    public void onServiceDisconnected(ComponentName className) {
        // This is called when the connection with the service has been
        // unexpectedly disconnected -- that is, its process crashed.
        // Because it is running in our same process, we should never
        // see this happen.
        mBoundService = null;
        Toast.makeText(Binding.this, R.string.local_service_disconnected,
            Toast.LENGTH_SHORT).show();
    }
};