Note that there are some explanatory texts on larger screens.

plurals
  1. POSticky Service Management
    primarykey
    data
    text
    <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>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload