0

I'm trying to create a service that is primarily run in the foreground and clients can bind to it only if it is already in the started state. However, every potential solution I can come up with is riddled with race conditions.

The most promiment example of this:

final ServiceConnection serviceConnection = // create instance...

void startAndBindToService() {
    final Intent serviceIntent = new Intent(this, MyService.class);

    startService(serviceIntent);
    
    // this *sometimes* doesn't bind because the service isn't started yet
    bindService(serviceIntent, serviceConnection, 0);  
}

Testing on an emulator, the above works consistently on a local service but not when the service is in another process.

I've also looked into having the service starting itself when its onBind method is called:

@Override
public void IBinder onBind(Intent intent) {
    startService(new Intent(this, this.getClass()));
    return binder;
}

But this never guarantees the service will be in the started state before the client unbinds.

And for the ones that think they are clever and ask why I don't use BIND_AUTO_CREATE, that doesn't solve the problem, and in fact it only makes it worse. BIND_AUTO_CREATE only creates the service, it doesn't put it in the started state, but it does allow for the service to end being created twice if a race condition does occur.

  • I also wanted add. One can just start a service and use a handler and repeatedly try to bind to the service every x milliseconds, but that isn't a very elegant solution. – OldApplesAndBananas_45 Apr 25 '22 at 01:34
  • I'm curious if your app contains the service you're trying to bind to, because it sounds like whoever wrote it did not properly implement onBind or onStartCommand (or both). If you're offering a bindable service, any initialization done in onStartCommand should also happen in onBind. Because either one can be used to launch a service. – Gabe Sechan Apr 25 '22 at 02:47
  • As stated in Android's documentation- generally you implement onBind OR onStartCommand, not both (https://developer.android.com/guide/components/bound-services). There are exceptions. But the idea is that binding circumvents the normal onStart functionality. When a Service is meant to run in either mode, onBind should be responsible for starting itself, or just running the same init code. – Gabe Sechan Apr 25 '22 at 02:52

0 Answers0