I have a simple android app with an activity that binds a service. The basic code is like this:
public class MyActivity extends AppCompatActivity {
private MyService service;
private boolean serviceIsBound;
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
service = ((MyService.LocalBinder) binder).getService();
serviceIsBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
serviceIsBound = false;
}
};
// Service gets bound via intent in onCreate()
@Override
protected void onDestroy() {
super.onDestroy();
if (serviceIsBound) {
service.unbindService(serviceConnection);
}
}
}
This produces an error java.lang.IllegalArgumentException: Service not registered
in the call service.unbindService(...)
when I close the activity.
I tried onStop()
instead of onDestroy()
--> same error.
I tried removing the onDestroy()
--> I get an error android.app.ServiceConnectionLeaked
. This error of course makes sense -- after all you should clean up your service connections. I just don't know how.
Call unbindService()
on the same Context
that you call bindService()
on. Presumably, given the structure of your sample, you are calling bindService()
on the MyActivity
instance; if so, call unbindService()
on that MyActivity
instance as well.
Note that you probably should not be doing it this way. On a configuration change (e.g., screen rotation), your MyActivity
instance will be destroyed and recreated. This means that you will unbind from the service, then bind to it again. If nothing else is bound to that service, and that service is not started, the service will be destroyed (when it is unbound) and then recreated (when the new activity instance binds again).
It is very likely that you do not need a bound service, particularly if the service is in the same process as the rest of your app. If you are certain that you need a bound service, bind and unbind from something that survives configuration changes, such as an AndroidViewModel
. There, you would use the Application
as your Context
for the bind/unbind calls. Or, if you are using a dependency inversion (DI) framework (e.g., Dagger/Hilt, Koin), you might get a Context
from it. Or, if appropriate, bind and unbind from some DI-managed singleton, again using the Application
as your `Context.
FWIW, this sample app contains a bound service. It is used by this client app, which binds and unbinds from a ViewModel
.