Android 如何使用活动中的取消按钮强制 IntentService 立即停止?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11258083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to force an IntentService to stop immediately with a cancel button from an Activity?
提问by pvans
I have an IntentService that is started from an Activity and I would like to be able to stop the service immediately from the activity with a "cancel" button in the activity. As soon as that "cancel" button is pressed, I want the service to stop executing lines of code.
我有一个从活动启动的 IntentService,我希望能够通过活动中的“取消”按钮立即从活动中停止服务。一旦按下“取消”按钮,我希望服务停止执行代码行。
I've found a number of questions similar to this (i.e. here, here, here, here), but no good answers. Activity.stopService()
and Service.stopSelf()
execute the Service.onDestroy()
method immediately but then let the code in onHandleIntent()
finish all the way through before destroying the service.
我发现了许多与此类似的问题(即这里、这里、这里、这里),但没有好的答案。 Activity.stopService()
并立即Service.stopSelf()
执行该Service.onDestroy()
方法,然后onHandleIntent()
在销毁服务之前让代码一直执行完。
Since there is apparently no guaranteed way to terminate the service's thread immediately, the only recommended solution I can find (here) is to have a boolean member variable in the service that can be switched in the onDestroy()
method, and then have just about every line of the code in onHandleIntent()
wrapped in its own "if" clause looking at that variable. That's an awful way to write code.
由于显然没有保证立即终止服务线程的方法,我能找到的唯一推荐解决方案(here)是在服务中有一个可以在onDestroy()
方法中切换的布尔成员变量,然后几乎每一行代码onHandleIntent()
包含在它自己的“if”子句中,查看该变量。这是一种糟糕的代码编写方式。
Does anybody know of a better way to do this in an IntentService?
有人知道在 IntentService 中执行此操作的更好方法吗?
采纳答案by kupsef
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;
}
}
回答by Sadegh
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:
这是诀窍,使用 volatile 静态变量并检查服务中某些行中的继续条件,应检查服务继续:
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;
回答by JoeyCK
I've used a BroadcastReceiver inside the service that simply puts a stop boolean to true. Example:
我在服务中使用了一个 BroadcastReceiver,它只是将一个停止布尔值设置为 true。例子:
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;
}
}
@Override
protected 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 SERVICE
Intent 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.
PD:我使用布尔值,因为在我的情况下,我在循环中停止服务,但您可以在 onReceive 中调用 unregisterReceiver 和 stopSelf。
PD2: Don't forget to call unregisterReceiver if the service finishes it's work normally or you'll get a leaked IntentReceiver error.
PD2:如果服务正常完成,请不要忘记调用 unregisterReceiver 否则您将收到泄漏的 IntentReceiver 错误。
回答by Manish DEWAN
In case of IntentServiceit does not stop or takes any other request through some intent action until its onHandleIntent
method completes the previous request.
在IntentService 的情况下,它不会停止或通过某些意图操作接受任何其他请求,直到其onHandleIntent
方法完成前一个请求。
If we try to start IntentServiceagain with some other action, onHandleIntent
will be called only when previous intent / task is finished.
如果我们尝试用其他一些动作再次启动IntentService,onHandleIntent
只有在之前的意图/任务完成时才会调用。
Also stopService(intent);
or stopSelf();
does not work until the onHandleIntent()
method finishes its task.
在该方法完成其任务之前也stopService(intent);
或stopSelf();
不工作onHandleIntent()
。
So I think here better solution is to use normal Service
here.
所以我认为这里更好的解决方案是在Service
这里使用 normal 。
I hope it will help!
我希望它会有所帮助!
回答by cycDroid
@Override
protected void onHandleIntent(Intent intent) {
String action = intent.getAction();
if (action.equals(Action_CANCEL)) {
stopSelf();
} else if (action.equals(Action_START)) {
//handle
}
}
Hope it works.
希望它有效。
回答by rtsai2000
If using an IntentService
, then I think you are stuck doing something like you describe, where the onHandleIntent()
code has to poll for its "stop" signal.
如果使用IntentService
,那么我认为您会陷入像您描述的那样的事情,onHandleIntent()
代码必须轮询其“停止”信号。
If your background task is potentially long-running, and if you need to be able to stop it, I think you are better off using a plain Service
instead. At a high level, write your Service to:
如果您的后台任务可能需要长时间运行,并且您需要能够停止它,我认为您最好使用普通的Service
。在较高级别,将您的服务写入:
- Expose a "start" Intent to start an AsyncTask to perform your background work, saving off a reference to that newly-created AsyncTask.
- Expose a "cancel" Intent to invoke
AsyncTask.cancel(true)
, or have onDestroy() invokeAsyncTask.cancel(true)
. - The Activity can then either send the "cancel" Intent or just call stopService().
- 公开“开始”意图以启动 AsyncTask 以执行您的后台工作,从而保存对新创建的 AsyncTask 的引用。
- 公开“取消” Intent to invoke
AsyncTask.cancel(true)
,或者让 onDestroy() invokeAsyncTask.cancel(true)
。 - 然后,活动可以发送“取消”意图或仅调用 stopService()。
In exchange for the ability to cancel the background work, the Service takes on the following responsibilities:
为换取取消后台工作的能力,本服务承担以下责任:
- The AsyncTask
doInBackground()
will have to gracefully handle InterruptedException and/or periodically check for Thread.interrupted(), and return "early". - The Service will have to ensure that
stopSelf()
is called (maybe in AsyncTask onPostExecute/onCancelled).
- AsyncTask
doInBackground()
必须优雅地处理 InterruptedException 和/或定期检查 Thread.interrupted(),并“提前”返回。 - 服务必须确保
stopSelf()
被调用(可能在 AsyncTask onPostExecute/onCancelled 中)。
回答by tolgap
As @budius already mentioned in his comment, you should set a boolean on the Service
when you click that button:
正如@budius 在他的评论中已经提到的,Service
当您单击该按钮时,您应该在 上设置一个布尔值:
// your Activity.java
public boolean onClick() {
//...
mService.performTasks = false;
mService.stopSelf();
}
And in your Intent
handling, before you do the important task of committing/sending the intent information, just use that boolean:
在您的Intent
处理中,在您执行提交/发送意图信息的重要任务之前,只需使用该布尔值:
// your Service.java
public boolean performTasks = true;
protected void onHandleIntent(Intent intent) {
Bundle intentInfo = intent.getBundle();
if (this.performTasks) {
// Then handle the intent...
}
}
Otherwise, the Service willdo it's task of processing that Intent
. That's how it was meant to be used,
because I can't quite see how you could solve it otherwiseif you look at the core code.
否则,服务将执行处理该Intent
. 这就是它的用途,因为如果你查看核心代码,
我不太明白你如何解决它。
回答by Pooja Singh
context.stopService(GPSService);
回答by Rinkal Bhanderi
Here is some sample code to start/stop Service
这是一些启动/停止服务的示例代码
To start,
开始,
Intent GPSService = new Intent(context, TrackGPS.class);
context.startService(GPSService);
To stop,
停止,
context.stopService(GPSService);
context.stopService(GPSService);