I was trying to get the next alarm clock, by the following which returns the next clock timestamp of utc wall time.
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val next = alarmManager.nextAlarmClock.triggerTime
If the next clock is at 19:00 of tomorrow, the next will result of 18:00 of tomorrow, what is the difference of utc wall time and utc time, I have googled for nothing.
Problem solved when I change a phone, there may be some fault on the first phone, because the result is not consistent when the alarm clock changes.
Related
So I am tring to schedule alarm at a particular time on current day using AlarmManager.
To do that I am using ZoneDateTime to get current time and then updating it to the hour at which I need to set the alarm. But for some reason time.withHour is giving me 8pm or 8am no matter what hour I am passing to it. Am I doing something wrong here?
var time = ZonedDateTime.now() //getting current time at my timezone
time = time.withHour(22).withMinute(8).withSecond(0)
print(time) //getting 8am/8pm at my timezone
val timeMilis = time.toInstant().toEpochMilli()
I have a logic that schedules reminders using AlarmManager. I need to implement the following:
Logic 1: when the user changes time zone, eg he travels from UK (UTC+0) to central Europe (UTC+1), alarms should follow the time zone.
Example, a reminder scheduled at 3PM UTC+0 should fire at 4PM UTC+1
Logic 2: when a time shift occurs, eg time shifts to daylight saving time in spring (from UTC+1 to UTC+2), alarms should keep the original time
Example, a reminder scheduled at 3PM UTC+1 should fire at 3PM UTC+2
How can I achieve this? As of now I have no particular logic in place and all the alarms follow Logic 1. I have found no way to identify when a time shift happens.
Scheduling logic is very simple:
LocalDateTime reminderTime = LocalDateTime.of(...)
ZoneOffset currentOffsetForMyZone = ZoneId.systemDefault().getRules().getOffset(Instant.now());
reminderTime.toInstant(currentOffsetForMyZone).toEpochMilli();
alarmManager.setExact(AlarmManager.RTC_WAKEUP, reminderTime, pendingIntent);
For each alarm store the time of day and the time zone in which it was set. This suffices for firing the alarm at the right time no matter if the user is currently in a different time zone. And Java will take summer time (DST) into account.
Your example times and UTC offsets correspond to standard time in those time zones, so let’s start with an example date in standard time even though it was a couple of days ago now:
LocalTime alarmTime = LocalTime.of(15, 0);
ZoneId alarmTimeZone = ZoneId.of("Europe/London");
// Travel to Paris and see the alarm go off at 4, assuming standard time
ZoneId currentTimeZone = ZoneId.of("Europe/Paris");
Instant actualAlarmTime = LocalDate.of(2021, Month.MARCH, 18)
.atTime(alarmTime)
.atZone(alarmTimeZone)
.toInstant();
ZonedDateTime timeOnLocation = actualAlarmTime.atZone(currentTimeZone);
System.out.format("Scheduled at %s or %d millis, goes off at %s local time%n",
actualAlarmTime, actualAlarmTime.toEpochMilli(), timeOnLocation);
The code prints:
Scheduled at 2021-03-18T15:00:00Z or 1616079600000 millis, goes off at
2021-03-18T16:00+01:00[Europe/Paris] local time
Let’s also try a date in the summer time part of the year. I have changed Paris to London and MARCH to APRIL:
// Stay back home in the UK
ZoneId currentTimeZone = ZoneId.of("Europe/London");
Instant actualAlarmTime = LocalDate.of(2021, Month.APRIL, 18)
.atTime(alarmTime)
.atZone(alarmTimeZone)
.toInstant();
Scheduled at 2021-04-18T14:00:00Z or 1618754400000 millis, goes off at
2021-04-18T15:00+01:00[Europe/London] local time
The basic trick is: don’t use the current offset for the time zone where you set the alarm. Let Java automatically apply the offset for the date and time where the alarm is to go off.
If anyone is interested, the fix was to apply the correct offset for the date and time where the alarm is to go of, as pointed out by Ole. My silly mistake was to apply always the current timezone.
LocalDateTime alarmTime = LocalDateTime.of(...)
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime zoneDateTime = ZonedDateTime.of(alarmTime , zone);
long startAtMillis = zoneDateTime.toInstant().toEpochMilli();
//Fire alarm
notificationAlarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, startAtMillis, pendingIntent);
I want to popup an alarm on selected day i.e. Monday ,Tuesday and so on. And at selected time on every week. I've an idea about interval but I don't know how to get the next day and popup alarm ?
You need to use the AlarmManager and get a WakeClock while processing the Intent in Service (make sure to release it and chose the right kind).
Here is a great example :
https://stackoverflow.com/a/8801990/220710
To get the day current day of the week, look at this question :
Android: how to get the current day of the week (Monday, etc...) in the user's language?
Then you would use :
setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
Schedule a repeating alarm
that has inexact trigger time requirements; for example, an alarm that
repeats every hour, but not necessarily at the top of every hour.
Then you would need to set :
type = RTC_WAKEUP
intervalMillis = ms in a week
triggerAtMillis = System.currentTimeMillis() + ms to the next Monday, Tuesday or
whatever
intent = the intent you want to fire to a Service that
will process it.
I have tried to do this without bothering the experts and have read numerous threads here and on other sites. It is clearly my brain not understanding what needs to be done in order for this to work.
My goal is that the app allows the user to enter a time and one or more days in a week. All of the GUI side and storing of the dates and times I have done, however to get the alarm manager to repeat, lets say every Monday at 14:00 and then can send at 14:02 . I have used the java Calendar object to hold the times and days of the week or even used date and day of the week of the month. These are then , as needed, converted to milliseconds for it to be read in by the alarm manager.
I then have used either the alarm manager set or set repeat methods to repeat the event. All I am able to do is get it to occur once and then if I change the emulator date and time to another Monday nothing happens.
The GUI holds the hours and minutes in required variables and then these are used against the calendar objects.
The alarm manager calls a broadcast receiver for the event to occur.
Please can someone simply give an example on how to set specific days such as Monday , Wednesday Friday. I know that separate alarm managers are needed for each day and at the moment I have just focused on Monday as my main test.
Links viewed:
How can i Repeat the Alarm in android for only Monday, Tuesday and Friday
How to repeat the alarm for "n" days at a particular time
how to repeat alarm after 1 day in android
Managed to figure this out now and so follows my answer:
The following code calculates the remaining days between now and the day needed for the scheduled task. the variable whichday is passed via parameter from the method this code belongs to. In the understanding of this whichday represents days of the week 1 through to 7 where 1 is Sunday , 2 is Monday and so .
//This gets the current day of the week as of TODAY / NOW
int checkcurrentday = getcurtime.get(Calendar.DAY_OF_WEEK);
// This calculates the days between now and the day needed which is represented by whichday.
int numberofdays = Calendar.SATURDAY + whichday - checkcurrentday;
//Now add NOT set the difference of the days to your Calendar object
tMondayOn.add(Calendar.DATE, numberofdays);
Well, you need to first use the Java Calendar API (or Joda!) to figure out when the next monday is. Set the alarm to to that time in milliseconds then use setRepeating and pass in a long that represents the interval of one week.
I want to use and alarmManager that sets a repeating alarm to go off on the hour, every hour. I know how to set a repeating alarm every hour but not how to actually set it from the top of the hour, I need to know this value for the 'whatTime' variable below.
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME, whatTime, 1*60*60*1000, operation);
Also I want to be able to set a flag that for e.g. - if the time happens to be between 4 and 8 in the daytime, perform some operations, otherwise don't bother.
So I really need to know how to find out the hour of the day, can anyone tell me how to do this? Many thanks
Try:
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
Calendar.HOUR_OF_DAY gives you the 24-hour time.
Calendar.HOUR gives you the 12-hour time.