无法取消重复警报 Android
Unable to cancel repeating alarm Android
我已经阅读了所有关于 Android、AlarmManager 和取消的问题。
我目前使用 Activity
通过以下方式启动接收器:
long msInterval = 1;
Intent intent = new Intent(this, Updater.class);
intent.setAction("theAction");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 12, intent, 0);
Updater.origin = pendingIntent;
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (msInterval), msInterval, pendingIntent);
这会在调用此代码后一毫秒启动接收器 Updater
,请求代码为 12(任意选择,使用 0 会产生相同的错误行为)。它还将Updater的origin设置为当前调度的PendingIntent,用于后面取消报警。
更新程序看起来像这样:
public class Updater extends BroadcastReceiver {
public static int flaggedClose = 0;
public static PendingIntent origin;
@Override
public void onReceive(Context context, Intent intent) {
// Do some work
Log.w("running", "run");
if (Updater.flaggedClose != 0) {
if(flaggedClose == 1) {
Toast.makeText(context, "Finished!", Toast.LENGTH_SHORT).show();
}
flaggedClose++; // Only show Toast once
Log.w("running", "close");
origin.cancel();
AlarmManager alarms = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarms.cancel(origin);
}
}
}
目前它所做的只是记录消息 "run",已完成 ~1000 times/s。当 Activity 的 onStop()
被调用时,Updater.flaggedClose
被设置为 1
。我可以在 Logcat 中看到它,因为它开始打印日志警告 "close"。但是,警报仍处于开启状态,因此每隔一条记录的消息为 "run",并且每隔一条为 "close"。在最好的情况下,警报会在几秒钟后关闭。最坏的情况我需要重新启动 phone。在AlarmManager的描述中,特别写明close关闭"Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled"。为什么还有警报被触发?
正如评论中提到的 ci_,可能 "those 100 "额外的“警报在取消发生之前已经触发”。对于遇到同样问题的任何其他人,这里有一个解决方案。我测试了 AlarmManager,如果延迟至少 200 毫秒,它似乎效果最好。要获得较低的延迟,请使用 Handler
。使用 Handler 的问题示例:
public class MainActivity extends Activity {
private boolean pressed = false;
private boolean done = false;
private Handler worker;
private Runnable method;
long msInterval = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
worker = new Handler();
method = getMethod();
Button toggle = (Button)(findViewById(R.id.toggle));
toggle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(!pressed) {
worker.post(method);
pressed = true;
} else {
done = true;
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
done = true;
}
private Runnable getMethod() {
return new Runnable() {
public void run() {
Log.w("running", "run");
if (done) {
Toast.makeText(getApplicationContext(), "Finished!", Toast.LENGTH_SHORT).show();
Log.w("running", "close");
} else {
worker.postDelayed(method, msInterval);
}
}
};
}
}
在第一次按下按钮时,处理程序启动 runnable,并且在每次调用时 runnable 调用自身。在第二次按下按钮时,条件 done
设置为真,因此可运行程序在一轮(清理)后完成。
我已经阅读了所有关于 Android、AlarmManager 和取消的问题。
我目前使用 Activity
通过以下方式启动接收器:
long msInterval = 1;
Intent intent = new Intent(this, Updater.class);
intent.setAction("theAction");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 12, intent, 0);
Updater.origin = pendingIntent;
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (msInterval), msInterval, pendingIntent);
这会在调用此代码后一毫秒启动接收器 Updater
,请求代码为 12(任意选择,使用 0 会产生相同的错误行为)。它还将Updater的origin设置为当前调度的PendingIntent,用于后面取消报警。
更新程序看起来像这样:
public class Updater extends BroadcastReceiver {
public static int flaggedClose = 0;
public static PendingIntent origin;
@Override
public void onReceive(Context context, Intent intent) {
// Do some work
Log.w("running", "run");
if (Updater.flaggedClose != 0) {
if(flaggedClose == 1) {
Toast.makeText(context, "Finished!", Toast.LENGTH_SHORT).show();
}
flaggedClose++; // Only show Toast once
Log.w("running", "close");
origin.cancel();
AlarmManager alarms = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarms.cancel(origin);
}
}
}
目前它所做的只是记录消息 "run",已完成 ~1000 times/s。当 Activity 的 onStop()
被调用时,Updater.flaggedClose
被设置为 1
。我可以在 Logcat 中看到它,因为它开始打印日志警告 "close"。但是,警报仍处于开启状态,因此每隔一条记录的消息为 "run",并且每隔一条为 "close"。在最好的情况下,警报会在几秒钟后关闭。最坏的情况我需要重新启动 phone。在AlarmManager的描述中,特别写明close关闭"Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled"。为什么还有警报被触发?
正如评论中提到的 ci_,可能 "those 100 "额外的“警报在取消发生之前已经触发”。对于遇到同样问题的任何其他人,这里有一个解决方案。我测试了 AlarmManager,如果延迟至少 200 毫秒,它似乎效果最好。要获得较低的延迟,请使用 Handler
。使用 Handler 的问题示例:
public class MainActivity extends Activity {
private boolean pressed = false;
private boolean done = false;
private Handler worker;
private Runnable method;
long msInterval = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
worker = new Handler();
method = getMethod();
Button toggle = (Button)(findViewById(R.id.toggle));
toggle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(!pressed) {
worker.post(method);
pressed = true;
} else {
done = true;
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
done = true;
}
private Runnable getMethod() {
return new Runnable() {
public void run() {
Log.w("running", "run");
if (done) {
Toast.makeText(getApplicationContext(), "Finished!", Toast.LENGTH_SHORT).show();
Log.w("running", "close");
} else {
worker.postDelayed(method, msInterval);
}
}
};
}
}
在第一次按下按钮时,处理程序启动 runnable,并且在每次调用时 runnable 调用自身。在第二次按下按钮时,条件 done
设置为真,因此可运行程序在一轮(清理)后完成。