How to make a repeating alarm more accurate? - android

I want to make a repeating alarm notification that will trigger in a specific time in a day. the repeating alarm that i made is firing the alarm well but sometimes its off in its set time. for example a I set an alarm in 6:00 am but after the first trigger the following day it started at 6:15 am so i was wondering if their is a more accurate way of setting an alarm?
here is my code for my repeating alarm
Calendar calendar_dog= Calendar.getInstance();
calendar_dog.set(Calendar.HOUR_OF_DAY,7);
calendar_dog.set(Calendar.MINUTE,0);
calendar_dog.set(Calendar.SECOND,0);
Intent intent= new Intent(getApplicationContext(), notify_dog.class);
PendingIntent dog_intent=PendingIntent.getBroadcast(getApplicationContext(),100,intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager dog_alarm =(AlarmManager)getApplicationContext().getSystemService(ALARM_SERVICE);
dog_alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP,calendar_dog.getTimeInMillis(),AlarmManager.INTERVAL_DAY,dog_intent);
and on my reciever
NotificationManager notify_dog=(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent dog_intent= new Intent(context, HomeActivity.class);
dog_intent.setFlags(dog_intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent dog_pending=PendingIntent.getActivity(context,100,dog_intent,PendingIntent.FLAG_UPDATE_CURRENT);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder dog_build= new NotificationCompat.Builder(context).setContentIntent(dog_pending).
setSmallIcon(R.drawable.pet)
.setContentTitle("Pet Guide 101")
.setContentText("have you feed your Dog?")
.setSound(alarmSound)
.setAutoCancel(true);
notify_dog.notify(100,dog_build.build());

From Android Developers:
As described above, choosing the alarm type is often the first step in creating an alarm. A further distinction is how precise you need your alarm to be. For most apps, setInexactRepeating() is the right choice. When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. This reduces the drain on the battery.
For the rare app that has rigid time requirements—for example, the alarm needs to fire precisely at 8:30 a.m., and every hour on the hour thereafter—use setRepeating(). But you should avoid using exact alarms if possible.
With setInexactRepeating(), you can't specify a custom interval the way you can with setRepeating(). You have to use one of the interval constants, such as INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY, and so on. See AlarmManager for the complete list.
So, to accomplish what you want, you need to use it like that:
dog_alarm.setRepeating(AlarmManager.RTC_WAKEUP,calendar_dog.getTimeInMillis(),AlarmManager.INTERVAL_DAY,dog_intent);

Related

Launching custom Activity when alarm goes off in custom alarm clock app Android

I know there is a lot of discussion about AlarmClock and AlarmManager and how to set alarms, launch apps, etc. However, I am yet to find the perfect answer for the following scenario.
In my Android alarm clock application I'm developing, I want to set an alarm for a specific time, pass in other settings such as what song to play, vibrate, etc.
1) what should I use to do this? AlarmClock or AlarmManager?
2) Now, when the alarm goes off at the specified time, how do I tell it to launch my custom Activity? Again the question of AlarmClock or AlarmManager.
This custom activity would show the time and have buttons saying "Sleep" or "Snooze" which the user can press (pretty much what happens when an alarm in any other alarm clock app goes off). I don't want to launch my alarm app, ONLY that one screen when the alarm goes off. When the user hits a button, I want to close that custom acitvity and for nothing else related to that app to open. I would like it so that the user can go back to doing whatever they were doing.
I think you can do your job with AlarmManager. As you say, if you want to set alarm for a specific time, you should use setRepeating(). If you want to wake up your device when the alarm fires choose RTC_WAKEUP type and if you don't want that RTC type. You define a PendingIntent, whatever you want to do(play sound, light and vibrate), you can do within this activity that attached to this intent. You should design your layout in that(YOUR_ACTIVITY) layout and put buttons to snooze/cancel alarm.
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, YOUR_ACTIVITY.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
Above code set an alarm for 14:00 and interval of one day which means it will be fired everyday 14:00 and run YOUR_ACTIVITY until you cancel it. this is an example in Google Android Documents.

Android setting multiple long date alarms

