【问题标题】:About AlarmManager and the way it is saved关于AlarmManager及其保存方式
【发布时间】:2015-10-04 15:49:15
【问题描述】:

我正在制作一个使用警报服务的应用程序。我仍在学习它是如何工作的,但有一件事非常不清楚,也无法解释。

假设您在启动应用时创建了一个闹钟。警报保存在某处,因为即使您的应用程序未运行,它也需要触发,对吗?

如果是这样,我如何在重新启动我的应用程序时收到此警报,这样我就不会每次都创建一个新的并且在某处存储了无限的警报?

如果没有,它是如何工作的?我在考虑使用数据库或 json 文件,但我觉得没有必要。

在我的 MainActivity 类中,我有这段代码来检查警报是否已经存在(这段代码显然是错误的)...

AlarmReceiver alarm;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button b = (Button) findViewById(R.id.button);
    b.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(alarm != null){
                alarm.cancel();
            }
            alarm = new AlarmReceiver(MainActivity.this);
        }
    });



}

我已经为设备重启时设置了一个 BroadcastReceiver(如 android 教程中所述)

public class SampleBootReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
        new AlarmReceiver(context);
    }
}
}

这是 AlarmReceiver 类本身:

public class AlarmReceiver {
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;

public AlarmReceiver(Context context){
    alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
    alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 17);
    calendar.set(Calendar.MINUTE, 30);

    alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
            1000 * 60 * 20, alarmIntent);
    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();

    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

}

public void cancel(){
    alarmMgr.cancel(alarmIntent);
}
}

以及仅启动通知的 AlarmBroadcastReceiver(有效):

public class AlarmBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    new NotificationMessage(context);
}
}

【问题讨论】:

    标签: android alarmmanager alarm


    【解决方案1】:

    警报保存在某个地方,因为即使您的应用未运行,它也需要触发,对吧?

    正确。

    如何在重新启动我的应用时收到此警报

    你没有。这是一个只写 API。

    所以我不会每次都创建一个新的,并且在某个地方存储了无限的警报?

    仅在需要时创建警报,而不是在应用的每次运行时创建。

    除此之外,在调用 AlarmManager 方法替换该警报(或使用 cancel() 取消警报)时,使用与现有警报等效的 PendingIntent

    我正在考虑使用数据库或 json 文件,但我觉得没有必要。

    您需要在持久存储中提供足够的信息才能知道警报响起时该怎么做。当您必须重新安排之前安排的警报时,您还需要持久存储中的足够信息来了解需要哪些警报、处理重新启动。

    【讨论】:

    • “除此之外,在调用 AlarmManager 方法替换该警报(或使用 cancel() 取消警报)时,使用与现有警报等效的 PendingIntent。”是否可以仅在我的 AlarmReceiver 类中做到这一点?如果我无法访问我之前设置的闹钟,我该如何更改它?
    • @zuokuok:“是否可以仅在我的 AlarmReceiver 类中做到这一点?” ——大概。等效的PendingIntent 是相同的操作(活动、服务、广播)、相同的 ID(getActivity() 的第二个参数等)和等效的Intent。等效的Intent 匹配路由特征(组件、操作、类别、数据、MIME 类型),但不必匹配额外内容。 “那我怎么改?” -- 创建一个等效的PendingIntent 并使用它安排一个新警报,它将替换旧警报。
    • 我的类的编写方式是否会覆盖当前的警报集,因为我的 pendingIntent 总是相同的?
    • @zuokuok:看起来不错。您可以使用 adb shell dumpsys alarm 查看未完成的警报事件,以准确确认您的计划。
    猜你喜欢
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 2016-08-05
    • 1970-01-01
    相关资源
    最近更新 更多