Android警报太早了

时间:2015-09-26 16:38:21

标签: android alarmmanager android-alarms

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

例如,检索时间是上午12:50,当前时间是上午12:40 即使有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();
     }

3 个答案:

答案 0 :(得分:1)

问题在于您将闹钟设置为在时间trigger时关闭,即时间减去当前时间。

您应该改为time.getTimeInMillis()

所以用

替换该行
am.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pi);
     }

答案 1 :(得分:1)

Bas van Stein是对的。 AlarmManager使用绝对时间:自1970年1月1日纪元以来的毫秒数。您正在尝试将其设置为相对时间:从设置警报时起的毫秒数。 AlarmManager解释说,在1970年1月1日上午12:10左右,时间非常接近时代。由于此时间过去很久,警报立即触发。

解决方案只是在time.getTimeInMillis()而不是set中使用trigger

执行此类工作的其他一些注意事项,因为您的应用程序与我的应用程序类似:

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

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

  • 从API级别23开始,紧急警报(如药物警报)应使用setAndAllowWhileIdle()以确保在低功率空闲状态期间其警报响起。我还不知道将setRTC_WAKEUP一起使用是否足以确保此行为。

答案 2 :(得分:0)

来自官方docs

  

注意:从API 19(KITKAT)开始,警报传递不准确:操作系统将移动警报以最小化唤醒和电池使用。有新的API支持需要严格交付保证的应用程序;请参阅setWindow(int,long,long,PendingIntent)和setExact(int,long,PendingIntent)。 targetSdkVersion早于API 19的应用程序将继续查看之前在请求时准确传递所有警报的行为。