调度重复的基于时间的警报

时间:2016-08-19 23:54:09

标签: android android-alarms

我想安排多个重复的基于时间的闹钟。根据{{​​3}},“基于精确触发时间的重复警报不能很好地扩展”,为什么这样,我不明白。但我需要这种精确的功能。那么我的选择是什么?我的主要目标是使用AlarmManager类安排警报,并在预定时间发生时发出通知,但考虑到开发文档,我不太确定如何去做。

修改

我设法安排了我的警报,这种警报在设定的时间间隔后最严格地反复重复出现基本的基于时间的警报,但在设置多个警报的意义上“重复”。现在当我在日历上设置我的日期和时间时,月份设置为提前一个月,如果我输入10,则将月份设置为11,这是我的代码:

Calendar cal = Calendar.getInstance();
String date = "23/10/2016";//month set to 10
String[] _date = date.split("/");
String time = "4:33";
String[] _time = time.split(":");

Intent intent = new Intent(test.this,
            AlarmReceiver.class);


intent.setData(Uri.parse("timer:555"));

PendingIntent sender = PendingIntent.getBroadcast(
            test.this, 0, intent,
            0);

cal.set(Integer.parseInt(_date[2]), //year
        Integer.parseInt(_date[1]), //month
        Integer.parseInt(_date[0]), //day
        Integer.parseInt(_time[0]), //hour
        Integer.parseInt(_time[1]));//minute

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);

Toast mToast = Toast.makeText(
            test.this,
            "Reminders added to the calendar successfully for "
                    + android.text.format.DateFormat.format(
                    "MM/dd/yy h:mmaa",
                    cal.getTimeInMillis()),
            Toast.LENGTH_LONG);
mToast.show();//month displayed is 11

1 个答案:

答案 0 :(得分:1)

我正在使用AlarmManager,就像你想要在我的项目中一样。在项目中,我可以安排单次或每日,每周,每月,每年的警报。实际上它的工作正常,但操作系统可以转换警报电池效率,有时可能会延迟1分钟。如果您在AlarmManager.html#setRepeating中阅读此内容:

  

注意:从API 19开始,所有重复警报都不准确。如果您的应用程序需要精确的交付时间,那么它必须使用一次性精确警报,每次重新安排如上所述。 targetSdkVersion早于API 19的旧应用程序将继续将所有警报(包括重复警报)视为完全警报。

如果你在那里阅读了接受的答案,你就会明白:alarmmanager-fires-alarms-at-wrong-time

请阅读此选定的答案:alarmmanager-setexact-with-wakefulbroadcastreceiver-sometimes-not-exact

如果您想知道我正在使用哪种:我使用的是非精确警报,因为我不想消耗电池,因为我的应用程序并不重要。

请注意;不精确的警报更节省电池。如果时间不重要,请使用不精确的。

所以,最后如果你想看一些代码样本我在Bitbucket中有历史。我可以提供我现有的代码供您参考,或者如果您通过尝试更新您的问题,我可以为您提供指导。

@Edit for setExact:

首先,你必须声明你的警报:

Intent alarmIntent = new Intent(getApplicationContext(), YourAlarmReceiver.class);
//this is important for you you must store this value
// you need this request code when shifting your Alarms
int piRequstCode=(int) System.currentTimeMillis();

以简单的方式,您可以存储待处理的意向请求代码,如:

alarmIntent.putExtra("piRequestCode",piRequstCode);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),piRequstCode,alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
//use mCalendarNotification to set your date for trigger
alarmManager.setExact(AlarmManager.RTC_WAKEUP, mCalendarNotification.getTimeInMillis(), pendingIntent);

然后在BroadcastReceiver

@Override
public void onReceive(Context context, Intent intent) {
   //right now you have your intent and context, so you can shift your alarm
   Bundle extras=intent.getExtras();
   int piRequestCode=extras.getInt("piRequestCode");
   Intent alarmIntent=new Intent(context, YourAlarmReceiver.class);
   alarmIntent.putExtra("piRequestCode",piRequstCode);

   // this will return your existing pending intent because your Intent and request code is same 
   // and FLAG_UPDATE_CURRENT updates pendingIntent with new config. 
   // If there is no pending Intent that matches with this requestCode and intent it will create new one.
   PendingIntent pendingIntent = PendingIntent.getBroadcast(context,piRequestCode,alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);

   //use AlarmManager with context
   AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
   alarmManager.setExact(AlarmManager.RTC_WAKEUP,shiftedTime, pendingIntent);
}

还有一件事,当设备重启时,所有警报都将丢失。您必须手动重置警报。因此,在数据库中存储pendingIntent请求代码(SqliteRealm等...)或SharedPreferences(如果您没有太多数据)是很好的策略。现在我使用Realm来存储requestCodes和所有其他东西,所以我建议你使用Database。

最后要明确在执行此步骤时是否需要更多帮助,请创建新问题或编辑此问题,我们会帮助您。