6

In many articles, tutorials, docs, have read so far, that we call startService() or bindService(), both starts the service. We can call both also, but that's a different story. I am unable to bindService without startService().

    private void bindTunManagerService(int flags) {
    TunnelManagerService.setParentActivity(this);
    Intent bindIntent = new Intent(this, TunnelManagerService.class);
    startService(bindIntent);
    tunManagerServiceStarted = bindService(bindIntent, tunConnection, BIND_AUTO_CREATE);

    Log.d(TAG, "tunManagerServiceStarted  : " + tunManagerServiceStarted + ", ** tunManagerService = " + tunManagerService );

In the above code, if I comment startService(), bindService returns false and tunManagerService = null, even onServiceConnected is not fired up and I get "Unable to sart service intent {...} not found" message. After adding startService, service's onCreate, onStart, onServiceConnected are called and is successfully bounded.

In practical usage, is it necesary to first startServie & then only we can bindService(). It implies that without startSErvice, we can't bindService !! If this statement is wrong, why I can't bindService without starting it ?

Any ideas ????

CODE ADDED

ServiceConnection :

    private ServiceConnection tunConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG,"onServiceConnected" );
        tunManagerService = ITunnelManagerService.Stub.asInterface(service);
        doConnect();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG,"onServiceDisconnected" );
        tunManagerService = null;
    }

};

Service :

public class TunnelManagerService extends Service {
@Override
public IBinder onBind(Intent arg0) {
    return binder;
}

@Override
public void onCreate() {
    super.onCreate();
    Log.d(TAG, "TunnelManagerService: onCreate");
    setCreatedPreference(true);
    notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.i(TAG, "Received start id " + startId + ": " + intent);
    return START_STICKY;
}

@Override
public void onDestroy() {
    super.onDestroy();
    setCreatedPreference(false);
    hideNotifConnected();
    Log.d(TAG, "TunnelManagerService: onDestroy");
}

private final ITunnelManagerService.Stub binder = new ITunnelManagerService.Stub() {
  // contains all methods
}

...............
.............

}

Manifest :

        <activity android:name=".StartUltimate" android:label="@string/app_name" 
         android:launchMode="singleTask" android:windowSoftInputMode="stateHidden|adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <service android:name="orange.android.vpn.utilities.TunnelManagerService" android:enabled="true"></service>

I use 2.3.3 SDK i.e. API 10. My activity from which I am calling is in "orange.android.vpn" and the service related files are in "orange.android.vpn.utilities" packages respectively.

Tvd
  • 4,463
  • 18
  • 79
  • 125

2 Answers2

8

I found the solution, so am sharing with all of you.

There are 2 types of Services : One where you start and stop. This can be started and stopped only once in an application. Other you Bind and Unbind as required N number of times. My Service is of second type. But just bind and unbind doesn't do the job. The service first needs to be started then only it cna be bound and unbound. So on start of app or whereever appropriate, Start the service. Then Bind when required. When don with it, Unbind it. That Bind-Unbind circle can go on. And Finally when you are sure you don't need it or at the end of the app Stop the Service. So the flow comes as Start -> Bind -> Unbind -> Stop <-

Hope this helps someone.

Tvd
  • 4,463
  • 18
  • 79
  • 125
  • bindService() actually starts the service if it hasn't been started already. – Jason Aug 09 '11 at 00:53
  • 5
    @ Jason: Yes, but some crucial things might be done in onStartCommand in the service. I'm working with a service now, where it turns out things only work if the service is explicitly started. This would be the explanation for Tvd's solution as well. – DuneCat Feb 09 '12 at 15:08
  • 10
    This doesn't seem like its the answer. You should be able to bind to a service without explicitly start it. If you also want to start it when binding: bing the service and pass it the flag Context.BIND_AUTO_CREATE – ZiviMagic Nov 18 '12 at 11:45
  • i seem to be able to bind fine without the flag. onStartCommand is not called but that is no issue for me. I guess you can use a bound service in more that one way - i dont want mine to be around after i unbind so i dont need to start it also – Dori Dec 14 '12 at 17:36
  • 1
    To Quote _When a service is unbound from all clients, the Android system destroys it (unless it was also started with `onStartCommand()`)_ see http://developer.android.com/guide/components/bound-services.html#Lifecycle – Dori Dec 14 '12 at 17:42
  • So where should I start my worker thread if it only binds without onStartCommand() -in onCreate()? – JohnyTex Jan 14 '16 at 13:55
  • 2
    This is a misleading answer. A service can be started by just calling bindService and passing BIND_AUTO_CREATE flag. Because of your answer I thought that the service always needs to be started before it can be binded. But then I tried it for myself and I was able to do so without calling startService() explicitly. Please modify your answer so that it does not mislead other people. – thedarkpassenger Sep 24 '17 at 08:24
6

Yes.

bindService(new Intent(this, MyService.class), mConnection, 0);

AFAIK, this will always return true (assuming there is no problem with MyService)

There are two scenarios:

  1. The service has previously been started - mConnection's onServiceConnected() is called
  2. The service has NOT previously been started - mConnection's onServiceConnected() is NOT called and the service is NOT started. However, as soon as the service is started (by some other means), the onServiceConnected() is then called

In practice, when I call this method, I assume the service is not started until the onServiceConnected() method is called.

Antonio
  • 19,451
  • 13
  • 99
  • 197
Mark
  • 7,446
  • 5
  • 55
  • 75