Android警报太早了

Android警报太早了,android,alarmmanager,android-alarms,Android,Alarmmanager,Android Alarms,我正在使用android studio开发一个应用程序,该应用程序将从数据库中检索时间信息,并设置一个警报,提示用户该喝药了,我的问题是警报出现得太早 例如,检索到的时间是12:50 AM,当前时间是12:40 AM 即使相差10分钟,警报也会立即响起 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm"); try { Calendar Cnow = Calendar.getInstance();

我正在使用android studio开发一个应用程序,该应用程序将从数据库中检索时间信息,并设置一个警报,提示用户该喝药了,我的问题是警报出现得太早

例如,检索到的时间是12:50 AM,当前时间是12:40 AM 即使相差10分钟,警报也会立即响起

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
try {
         Calendar Cnow = Calendar.getInstance();
         long now=Cnow.getTimeInMillis();
         Calendar time=Calendar.getInstance();
         time.setTimeInMillis(0);
         Date dTime=sdf.parse(strAlarmDate + " " + strTime1);
//example strAlarmDate="2015-09-27" and strTime1="12:50 AM" and now="12:40 AM" in millis
//dTime="...... 2015-09-27 00:50"
         time.setTime(dTime);
         //Date dNow=now.getTime();
         //time.setTime(date);
         //long trigger=time.getTimeInMillis()-now.getTimeInMillis();
         long trigger=time.getTimeInMillis()-now;
         if(trigger>0) {
             ctr++;
             Intent i = new Intent(Login.this, AlarmReceiver.class);
             i.putExtra("message", strMedname);
             i.putExtra("line", strLine);
             final int _id = (int) System.currentTimeMillis();
             PendingIntent pi = PendingIntent.getActivity(Login.this, _id, i, 0);
             AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
//           am.set(AlarmManager.RTC_WAKEUP, trigger, pi);
//           am.setExact(AlarmManager.RTC_WAKEUP, trigger, pi);
             am.set(AlarmManager.RTC_WAKEUP, trigger, pi);
         }
     }catch(ParseException ex)
     {
          ex.printStackTrace();
     }

问题是,您将报警设置为在时间
触发时发出,即时间减去当前时间

您应该通过
时间。改为getTimeInMillis()

因此,将线路替换为

am.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pi);
     }
官员说:

注意:从API 19(KITKAT)开始,警报传递是不精确的:操作系统将切换警报,以尽量减少唤醒和电池使用。有新的API支持需要严格交付保证的应用程序;请参见设置窗口(int,long,long,pendingent)和设置精确窗口(int,long,pendingent)。targetSdkVersion早于API 19的应用程序将继续看到之前的行为,其中所有警报都会在请求时准确传递


巴斯范斯坦是对的
AlarmManager
使用绝对时间:自1970年1月1日起的毫秒。您正试图将其设置为相对时间:从设置报警时间算起的毫秒
AlarmManager
将其解释为1970年1月1日12:10左右的某个时间非常接近新纪元。由于这段时间已经过去很久了,警报会立即触发

解决方案就是在
设置中使用
时间.getTimeInMillis()
,而不是
触发器

由于您的应用程序与我的应用程序在意图上相似,因此需要注意以下几点:

  • 正如Frank N.Stein指出的那样,自API 19以来的大多数警报都是不精确的。这种不准确的程度取决于实施情况,以及警报在未来产生的时间。对于像药物这样的东西,可能至少每天都有,在我所有的测试中,警报在预定时间的一分钟内发出

  • 您正在使用当前时间作为
    pendingent
    中的
    requestCode
    。通过将此设置为对程序有意义的数字并存储该值,您可以在以后通过重新创建相同的
    pendingent
    来更新或取消此报警

  • 从API级别23及以后,紧急警报(如药物警报)应使用
    setandallowhileidle()
    确保其警报在低功率闲置状态下关闭。我还不知道将
    set
    RTC_WAKEUP
    一起使用是否足以确保这种行为