如何避免PendingIntent的重复使用

4

你好!

我在复制PendingIntents方面遇到了困难。我的应用程序有一个服务,在应用程序的onCreate时启动,执行一些异步任务,并自行停止。 问题是,每次应用程序启动时,我都会从数据库中获得一组新的PendingIntents(完全相同),但它们不会取消以前的PendingIntents,即使使用FLAG_CANCEL_CURRENT也无效。我通过“adb shell dumpsys alarm”确定了这一点。
以下是异步任务的onPostExecute:

        while (c.moveToNext())
        {
            int _id = c.getInt(c.getColumnIndex(Maindb._ID));
            long remind_timestamp = c.getLong(c
                    .getColumnIndex(Maindb.REMIND_TIMESTAMP));
            String remind_name = c.getString(c.getColumnIndex(Maindb.NAME));
            String remind_description = c.getString(c
                    .getColumnIndex(Maindb.DESCRIPTION));

            Log.i("Service reminders : id = " + _id + "; REMIND_TIMESTAMP="
                    + remind_timestamp + "; NAME = " + remind_name
                    + "; DESCRIPTION=" + remind_description);

            Intent myIntent = new Intent(ReminderService.this,
                    AlarmReceiver.class);

            myIntent.putExtra(RemindDialog.REMIND_DIALOG_ID, _id);
            myIntent.putExtra(RemindDialog.REMIND_DIALOG_NAME, remind_name);
            myIntent.putExtra(RemindDialog.REMIND_DIALOG_DESCRIPTION,
                    remind_description);
            myIntent.putExtra(RemindDialog.REMIND_DIALOG_TIMESTAMP,
                    remind_timestamp);

            pendingIntent = PendingIntent.getService(ReminderService.this,
                    _id, myIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);

            AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

            alarmManager.set(AlarmManager.RTC_WAKEUP, remind_timestamp,
                    pendingIntent);
            Log.i("Successfully setted alarm for ID:TIMESTAMP = " + _id
                    + ":" + remind_timestamp);


        }

        Log.d("Closing cursor");
        c.close();

        Log.d("Nothing else to do, Stoping the services by himself");
        stopSelf();

    }

第二次启动应用程序后,从“adb shell dumpsys alarm”输出的结果如下:

RTC_WAKEUP #26: 闹钟{42096e70 类型 0 com.} 类型=0 时间=+93d9h0m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{4283e8b8: PendingIntentRecord{426ab530 com.startService}}

RTC_WAKEUP #25: 闹钟{41dff7f8 类型 0 com.} 类型=0 时间=+93d9h0m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{41f1e730: PendingIntentRecord{41e7e1b0 com.startService}}

RTC_WAKEUP #24: 闹钟{42161b60 类型 0 com.} 类型=0 时间=+76d19h50m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{428494d8: PendingIntentRecord{42705b90 com.startService}}

RTC_WAKEUP #23: 闹钟{41ef50a8 类型 0 com.} 类型=0 时间=+76d19h50m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{41f1de18: PendingIntentRecord{41efdcd0 com.startService}}

RTC_WAKEUP #22: 闹钟{42549b40 类型 0 com.} 类型=0 时间=+51d5h30m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{428697e8: PendingIntentRecord{427c9890 com.startService}}

RTC_WAKEUP #21: 闹钟{41f2fe20 类型 0 com.} 类型=0 时间=+51d5h30m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{41fb31a0: PendingIntentRecord{41f3d018 com.startService}}

RTC_WAKEUP #20: 闹钟{4269f008 类型 0 com.} 类型=0 时间=+21d10h30m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{428706f0: PendingIntentRecord{427fd1f0 com.startService}}

RTC_WAKEUP #19: 闹钟{41fb1428 类型 0 com.} 类型=0 时间=+21d10h30m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{41f3c958: PendingIntentRecord{4212d098 com.startService}}

RTC_WAKEUP #18: 闹钟{426aa948 类型 0 com.} 类型=0 时间=+16d14h16m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{42875fb8: PendingIntentRecord{4282bf98 com.startService}}

RTC_WAKEUP #17: 闹钟{42554a70 类型 0 com.} 类型=0 时间=+16d14h16m54s107ms 重复间隔=0 次数=0 操作=PendingIntent{41ec39e8: PendingIntentRecord{426a0620 com.startService}}

所以,主要问题是为什么我的PendingIntents会重复,因为乍一看,第一次和第二次启动应该完全相同(输入光标肯定相同)。
谢谢!对我的英语不好感到抱歉。

你的 _id 值是否总是相同的?因为每个不同的 _id 值都会得到一个不同的 PendingIntent - David Wasser
@David Wasser 是的,_id 是相同的。我从sqlite数据库中检索它。我用日志重新检查了两次。 - Sergey Grabak
好的,你可以尝试先取消警报,然后再重新安排它们(请参阅我的答案)。如果这解决了问题,请让我知道。 - David Wasser
@David Wasser 取消操作无效,待处理意图仍在重复。 - Sergey Grabak
好的,我更新了我的回答。请尝试一下并让我知道结果。 - David Wasser
1个回答

6

你可能已经替换了PendingIntent,以避免重复。然而,你并没有取消之前用AlarmManager预定的闹钟。为了取消之前预定的闹钟,你需要调用:

alarmManager.cancel(pendingIntent);

在开始之前:

alarmManager.set(AlarmManager.RTC_WAKEUP, remind_timestamp, pendingIntent);

这将取消与传递的PendingIntent匹配的任何警报。
编辑:以上回答对OP没有帮助,可能是错误的(请参见A--C的评论)
在替换PendingIntent时,您需要使用PendingIntent.FLAG_UPDATE_CURRENT而不是PendingIntent.FLAG_CANCEL_CURRENT。这应该只会有一个预定的警报。
问题在于,当您创建新的PendingIntent并取消现有的PendingIntent时,使得AlarmManager无法确定您正在调度的警报是否正在替换另一个警报(因为它无法比较PendingIntent,因为旧的已经不存在了)。

set() 应该自动执行替换。如果已经为此 Intent 安排了一个闹钟,则它将被删除并由此新的闹钟替换。 - A--C
@A--C 是的,你说得对。我忘记了 :-( 看代码,我能想到的唯一其他可能是他的“_id”字段总是不同的,但在描述中他暗示它不是这样的。 - David Wasser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接