Android java.lang.IllegalArgumentException: Service not registered

I realize this question has already been answered. But I think there is reason to go into why people are making this mistake.

The issue is really with the training docs. http://developer.android.com/reference/android/app/Service.html shows a correct implementation while https://developer.android.com/guide/components/bound-services.html in the 'ActivityMessenger' shows a Very INCORRECT implementation.

In the 'ActivityMessenger' example onStop() could potentially be called before the service has actually been bound.

The reason for this confusion is they are using the bound service boolean to mean different things in different examples. (mainly, was bindService() called OR is the Service actually connected)

In the correct examples where unbind() is done based on the value of the bound boolean, the bound boolean indicates that the bindService() was called. Since it's queued up for main thread execution, then unbindService() needs to be called (so queued to be executed), regardless of when (if ever) onServiceConnected() happens.

In other examples, such as the one in http://developer.android.com/reference/android/app/Service.html. The bound indicates that the Services is Actually bound so that you can use it and not get a NullPointerException. Note that in this example, the unbindService() call is still made and the bound boolean doesn't determine whether to unbind or not.


Another possible reason for this exception might be that unbindService is called by the wrong Context. Because services can be bound not only by Activities, but also by other instances inherited by Context (with the exception of BroadcastReceivers), even by other Services, be sure that unbindService is called by the context that has bound the Service and not by the bound Service itself. This would yield directly the above exception "Service not registered".


Use mIsBound inside doBindService() and doUnbindService() instead of in the ServiceConnection instance.

ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mBinder = (MyIBinder) service;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mBinder = null;
    }
}; 

...

public void doBindService() {
    mIsBound =bindService(new Intent(this, MyService.class),
        mConnection, Context.BIND_AUTO_CREATE); 
}

public void doUnbindService() {
    if (mIsBound) {
        unbindService(mConnection);
        mIsBound = false;
    }
}

This is how it's done in http://developer.android.com/reference/android/app/Service.html