title: Sticky Service Management
body: <p>I've got a Sticky Service (returns <code>START_STICKY</code> from <code>onStartCommand</code>) which executes some code in an <code>AsyncTask</code>, but I'm having some problems with how and when to start, bind, stop, unbind.  I only want the service around whilst the parent activity is alive, I don't want it hanging around in the background when the app has been closed, but I need the service to survive an orientation change.  I currently don't need the service to be active for the entire duration of the activity being active, so I call stopSelf() after the main work is done in my <code>AsyncTask</code> in the <code>Service</code> and then start the <code>Service</code> again when needed.  Sometimes I'll need to interrupt the work the service is doing, cancel the <code>AsyncTask</code> and start again with different data. The problem is that no matter what I do - I can't seem to get it solid throughout all the different possible scenarios. Can anyone have a look through and tell me what I'm doing wrong?</p>
  
  <p>My <code>Service</code> is :</p>
  
  <pre><code>public class ChordCalculatorService extends Service {
  
      private final IBinder mBinder = new LocalBinder();
      private AsyncTask&lt;SearchData, SearchStatusData, List&lt;Item&gt;&gt; currentTask;
  
      @Override
      public void onCreate() {}
  
      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
          // We want this service to continue running until it is explicitly
          // stopped, so return sticky.
          return START_STICKY;
      }
  
      /**
       * Class for clients to access. Because we know this service always runs in
       * the same process as its clients, we don't need to deal with IPC.
       */
      public class LocalBinder extends Binder {
          public ChordCalculatorService getService() {
              return ChordCalculatorService.this;
          }
      }
  
      @Override
      public void onDestroy() {
          super.onDestroy();
      }
  
      @Override
      public IBinder onBind(Intent intent) {
          return mBinder;
      }
  
      public SearchData getSearchData() {
          return searchData;
      }        
  
      public void startWork() {
          if (currentTask != null &amp;&amp; currentTask.getStatus() == Status.RUNNING) {
              currentTask.cancel(true);
          }
          if(searchData != null) {
              Worker task = new Worker();
              currentTask = task.execute(new SearchData[] { searchData });
          } else {
              Message msg = handler.obtainMessage(ERROR, "No search data set");
              handler.sendMessage(msg);
          }
      }
  
  
      class Worker extends AsyncTask&lt;SearchData, SearchStatusData, List&lt;Item&gt;&gt; {
          // ... code ...
  
          @Override
          protected void onPostExecute(List&lt;Item&gt; result) {
              Message msg = handler.obtainMessage(COMPLETE, new StatusData(Status.STATUS_FINISHED, result));
              handler.sendMessage(msg);
              stopSelf();
          }
      }
  }
  </code></pre>
  
  <p>Currently I have the <code>Service</code> being started when my custom <code>View</code> is created:</p>
  
  <pre><code>public class MyCustomView extends BasicFretBoardView  {
  
      private ServiceConnection conn;
      private MyService myService;
      private boolean isServiceStarted;
      private boolean isServiceBound;
  
      public MyCustomView(Context context, AttributeSet attr) {
          super(context, attr);
          startService();
      }
  
      public void startService() {
          Intent serviceIntent = new Intent(getContext(), MyService.class);
          conn = new ServiceConnection() {
              @Override
              public void onServiceConnected(ComponentName name, IBinder service) {
                  myService = ((LocalBinder) service).getService();
                  myService.registerHandler(serviceHandler);
              }
  
              @Override
              public void onServiceDisconnected(ComponentName name) {
                  myService = null;
              }
          };
  
          // Explicitly start the service. Don't use BIND_AUTO_CREATE, since it
          // causes an implicit service stop when the last binder is removed.
  
          getContext().startService(serviceIntent);
          getContext().bindService(serviceIntent, conn, 0);
          isServiceStarted = true;
          isServiceBound = true;
      }
  
      public void stopService() {
          if (isServiceStarted) {
              Intent serviceIntent = new Intent(getContext(), MyService.class);
              getContext().stopService(serviceIntent);
              isServiceStarted = false;
          }
          unBindService();
      }
  
  
      public void unBindService() {
          if(isServiceBound) {
              getContext().unbindService(conn);
              isServiceBound = false;
          }
      }
  
      // gets called based on some user interaction
      private void startServiceWork() {
          if(!isServiceStarted) {
              startService();
          } else {
              myService.cancelCalcalation();
          }
          myService.setData(data);
          myService.startWork();
      } 
  }
  </code></pre>
  
  <p>and stopping the service is handled in the <code>Activity</code>:</p>
  
  <pre><code>public class CustomChordActivity extends Activity {
  
      // ... code ...
  
      @Override
      public void onBackPressed() {
          super.onBackPressed();
      }
  
      @Override
      protected void onPause() {
          if(isFinishing()) {
              chordsView.stopService();
          }
          super.onPause();
      }
  
      @Override
      protected void onStop() {
          super.onStop();
      }
  
      @Override
      protected void onDestroy() {
          chordsView.unBindService();
          super.onDestroy();
      }
  
      @Override
      protected void finalize() throws Throwable {
          super.finalize();
      }
  }
  </code></pre>