I'm trying to create a function in my App, which notifies the user at the expiration day of his rented books. I'll work with checkboxes in a listview, as below:
(Dates are for show purposes only)
Now i'm wondering how can i do it the best way. I'm having experiences with AlarmManager and BroadcastReceivers, but I didn't get a clear flowchart yet.
Thats because I need to set an specific alarm to each book and cancel that specific alarm when requested. Also, it needs to reactivate all Alarms when device is restared (by calling BOOT_COMPLETE broadcast).
PS.: Alarms will usually be set to one week after current date.
PS2.: Can I use Calendar to do it? I mean, this way i wouldn't have to reactivate all alarms, or calculate (expirationDate - currentDate) in millis.
Can someone, who has an idea, try to show me the way? Thanks!
I think the key would be to give each and every book its own alarm id as soon as you set the alarm for this book for the first time.
Then you should keep a list of the running alarm ids and timestamps (maybe in SharedPreferences).
With a method like this you can cancel a specific alarm with regards to its alarm id:
public static void cancelAlarm(Context context, int alarmId) {
PendingIntent pi = PendingIntent.getService(context, alarmId,
new Intent(context, YourService.class),
PendingIntent.FLAG_NO_CREATE);
if(pi!=null) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(pi);
}
}
When you receive the BOOT broadcast, you can get the list of alarm ids together with timestamps from SharedPreferences and start all the alarms with their respective alarm ids

How to test Alarm Manager which set for a INTERVAL_DAY

I written a small application which invokes a service using AlarmManager with interval of the day. To test this app, i am using emulator 5.1 . When i set manually date and time(for current date or future date time) the AlarmManager invokes service for that day. When i am trying to change the date for checking whether it will work for other day by changing date then its not invoking service.
Here is my code.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(calendar.HOUR_OF_DAY,13);
calendar.set(calendar.MINUTE,20);
calendar.set(Calendar.SECOND,10);
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this,BackgroundService.class);
pendingIntent = PendingIntent.getService(this, 0, intent, 0);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);
Toast.makeText(this, "Alarm Set", Toast.LENGTH_SHORT).show();
BackgroundService is service which popup with a Toast .
I have 2 issues.
How can test AlarmManager , which we set with Interval of a day?
The Alarm Manager is not exactly invoking at the second. For example , i set the alarm at 13:20:10 but its coming at 13:20:some Random second
Your help is much appreciated.
Thank you.
RTC (Real Time Clock) is the clock that you can adjust, so you could possibly just change the current time programatically for a test case. See this answer
You're using a alarmManager.setInexactRepeating method, which doesn't guarantee an exact time of alarm delivery. For more precise timings, use alarmManager.setRepeating, however keep in mind that it's not really recommended, as most use cases do not require exact timings and it will cause higher battery usage. See inexactRepeating and repeating

Android - Alarms sometimes fires at the wrong time using AlarmManager

This problem seems a little bit odd, but if someone as encounter something like this, please help me...
I created an Alarm Scheduler, that sends an alarm to the user using AlarmManager, through this code:
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("tk_alert_id", lastAlertId.getId()+"");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, idRandom, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, date.getTimeInMillis(), pendingIntent);
The problem is that, sometimes, I receive this alarm on my AlarmReceiver (BroadcastReceiver) at a wrong time, as you can see in the image bellow:
image, and I can't figure out what's the problem... I checked the time for date and was set as "2015-05-27 17:00:00", but it was received a little minutes earlier (around 16:57) ...
Does anyone knows what kind of problem I am encountering here?
For API levels <19 you should use AlarmManager.setRepeating() and your alarms will trigger exactly at specified time.
Api levels >=19 and above this no longer works. There was change in android so that all repeating alarms are inexact.
So if you would like to achieve exact repeating alarm use AlarmManager.setExact().
See this question for more info.
Edit
For your purpose (a one-off alarm, at a precise time) use alarmManager.setExact(....). See docs

Alarm Manager events not fired (registering for notifications per day)

I am writing an application which needs a homewidget showing the current date. For that I have used the alarm manager registering as follows:-
Intent intent = new Intent(HomeScreenWidgetProvider.ACTION_UPDATE_DATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetId);
intent.setData(getUriData(appWidgetId));
PendingIntent datePendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarms = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarms.cancel(datePendingIntent);
**alarms.setRepeating(AlarmManager.RTC, getTimeForMidnight(), AlarmManager.INTERVAL_DAY, datePendingIntent);**
As you see, the above code registers for notifications first for the next 12.00AM with an interval of a day from there on. I update the date in my widget when I get a notification from alarm manager.
There is one big problem though. I don't get the alarm manager events when the date changes (at 12.00AM). And so the date does not change in my home screen widget.
The above code works fine in the emulator but not on the device. I am using Samsung Galaxy S 19000 for (real time) testing.
Is there a problem with use of alarm manager? Or is there an alternate way of receiving date change notifications?
I think in setRepeating() method, you should set the first parameter as AlarmManager.RTC_WAKEUP. If you use AlarmManager.RTC, the alarm event won't be triggered when the device is asleep. Please see the SDK document about AlarmManager for more details.
Also, you can register a BroadcastReciever listening to ACTION_DATE_CHANGED, by which you can receive date change event.
Hope it helps.

Categories

Resources