How to force an IntentService to stop immediately with a cancel button from an Activity?
Here is the trick, make use of a volatile static variable and check continue condition in some of lines in your service that service continue should be checked:
class MyService extends IntentService { public static volatile boolean shouldContinue = true; public MyService() { super("My Service"); } @Override protected void onHandleIntent(Intent intent) { doStuff(); } private void doStuff() { // do something // check the condition if (shouldContinue == false) { stopSelf(); return; } // continue doing something // check the condition if (shouldContinue == false) { stopSelf(); return; } // put those checks wherever you need }}
and in your activity do this to stop your service,
MyService.shouldContinue = false;
Stopping a thread or a process immediately is often a dirty thing. However, it should be fine if your service is stateless.
Declare the service as a separate process in the manifest:
<service android:process=":service" ...
And when you want to stop its execution, just kill that process:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses();Iterator<RunningAppProcessInfo> iter = runningAppProcesses.iterator();while(iter.hasNext()){ RunningAppProcessInfo next = iter.next(); String pricessName = getPackageName() + ":service"; if(next.processName.equals(pricessName)){ Process.killProcess(next.pid); break; }}
I've used a BroadcastReceiver inside the service that simply puts a stop boolean to true. Example:
private boolean stop=false;public class StopReceiver extends BroadcastReceiver { public static final String ACTION_STOP = "stop"; @Override public void onReceive(Context context, Intent intent) { stop = true; }}@Overrideprotected void onHandleIntent(Intent intent) { IntentFilter filter = new IntentFilter(StopReceiver.ACTION_STOP); filter.addCategory(Intent.CATEGORY_DEFAULT); StopReceiver receiver = new StopReceiver(); registerReceiver(receiver, filter); // Do stuff .... //In the work you are doing if(stop==true){ unregisterReceiver(receiver); stopSelf(); }}
Then, from the activity call:
//STOP SERVICEIntent sIntent = new Intent();sIntent.setAction(StopReceiver.ACTION_STOP);sendBroadcast(sIntent);
To stop the service.
PD: I use a boolean because In my case I stop the service while in a loop but you can probably call unregisterReceiver and stopSelf in onReceive.
PD2: Don't forget to call unregisterReceiver if the service finishes it's work normally or you'll get a leaked IntentReceiver error.