How to set an alarm to exact hour on following days? - java

I'm trying to make an alarm that besides shoot today, repeat on the exact same hour on the next day.
Not having any success until now.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, timeHOUR);
calendar.set(Calendar.HOUR, timeHOUR);
calendar.set(Calendar.MINUTE, timeMINUTE);
The alarm must occur at the same times on the following days.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Also i need to be able to register more than 1 alarm. I'm not sure if setRepeating() supports that.

Related

The AlarmManager is unreliable, are there improvements or alternatives?

I need a widget to be updated frequently using a set value, like every 1-5 seconds.
I found out that for this an AlarmManager should be used.
I tested the AlarmManager's setExact() method and found out, that its minimum time is exactly 5 seconds.
I also noticed that the interval can have huge delays.
I tested this with a set interval of 5 seconds.
My test showed for the setExact() method following values: 5s, 5s, 40s, 41s, 19s, 5s, 5s, ...
Using the setRepeating() method showed even worse value: 17s, 39s, 7s, 75s, 60s, ... Apparently the AlarmManager also does not trigger at all when used on a Samsung Device, which is the Device I am planning to use the widget on.
Is there an alternative to using an AlarmManager?
Can the AlarmManager somehow become more reliable?
I need the update rate to be constant, without delays like this.
final AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent notifyIntent = new Intent(this, AlarmReceiver.class);
final PendingIntent notifyPendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
long triggerTime = SystemClock.elapsedRealtime()
+ 3000;
long repeatInterval = 1000;
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
triggerTime, notifyPendingIntent);
Besides the AlarmManager I have checked out the JobScheduler and Worker, but both seem to underlie a 15 minute (!) minimum interval.
Using a simple Thread seems to be working however. I just have to find out how to make it run reliably then...
If you know other solutions please let me know!

Starting a service at a specific time every day

i made a calendar to show toast in specific time every day at 8:00 pm
but the app show start the service and show the toast in different time.
like
8:00 pm
8:23 pm
8:30 pm
8:32 pm
8:50 pm
and doesn't stop showing the toast
what is the wrong?
this is my Mainactivity.java code
Intent alarmIntent = new Intent(MainActivity.this, MyService.class);
pendingIntent = PendingIntent.getService(MainActivity.this, 0, alarmIntent, 0);
setAlarm();
}
private void setAlarm() {
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
/* Set the alarm to start at 8.00 PM */
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 20);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
//Add a day if alarm is set for before current time, so the alarm is triggered the next day
if (calendar.before(Calendar.getInstance())) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS), pendingIntent);
}}
From the documentation of setRepeating
Note: as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whose targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.
EDIT
You alarm being inexact, it means that the system will not wake up in the exact time you set 00:800 to fulfill your request, instead it will group some actions that needs to be done, somewhere around the time you set, and fire them all together to save battery of the phone, and do prevent the phone from being awake every couple of seconds separately.
You can replace your call to non repeating call using AlarmManager.set() and handling repetition yourself, as in each alarm firing schedules the next one.
Or if your alarm firing is not time critical (it doesn't not have to be very exact), you can leave it as it is.
To have a precise alarm instead of using setRepeating use setAndAllowWhileIdle
otherwise, if you are not in need of precise timing I would recommend you to use firebase job dispatcher to schedule your job https://github.com/firebase/firebase-jobdispatcher-android

Setting alarm on daily basis

I am developing an android app where I am trying to set an alarm on daily basis.And for that I am using Calendar as
alarmCalendar.set(Calendar.DATE,taskdate);
alarmCalendar.set(Calendar.MONTH, 7);
alarmCalendar.set(Calendar.YEAR, 2013);
alarmCalendar.set(Calendar.HOUR, 11);
alarmCalendar.set(Calendar.MINUTE, 30);
alarmCalendar.set(Calendar.SECOND, 0);
I was setting the alarm using the below code.
alarmtime = alarmCalendar.getTimeInMillis();
am.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime, AlarmManager.INTERVAL_DAY, pi);
The Problem with the above code is, the alarm triggers sometimes and sometimes it doesn't.
So I am trying it out in one more way. that is,
Once the alarm triggers, On cancel of that alarm I am trying to set it for the next day using
am.set(AlarmManager.RTC_WAKEUP, currenttime, pendingIntent);
instead of am.setRepeating(). But now the problem is that, even though there is no looping in the code, the alarm triggers continuously on cancelling it.
Not getting where I am going wrong.
Please Help.Thanks!
Do you have a BroadcastReceiver with the BOOT_COMPLETED permission to recreate the alarm every time the phone starts up? Otherwise you'll loose the alarm.
Check it out here http://learnandroideasily.blogspot.nl/2013/07/bootcompleted-broadcastreceiver-in.html

AlarmManager Being Triggered immediately because time occurs in the past

When launching my application, the AlarmManager is being triggered immediately because the time occurs in the past.
My idea was to check the actual time with the schedule one :
if(calendar.before(Calendar.getInstance())); //where calendar is my scheduled calendar
If the above condition is true then:
calendar.add(Calendar.DAY_OF_YEAR, 1);
I think this will work.
However the confusion is at day 365:
If the scheduled time was before the Actual time, it will add one day according to this line: calendar.add(Calendar.DAY_OF_YEAR, 1);
and it will become 1
Doesn't that make it always in the past? Because there is no 366 ? Thus the AlarmManager will be always triggering it immediately considering it in the past?
EDIT:
Do you suggest I put instead :
calendar.add(Calendar.HOUR_OF_DAY, 24);
CommonsWare's comment is correct; add() will add that amount of time and adjust all the fields appropriately.
The behavior you were concerned about would occur if you used roll() instead of add(). But you should be safe with add().
Here's the doc if you want to dig in further.

Figuring out local time on user's machine in UTC?

I need to set an alarm on a user's phone. This is an android function, and the alarm takes the time to fire in System.currentTimeMillis() format. I want to set the alarm at 7pm on the user's phone, but I don't know what timezone the user has their phone set to.
How can I figure out what the equivalent time at 7pm for the current day is in UTC (currentTimeMillis()) ?
Thanks
Calendar cal = Calendar.getInstance(); // returns current time in user's default TimeZone
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.HOUR_OF_DAY, 19);
long time = cal.getTime().getTime();

Categories