I've searched for examples of how to implement such a problem but couldn't find anything that could solve my problem so I'm asking you for an advice how to solve it.
I have to implement an alarm that fires every day at a specific time during the period between two specified dates.
Up to now I have a repeating alarm firing every day at a specific time but not specified until when to repeat...
Any advice and ideas will be highly appreciated!
Suppose you want to set an repeating Alarm from Date1 to Date2.
For Date1, there is no problem for you since it is working.
Set an alarm for Date2 and when that alarm is fired cancel Date1 repeating alarm.
I do it like this:
Lets say you wanted to set a repeating alarm, that first triggered at a 'random' time between two hours (e.g. 0100 - 0500) in the day, and then always triggered at that same time of day again every 24 hours.
private long getTimeOfNextWidgetAutoUpdateInMilliseconds(Calendar now, int startHour, int endHour){
// calc the time diff in milliseconds from now until a 'random' time between startHour and endHour
// ensure to +1 day if the time has already passed
}
private void createAutoRefreshAlarm(Context context, long initialTriggerTimeInMillis,
long intervalInMillis) {
AlarmManager alarmManager = getAlarmManager(context);
PendingIntent widgetRefreshPi = getWidgetRefreshAlarmPendingIntent(context);
setRepeatingAlarm(initialTriggerTimeInMillis, intervalInMillis, widgetRefreshPi,
alarmManager);
ApplicationData.setAppDataBoolean(WIDGET_REFRESH_ALARM_SERVICE_INITITATED, true);
}
private static void setRepeatingAlarm(long initialTriggerTimeInMillis, long intervalInMillis,
PendingIntent widgetRefreshPi, AlarmManager alarmManager) {
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
initialTriggerTimeInMillis,
intervalInMillis,
widgetRefreshPi);
}
private PendingIntent getWidgetRefreshAlarmPendingIntent(Context context) {
Intent alarmIntent = new Intent(context, AlarmManagerBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
private static AlarmManager getAlarmManager(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
return alarmManager;
}
I would then have the following in the WidgetProvider class:
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
int startHour = 1;
int endHour = 5;
long initialTriggerTimeInMillis = getTimeOfNextWidgetAutoUpdateInMilliseconds(
Calendar.getInstance(),
startHour,
endHour);
long intervalInMillis = 86400000; // 24 hours
createAutoRefreshAlarm(context, initialTriggerTimeInMillis, intervalInMillis);
}
This should get you going, I've cut+pasted from my own project, so there may be a few errors.
Also, remember to cancel your alram in the onDisabled() method of your `WidgetProvider.
There are other scenarios that delete the alarm that you should consider, e.g. ON BOOT
Related
I am trying to implement alarm that notify daily at the same time. It works fine. But when i set alarm again it notify me on the spot without waiting time to come, because time on which alarm is set has been passed. But when I change Calendar.DATE to Calendar.DAYS_OF_MONTH it does not notify me. So can any one help me where i am wrong. I am sharing my code below.
public void setNotification() {
PendingIntent pendingIntent = createPendingIntent();
Calendar calendarToSet=Calendar.getInstance();
Calendar currentTime=Calendar.getInstance();
calendarToSet.set(Calendar.HOUR,10);
calendarToSet.set(Calendar.MINUTE,0);
calendarToSet.set(Calendar.SECOND,0);
calendarToSet.set(Calendar.AM_PM,Calendar.AM);
if(calendarToSet.before(currentTime))
{
calendarToSet.set(Calendar.DATE,1);
}
AlarmManager alarmManager = (AlarmManager) MyAppManager.context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendarToSet.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);
// Toast.makeText(MyAppManager.context, "set", Toast.LENGTH_LONG).show();
}
public PendingIntent createPendingIntent() {
Intent intent = new Intent(MyAppManager.context, TaffaquhFiddinBroadCastReceiver.class);
intent.putExtra("key", "What_to_say_upon_completing_ablution");
PendingIntent pendingIntent = PendingIntent.getBroadcast(MyAppManager.context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
What i am trying to do is to set alarm for the next day if the time is passed so please help.
Also what is the difference between Calendar.DATE and Calendar.DAYS_OF_MONTH?
The problem is you are setting the day field of your Calendar instance, instead of adding a day to it.
Change the following:
calendarToSet.set(Calendar.DATE, 1);
To this:
calendarToSet.add(Calendar.DATE, 1);
Also what is the difference between Calendar.DATE and
Calendar.DAYS_OF_MONTH?
They are the same, DATE is just a synonym for DAY_OF_MONTH.
From the source code of the Calendar class:
public static final int DATE = 5;
public static final int DAY_OF_MONTH = 5;
As you can see, they represent the same value.
TL;DR - AlarmManager .setRepeating is starting immediately instead of the desired future time.. (for example 5 minutes from now)
So basically I am starting an alarm manager and i'm giving it the time left to operate and for some reason it is firing instantly.. the user is choosing a time from a time picker, and I set this time for the next alarm.
code below:
-this method get's the time left until the alarm, this is used as the triggerInMillis for the alarmManager.
/** calculate the time left until the alarm with calendar */
private static long getTimeFromCalendar(final int hourOfDay, final int minute) {
Date dat = new Date();//initializes to now
Calendar cal_alarm = Calendar.getInstance();
Calendar cal_now = Calendar.getInstance();
cal_now.setTime(dat);
cal_alarm.setTime(dat);
cal_alarm.set(Calendar.HOUR_OF_DAY,hourOfDay);
cal_alarm.set(Calendar.MINUTE, minute);
cal_alarm.set(Calendar.SECOND,0);
if(cal_alarm.before(cal_now)){
cal_alarm.add(Calendar.DATE,1);
}
long calAlarm = cal_alarm.getTimeInMillis();
long calNow = cal_now.getTimeInMillis();
long timeLeft = (calAlarm - calNow);
return timeLeft;
}
then I call the -startAlarm- method :
private static void startAlarm(final Enums typeToStart) {
final PendingIntent pendingIntent = GBAlarms.createPendingIntent(OnAlarmReceiver.class, Constants.typeEnum, typeToStart);
final long timeToAlarm = Utils.getTimeToAlarm(typeToStart);
long repeatTime = Constants._24hours;
GBAlarms.createRepeatingAlarm(timeToAlarm, repeatTime, pendingIntent);
}
and finally, my -GBAlarms.class- where i create my alarms and pending intents.
public class GBAlarms {
/** Define our AlarmManager */
private static AlarmManager mgr = (AlarmManager) BaseApplication.getAppContext().getSystemService(Context.ALARM_SERVICE);
/** Create a new PendingIntent */
public static PendingIntent createPendingIntent(final Class destination, #Nullable final String extra, Enums.TeaType type) {
Intent i = new Intent(BaseApplication.getAppContext(), destination);
if (extra != null && type != null) { i.putExtra(extra, type); }
PendingIntent pi = PendingIntent.getBroadcast(BaseApplication.getAppContext(), type.getValue() , i, 0);
return pi;
}
/** Create a new repeating Alarm */
public static void createRepeatingAlarm(final long time, final long repeatTime, final PendingIntent pi) {
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, repeatTime, pi);
}
}
I don't understand, for some reason the alarm pops right when I set it in the -createRepeatingAlarm- method, and I debugged of course, the time parameter looks legit.. if I set it to 3 minutes, 10 minutes, it puts that time left in the trigger..
can anyone spot my mistake? maybe I'm missing something?
thanks a lot for any help.
You are creating a "pending" alarm,
a alarm that repeats after a specific interval.
The trick is to cancel the current alarm in the moment you are starting.
Look at the code below: You have to call the method getBroadcast with the
flag PendingIntent.CANCEL_CURRENT
AlarmManager alarmMgr;
PendingIntent pendingIntent;
public void startAlarmManager()
{
Intent dialogIntent = new Intent(getBaseContext(), AlarmBroadcastReceiver.class);
alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
pendingIntent = PendingIntent.getBroadcast(this, 0, dialogIntent,PendingIntent.FLAG_CANCEL_CURRENT);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(), 10000, pendingIntent);
}
}
why are you using ELAPSED_TIME?
please try using RTC_WAKEUP and switch
long timeLeft = (calAlarm - calNow);
with just calAlarm
you don’t need to mills left, you need the mills that you want it to pop.
I know this is most common thread in SO but i didn't find any answer for my question . I want to trigger dynamic broadcast receiver at particular time. For this i am using below code
public void method1() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent i) {
doTASK();
}
};
registerReceiver(br, new IntentFilter("com.XXXX.wakeup"));
pi = PendingIntent.getBroadcast(this, 0,
new Intent("com.xxxx.wakeup"), 0);
am = (AlarmManager) (this.getSystemService(Context.ALARM_SERVICE));
setAlarmManagerObject();
}
And setAlarmManagerObject() method is here
public void setAlarmManagerObject() {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
cal.set(year, month, day
, com.XXXX.Constants.AlarmHour
, com.xxxx.Constants.AlarmMinute
, com.xxxx.AlarmSecond);
am.setRepeating(AlarmManager.ELAPSED_REALTIME, cal.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pi);
}
My problem is that when i used AlarmManager.RTC_WAKEUP it wake up when device is off. I don't want this property in my app. So i used AlarmManager.ELAPSED_REALTIME, but with ELAPSED_REALTIME alarm manager is not triggering. I want that my alarm manager trigger exact at same time. If device is off or sleep condition then alarm manager will also off after device wake up.It should trigger at exact time. Any help will really appreciated.
You need to use something like this:-
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP (or AlarmManager.ELAPSED_REALTIME),
SystemClock.elapsedRealtime() + Constants.DELAY_IN_MILLIS,
pendingIntent);
You can calculate DELAY_IN_MILLIS which is time delay in milliseconds from current system time.
For repeating alarm you can have code something like this:-
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + Constants.DELAY_IN_MILLIS,
Constants.ONE_DAY_IN_MILLIS,
pendingIntent);
I'm making an application that lets the user choose days and start an alarm on a specific time on those days.
lets take my problem as an example I want my alarm to fire every Friday at 12:30
the problem is It just never fires the alarm even though I'm in the same day here is my code
cals = Calendar.getInstance();
int days = Calendar.FRIDAY + (7 - cals.get(Calendar.DAY_OF_WEEK)); // how many days until Sunday
cals.add(Calendar.DATE, days);
cals.set(Calendar.DAY_OF_WEEK,6);
cals.set(Calendar.HOUR_OF_DAY, 12);
cals.set(Calendar.MINUTE, 30);
cals.set(Calendar.SECOND, 0);
cals.set(Calendar.MILLISECOND, 0);
alarm.SetAlarm(getApplicationContext(), 10,"Start", cals.getTimeInMillis());
public void SetAlarm(Context context,int id,String sor,long time)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
if(sor.equals("Start"))
{
Intent i = new Intent(context, MyAppReceiver.class);
PendingIntent p = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, time, DateUtils.DAY_IN_MILLIS, p);
}
}
Did you register your MyAppReceiver as a BroadcastReceiver in the AndroidManifest.xml?
I have a scheduleAlarm class which is supposed to set the alarm in a specific time, however the alarm is being fired immediately after the method is called. I've checked that provided time in milliseconds is fine, so I've no idea what's going on.
private void scheduleAlarm(int day, int startHour, int startMinute, String info) {
AlarmManager mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK, day);
c.set(Calendar.HOUR, startHour);
c.set(Calendar.MINUTE, startMinute);
Intent startIntent = new Intent(this, Recorder.class);
startIntent.putExtra("info", "someinfo");
Log.v("millis", String.valueOf(c.getTimeInMillis())); // time is okay
Random mRandom = new Random();
int randomInt = mRandom.nextInt();
PendingIntent pendingIntent = PendingIntent.getService(this, randomInt, startIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
}
Just make sure that the time set for the alarm is after current time.
There is an easy way to check that.
just do
Calendar.getInstance().getTimeInMilis() - c.getTimeInMillis()
Log this result, and you can see if the second is before the first.
Lets say now is 4 o'clock, and you set the same day and 3 o'clock. it will get activated instantly.
Other than that i see no reason why it should fail.
Another way to test would be to use currentTime and add lets say 10k miliseconds and see if it activates in 10 seconds after you test it. Then you are sure that the time set is wrong in your case.