无法取消重复警报Android

时间:2015-03-17 15:18:22

标签: android alarmmanager repeatingalarm receiver

我已阅读有关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的原点设置为当前计划的PendingIntent,稍后用于取消警报。

Updater看起来像这样:

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次/秒。调用活动onStop()后,Updater.flaggedClose设置为1。我可以在Logcat中看到这个,因为它开始打印日志警告“关闭”。但是,警报仍然打开,因此每个其他记录的消息都“运行”,而其他所有消息都“关闭”。在最好的情况下,警报会在几秒钟后关闭。最坏的情况我需要重启手机。在AlarmManager的描述中,它明确指出close关闭“任何类型的任何警报,其Intent与此匹配(由filterEquals(Intent)定义)将被取消”。为什么还会触发警报?

1 个答案:

答案 0 :(得分:1)

正如评论中提到的那样,有可能在取消发生之前已经触发了“那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设置为true,因此runnable在一轮(清理)轮之后完成。