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,稍后用于取消警报。

更新程序如下所示:

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);
        }
    }
}

它目前所做的只是记录消息“运行”,它完成了约 1000 次/秒。当onStop()调用 Activity 时,Updater.flaggedClose设置为1. 我可以在 Logcat 中看到这一点,因为它开始打印日志警告“关闭”。但是,警报仍然存在,因此所有其他记录的消息都是“运行”,而其他所有消息都是“关闭”。在最好的情况下,警报会在几秒钟后关闭。最坏的情况我需要重新启动手机。在 AlarmManager 的描述中,它特别指出 close 关闭“任何类型的警报,其 Intent 与此匹配(由 filterEquals(Intent) 定义),将被取消”。为什么还会触发警报?

4

1 回答 1

1

正如评论中提到的 ci_ ,有可能“在取消发生之前已经触发了这 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);
                }
            }
        };
    }
}

在按下第一个按钮时,处理程序启动可运行对象,并且在每次调用时,可运行对象都会调用自身。在第二个按钮按下条件done设置为 true,因此可运行对象在一轮(清理)之后完成。

于 2015-03-20T08:35:12.493 回答