Issue
I have this code in my class:
public void setAlarm(Context context)
{
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, StepCountUpdaterAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
Long startOfTommorowMillis = calendar.getTimeInMillis();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Long startOfTodayMillis = calendar.getTimeInMillis();
calendar.set(Calendar.HOUR_OF_DAY, 6);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
Long startOfAlarmMillis = calendar.getTimeInMillis() - startOfTodayMillis;
Long totalWaitMillis = (startOfTodayMillis + startOfAlarmMillis) - System.currentTimeMillis();
if(totalWaitMillis < 0) return;
if (android.os.Build.VERSION.SDK_INT >= 23) {
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
totalWaitMillis,
pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP,
totalWaitMillis,
pendingIntent);
}
}
What I am trying to do is to have this alarm fire at 6:30am UTC every day. To do that I use Long totalWaitMillis = (startOfTomorrowMillis + startOfAlarmMillis) - System.currentTimeMillis();
but for testing purposes, i changed it to use startOfTodayMillis
so i can test the alarm.
I managed to get the calendar to show the correct firing times with startOfTodayMillis - startOfAlarmMillis
. When i subtract System.currentTimeMillis()
, it seems to provide the correct amount of millisecond delay for the alarm to fire next. In effect, it calculates the time in milliseconds till it hits 6:30 today (I have not fired it in the past in this scenario). Yet despite this, it fires extremely early and does its task far earlier than expected. When I use startOfTomorrowMillis + startOfAlarmMillis
as well, it fires practically a day early and multiple times. I am a novice when it comes to working with AlarmManager so any help here would be appreciated.
EDIT: I am aware that these alarm timers are not exact. I expected a few seconds offset but not minutes or near enough a day. To add a bit of detail, I just tried setting the alarm an hour from now, it fired at least 5 times within around 20 seconds, after an initial 30 seconds from the alarm being set. My device currently uses the setAndAllowWhileIdle
method.
Solution
The method shown in the question was to have the alarm work in idle but to repeat itself which is not a feature i have seen available in the AlarmManager from reading its documentation.
My initial misconception with the AlarmManager was that the setAndAllowWhileIdle
and set
methods's second parameter Long triggerAtMillis
wasn't a count down to the next time it should fire the alarm, it was the actual time it should fire for the next alarm. The documentation for the triggerAtMillis
parameter shown here and below:
triggerAtMillis: time in milliseconds that the alarm should go off, using the appropriate clock (depending on the alarm type).
Courtesy of @Niaj Mahmud 's I have made my own twist to the answer he provided that works such that it does a scheduled task while the phone is in doze mode/ is idle. In this example I schedule the task at 11:58pm of each day, without the need for a notification.
Activity.java code:
public void setAlarm(Context context)
{
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, StepCountUpdaterAlarm.class);
intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 58);
calendar.set(Calendar.SECOND, 0);
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_YEAR, 1);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}
BroadcastReciever.java code
@Override
public void onReceive(Context context, Intent intent) {
MyActivity myActivity = MyActivity.getInstance();
//Do your work here.
myActivity.setAlarm(context); //Set your alarm again to reschedule itself.
}
Answered By - Xeno Xetric
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.