I have read many articles, but non seems to work for me!
I have to schedule a repeating task with AlarmManager for everyday at 7:15. The following method is set in an activity and registered a broadcast receiver for it!
private void setTask(Context context) {
Calendar updateTime = Calendar.getInstance();
updateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
updateTime.set(Calendar.HOUR_OF_DAY, 7);
updateTime.set(Calendar.MINUTE, 15);
Intent intent = new Intent(context, NotifyUpdate.class);
PendingIntent fireAlarm = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(alarms.RTC_WAKEUP, updateTime.getTimeInMillis(), alarms.INTERVAL_DAY, fireAlarm);
}
The problem is when I run the app the method gets executed immediately regardless of the time set, but not executing at (7:15).
Any Idea?
Try this before setting alarm
Calendar now = Calendar.getInstance();
if (updateTime.before(now)) {
updateTime.add(Calendar.DAY_OF_MONTH, 1); // if its in the past increment
}
alarms.setRepeating(alarms.RTC_WAKEUP, updateTime.getTimeInMillis(), alarms.INTERVAL_DAY, fireAlarm);
You said that you have immediate triggering not depending on time. It's happening because updateTime-object references at time in the past, so the goal is to set an alarm to 7:15 in the future. This will help to avoid immediate triggering.
Related
Below is the code I am using to create alarms when data is pulled from external API. If the time set is in the past, the alarm goes off as soon as it is set(2 second gap). For example if I set the alarm for 8:00 AM, 10th April at 10:00 AM on 11th April(Past time). It starts the alarm as soon as it is set.
public static final int ALARM_REQUEST_CODE = 1001;
public static AlarmManager alarmManager = (AlarmManager) EHCApplication.getInstance().getApplicationContext().getSystemService(Context.ALARM_SERVICE);
public static Intent alarmIntent = new Intent(EHCApplication.getInstance().getApplicationContext(), AlarmReceiver.class);
public static PendingIntent pendingIntent = PendingIntent.getBroadcast(EHCApplication.getInstance().getApplicationContext(), ALARM_REQUEST_CODE, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
public static void setAlarm(Reminder rm) {
for (ScheduledTime time : rm.getScheduledTime()) {
Bundle bundle = new Bundle();
bundle.putParcelable(Constants.ARGS_SELECTED_MEDICINE, medicine);
alarmIntent.putExtras(bundle);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time.getTimeInMilliseconds(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
I am expecting the alarm to go off from next time it hit the time. Where am I making mistake?
This is the expected behavior.
From the documentation of setRepeating() (and other AlarmManager set methods):
If the stated trigger time is in the past, the alarm will be triggered
immediately
If you would like to prevent that happening, then simply do not set alarms with a past trigger time (e.g. check against System.currentTimeMillis() when setting the alarm).
Well, I ran into same problem and after studying I found that alarm will be run as soon when past time is set for the alarm.
Source: Here is documentation of Alarm Manager - setRepeating()
So, I resolved the issue by checking if "Calendar time is in past from system time than I add a day"
Working code:
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, min);
calendar.set(Calendar.SECOND, 0);
alarmManager.cancel(pendingIntent);
// Check if the Calendar time is in the past
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
Log.e("setAlarm","time is in past");
calendar.add(Calendar.DAY_OF_YEAR, 1); // it will tell to run to next day
}
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent); //Repeat every 24 hours
I am setting alarm usng this
Calendar now = Calendar.getInstance();
Calendar alarm = Calendar.getInstance();
alarm.set(Calendar.HOUR_OF_DAY,21);
alarm.set(Calendar.MINUTE,30);
if (alarm.before(now)) {
alarm.add(Calendar.DAY_OF_MONTH, 1); //Add 1 day if time selected before now
}
AlarmManager alarmManager =(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context,Receiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context,(int)alarm.getTimeInMillis(),i,0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, (int)alarm.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pi);
But even if I schedule it for next day,it triggers immediately after saving alarm.
Dont know what the issue is have searched a lot but everyone else gets it working
You are casting a long timestamp to int thus losing bits and changing the actual timestamp value. You end up with a time that already has passed so it executes the intent immediately.
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarm.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
Notice that I removed the (int) cast in the last line.
I have created a pending intent that fires a repeating alarm every minute. The alarm works fine but when I cancel the alarm, it still fires. I have read other posts about this and I made sure that everything is as suggested, mainly to use FLAG_UPDATE_CURRENT and to use the same code for the intent, when creating and when cancelling. Here is the code I use:
Create the alarm:
final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final Calendar c = Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
c.add(Calendar.MINUTE, 1);
alarmManager.setRepeating(AlarmManager.RTC, c.getTimeInMillis(), 1000 * 60, getIntent(context));
Cancel the alarm:
final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
getIntent(context).cancel();
alarmManager.cancel(getIntent(context));
The getIntent function:
public static PendingIntent getIntent(Context context) {
return PendingIntent.getBroadcast(context, 20, new Intent(ACTION_MINUTE_ALARM), PendingIntent.FLAG_UPDATE_CURRENT);
}
Does anyone know what the problem is?
After a lot of struggle I discovered that there was another service running (different apk) that was also creating exactly the same pendingIntent using a repeating alarm. Removing that service fixed the problem. Therefore, the method described in the original question works. Hope this helps someone.
I have an alarm checker in my activity (Groups.java) to start a service each few seconds:
public void lookForGroups()
{
int seconds = 40;
Intent myIntent = new Intent(Groups.this, GroupsTaskAlarmChecker.class);
pendingIntent = PendingIntent.getService(Groups.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), seconds * 1000, pendingIntent);
}
Also depending on sharedPreferences variable I start this service when I reboot device.
Is posible to "kill" or start that alarm checker depending of a value of a variable?
for example to automatically or manually sync my application.
Thank you very much in advance and sorry for mi english ;)
Not sure if I understand this...but you create an Alarm checker and want to kill it if it's already running?
alarmManager.cancel(pendingIntent)
should do it. According to the reference, it will cancel any alarms with a matching intent
My application schedules multiple alarms for particular times. These alarms are scheduled when the application starts. (For each day there are 5 alarms resulting in 35 alarms per week)...
I have verified through logs that these alarms are scheduled when the application starts.
The problem is when I started testing my application the 7 alarms goes off perfectly fine. However the 8th alarm doesn't fired. I have tested this scenario by keeping my device still for more than 1 day. How can I debug this behaviour and what are the possible reasons that prevent alarm for firing.
Edit:
Code for scheduling:
try {
if (info != null) {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day);
c.set(Calendar.HOUR_OF_DAY, info.getHour());
c.set(Calendar.MINUTE, info.getMinute());
c.set(Calendar.SECOND, 0);
Intent intent = new Intent(context, AlarmReceiverActivity.class);
intent.putExtra("name", info.getPrayerName());
intent.putExtra("sound", soundType);
intent.putExtra("time", formatTimeClock(context, info.getHour(), info.getMinute()));
PendingIntent pendingIntent = PendingIntent.getActivity(context, alarmId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
}
} catch (Exception e) {
Log.e("ALarmSchedularManager", e.getMessage());
}
How can I debug this behaviour
Use adb shell dumpsys alarm to see what your scheduled alarms are and when they are next to be invoked.
what are the possible reasons that prevent alarm for firing
Your code does not appear take into account the possibility that the time has already passed, though that may be handled outside the code snippet you show above.
Hopefully below code will help, I used the same in my app. Here the argument passed in AlarmManager class for repeating should be 24*60*60*1000
AlarmManager am = (AlarmManager) ct.getSystemService(Context.ALARM_SERVICE);
Intent intent1 = new Intent(ct, TimeAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(ct, 0,intent1, PendingIntent.FLAG_CANCEL_CURRENT);
Date curr=new Date();
curr.setHours(h);
curr.setMinutes(m);
c.setTime(curr);
c.set(Calendar.SECOND, 0);
Calendar c1 = Calendar.getInstance();
am.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),24*60*60*1000, pendingIntent);
instead of hard code manipulation (24*60*60*1000) you can use AlarmManager.INTERVAL_DAY. Check this for different interval upto 1 day http://developer.android.com/reference/android/app/AlarmManager.html#INTERVAL_DAY