I have this static helper function, to set a daily-repeating alarm:
public static void setAlarm(Context context, int hh, int mm)
{
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hh);
calendar.set(Calendar.MINUTE, mm);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intentAlarm = new Intent(context, AlarmReciever.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intentAlarm, 0);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
}
I have three places where this helper function is called:
When device boots up, I want to re-register the alarm:
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
setAlarm(context, 7, 00);
}
}
In one of my activities, call it ActivityA:
AlarmReciever.setAlarm(ActivityA.this, 7, 00);
In another activity, call it ActivityB:
AlarmReciever.setAlarm(ActivityB.this, 7, 00);
Questions:
What would happen if all three kinds of setAlarm() are called? I'm concerned that they don't have the same context. Would android know they are the same PendingIntent and only fire once? I want it to only fire once at 7 am.
What if I press setAlarm button in ActivityA a few times so the same alarm is set with the same context and intent, when 7 am comes, how many would fire?
Say it fired at 7 am this morning and now it's 2 pm in the afternoon. I now press the button in ActivityA. The alarm would fire instantly (tested), because 7 am is a "past time". But before adding the new alarm, shouldn't the system check existing ones, and realize this is a repeating intent, and one has been fired at 7 am already? In my opinion it should ignore my setAlarm() requested at 2 pm.
For what it's worth, I did experiments and I'm posting the results here in case anyone else wonders:
As long as the PendingIntent is identical, android will only fire the alarm once. You may set the alarm however many times you want, from whatever activities/classes you want.
One.
The new alarm will just trigger right way (because 7 am is a "past time"). You can write code to record the last fired date/hour (e.g. use SharedPreferences), and do some logic there, or depends on your situation, you may want to schedule the alarm to fire at 7 am the next day (do a plus one day on the Calendar object).
Related
I want to repeat a notification in android at a scheduled time in a specific day of the week (8:30am Saturday). I have set up the code and the alarm works (with the notification). The alarm need not wake up the device and fires the notification on next wake up.
Problem: The alarm is fired once every time the app is newly opened.
Tried different combinations but cant get it to work. Your help is much appreciated. Thank you.
MainActivity.java (OnCreate)
AndroidHelper ahelper= new AndroidHelper();
public static long rand_news_notify_freq= AlarmManager.INTERVAL_DAY * 7;
Calendar ca = Calendar.getInstance();
ca.set(Calendar.HOUR_OF_DAY,8);
ca.set(Calendar.MINUTE,30);
ca.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
ca.set(Calendar.SECOND, 0);
ca.set(Calendar.MILLISECOND, 0);
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
ahelper.setAlarms(alarmMgr, getApplicationContext(), RandomNewsNotification.class, ca, rand_news_notify_freq);
AndroidHelper.class
public class AndroidHelper{
public AndroidHelper()
{
}
public void setAlarms(AlarmManager alarmMgr, Context tctx, Class alarmClass, Calendar calendar, long freq)
{
Intent alarmIntent = new Intent(tctx, alarmClass);
PendingIntent pendingIntent = PendingIntent.getBroadcast(tctx, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
//alarmMgr.setRepeating(alarmMgr.RTC, calendar.getTimeInMillis(), freq, pendingIntent); // This is not working
alarmMgr.setInexactRepeating(alarmMgr.RTC, calendar.getTimeInMillis(), freq, pendingIntent); // This is not working too (same problem)
}
}
What needs to be changed?
I don't know you want to set exact repeating or inexact repeating. for exact repeating, you yourself should handle repeating with exact methods and don't use repeating methods of alaramManager like setInexactRepeating.
also consider if device is on Doze mode, alaram won't fire. so you should use setExactAndAllowWhileIdle method to guarantee that the alarms will execute.
you can see more detail on Android Developer document:
https://developer.android.com/training/scheduling/alarms
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.
I am working on Android AlarmManager and i found one issue in my code. The Alarm manager gets called in different time as well , i don't find what's the reason , i gave alarm at 7:10 AM but it gets called whenever i open the app in different time like 3:10 PM , 4:30 PM etc.
MyCode :
public void setAlarm(){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) + 1);
calendar.set(Calendar.HOUR_OF_DAY, 7);
calendar.set(Calendar.MINUTE, 10);
calendar.set(Calendar.AM_PM,Calendar.AM);
Intent intent = new Intent(appContext, MyAlarmManager.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(appContext, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) appContext.getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
MyAlarmManager.java
public class MyAlarmManagerextends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
setAlarm();
} }
So , this is the above code , please let me know what's wrong in the code and suggest me some solution.
This is happening because the alarm is set in the past (when you set it anytime after 07:10 AM) So, you have to add 1 day if it is past 07:10 AM today.
Explanation -
Suppose it is 8 AM today and you are setting an alarm for 07:10, it sets an alarm for the same day 07:10 AM which is already past, hence it goes off whenever you open the app
Solution -
Option 1 - Either set date, month and year too like -
calendar.set(Calendar.DATE, date);
calendar.set(Calendar.MONTH, month);
Option 2 - Check what is the current time, if current time > the alarm time, add one day to the alarm
//If you are past 07:10 AM then
calendar.add(Calendar.DATE,1);
This might happen if you are using Android version Marshmallow or higher. It is called Doze Mode
Doze Mode is implemented to save the battery by delaying stuff like AlarmManager, SyncAdapter, JobScheduler. Refer to this link to find out more about Doze Mode
I'm trying to update fragment on clock time, say for example 8PM, with below logic. Unfortunately, it doesn't update the fragment. Any help/reference would be appreciated.
What I did:
registered an AlarmManager in app's Application class as below:
alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent().setAction(AppConstants.INTENT_ACTION_UPDATE_DASHBOARD);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
// Set the alarm to start at Consulting start time
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
alarmMgr.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);
Listens for AlarmManager in Fragment as below:
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mDashboardUpdateReceiver, new IntentFilter
(AppConstants.INTENT_ACTION_UPDATE_DASHBOARD));
and performs actions if broadcast receives:
private BroadcastReceiver mDashboardUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Dashboard updating...");
updateCounters();
}
First, a PendingIntent does not trigger a local broadcast. You cannot use LocalBroadcastManager here.
Second, using AlarmManager to update a UI is rather odd. If your UI exists, you have a process running, so you could use something in-process (e.g., ScheduledExecutorService) rather than fussing with AlarmManager.
Third, you are not taking into account that set(Calendar.HOUR_OF_DAY, hour) and calendar.set(Calendar.MINUTE, minute) might change the Calendar to be in the past. Imagine if you execute your first code snippet at 23:00, with hour set to be 22 and minute set to be 0. The Calendar object that you create will be for today, but for 22:00 today, which was an hour before now (23:00). You need to check the Calendar, see if it is in the past, and if so, add() a day or otherwise adjust it to some future time.
I want to start alarm when i have selecting the days,hours,and minutes.
This is my code so far :
public void startAt() {
Intent alarmIntent = new Intent(backgroundApplication.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(backgroundApplication.this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_WEEK,calendar.WEDNESDAY);
calendar.set(Calendar.HOUR_OF_DAY,7);
calendar.set(Calendar.MINUTE,35);
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 5, pendingIntent);
}
For the example i set the DAY_OF_WEEK is today(friday) it works great. But when i changed it into Wednesday, or other day before friday it still running.
Is there any other way to start in selected days ?
According to the documentation http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating%28int,%20long,%20long,%20android.app.PendingIntent%29, the 2nd parameter is the trigger time in milliseconds and if you set it to a time in the past, the alarm will trigger immediately. If you want the alarm to only start from next Wednesday, then you have to advance your Calendar time to the next Wednesday with calendar.add(Calendar.WEEK_OF_MONTH, 1). By the way, in your code, you don't need to have calendar.setTimeInMillis(System.currentTimeMillis()).Calendar.getInstance() will return the current time by default. You should also use static field Calendar.WEDNESDAY.