首页 文章

无法取消重复警报Android

提问于
浏览
1

我已经阅读了有关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次/秒 . 调用Activity的 onStop() 时, Updater.flaggedClose 设置为 1 . 我可以在Logcat中看到这个,因为它开始打印日志警告"close" . 但是,警报仍然打开,因此每隔一条记录的消息都是"run",而其他所有消息都是"close" . 在最好的情况下,警报会在几秒钟后关闭 . 最坏的情况我需要重启手机 . 在AlarmManager的描述中,它特别声明close关闭"Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled" . 为什么还会触发警报?

1 回答

  • 1

    正如评论中提到的ci_,有可能"those 100 "额外" alarms already triggered before the cancel happens" . 对于有同样问题的其他人来说,这是一个解决方案 . 我测试了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在一个(清理)轮之后结束 .

相关问题