Android 报警太早
Android Alarms too early
我正在使用 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();
}
问题是您将闹钟设置为在 trigger
时间响起,即时间减去当前时间。
您应该传递 time.getTimeInMillis()
。
因此将此行替换为
am.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pi);
}
来自官方docs:
Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.
Bas van Stein 是正确的。 AlarmManager
使用绝对时间:自 1970 年 1 月 1 日纪元以来的毫秒数。您正试图将其设置为相对时间:从您设置闹钟的时间算起的毫秒数。 AlarmManager
将其解释为非常接近纪元的某个时间,即 1970 年 1 月 1 日左右的 12:10AM。由于时间已经过去很久了,警报立即触发。
解决方法就是在set
中使用time.getTimeInMillis()
而不是trigger
。
做这种工作的一些其他注意事项,因为你的应用程序与我的意图相似:
自 API 19 以来的大多数警报都是不准确的,正如 Frank N. Stein 指出的那样。这种不精确的程度取决于实现以及警报在未来多长时间内创建。对于可能至少每天一次的药物之类的东西,在我的所有测试中,警报都会在预定时间的一分钟内触发。
您正在使用当前时间作为 PendingIntent
中的 requestCode
。通过将其设置为对您的程序有意义的数字并存储该值,您可以稍后通过重新创建相同的 PendingIntent
.
来更新或取消此警报
从 API 级别 23 及以后,药物警报等紧急警报应使用 setAndAllowWhileIdle()
以确保它们的警报在低功耗空闲状态下响起。我还不知道将 set
与 RTC_WAKEUP
一起使用是否足以确保此行为。
我正在使用 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();
}
问题是您将闹钟设置为在 trigger
时间响起,即时间减去当前时间。
您应该传递 time.getTimeInMillis()
。
因此将此行替换为
am.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pi);
}
来自官方docs:
Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.
Bas van Stein 是正确的。 AlarmManager
使用绝对时间:自 1970 年 1 月 1 日纪元以来的毫秒数。您正试图将其设置为相对时间:从您设置闹钟的时间算起的毫秒数。 AlarmManager
将其解释为非常接近纪元的某个时间,即 1970 年 1 月 1 日左右的 12:10AM。由于时间已经过去很久了,警报立即触发。
解决方法就是在set
中使用time.getTimeInMillis()
而不是trigger
。
做这种工作的一些其他注意事项,因为你的应用程序与我的意图相似:
自 API 19 以来的大多数警报都是不准确的,正如 Frank N. Stein 指出的那样。这种不精确的程度取决于实现以及警报在未来多长时间内创建。对于可能至少每天一次的药物之类的东西,在我的所有测试中,警报都会在预定时间的一分钟内触发。
您正在使用当前时间作为
PendingIntent
中的requestCode
。通过将其设置为对您的程序有意义的数字并存储该值,您可以稍后通过重新创建相同的PendingIntent
. 来更新或取消此警报
从 API 级别 23 及以后,药物警报等紧急警报应使用
setAndAllowWhileIdle()
以确保它们的警报在低功耗空闲状态下响起。我还不知道将set
与RTC_WAKEUP
一起使用是否足以确保此行为。