I have a setup that looks something like this:
class MyFragment implements SomeEventListener {
Application mAppContext;
boolean mBound;
boolean mDidCallUnbind;
MyIBinder mBinder;
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBound = true;
mBinder = (MyIBinder) service;
mBinder.getThings();...
}
@Override
public void onServiceDisconnected(ComponentName name) {
mDidCallUnbind = false;
mBound = false;
mBinder = null;
}
};
...
@Override
public void onSomeEvent() {
mAppContext.bindService(...);
}
void unbindService() {
if (mBound && !mDidCallUnbind) {
mDidCallUnbind = true;
mAppContext.unbindService(mConnection);
}
}
@Override
public void onPause() {
unbindService();
super.onPause();
}
}
However, I am still seeing the error in the title from time to time: java.lang.IllegalArgumentException: Service not registered
being generated when unbindService()
is called. Am I missing something silly, or is there more going on? I should note that there may be more than one of this same fragment in existence.
Edit
Since no one actually seems to be reading the code, let me explain. unbindService()
does not call Context.unbindService(ServiceConnection)
unless the service is bound (mBound
) and it had not previously been called before the onServiceDisconnected(...)
callback was hit from a possible previous call to unbindService()
.
That in mind, are there any cases where Android will unbind your service for you such that the service would become unbound but onServiceDisconnected would not be called thus leaving me in a stale state?
Also, I am using my Application context to do the initial binding. Assume something like:
@Override
public void onCreate() {
mApplication = getContext().getApplicationContext();
}
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() {
bindService(new Intent(this, MyService.class),
mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
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