AlarmManager going off whenever app opens - java

I am trying to set an AlarmManager to go off for a specific time during the day. Here is my current code on it -
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 16);
calendar.set(Calendar.SECOND, 0);
long time = calendar.getTimeInMillis();
Intent intent = new Intent(MainActivity.this, Drawing.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MainActivity.this, 0, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, time,
AlarmManager.INTERVAL_DAY, pendingIntent);
The drawing class displays a notification. The alarm does go off at the right time, but anytime the app is re-opened the notification goes off immediately.
I know its nothing to do with the drawing class because when i set the alarm to just go off with System.currentTimeInMillis() + 10 secs it works fine, even when app is reopening.
Any ideas? What is wrong with my logic?

You are not checking to see if calendar is in the past, as it will be ~2/3rds of the time (i.e., any time this code is run after 08:16). You will need to add() a day in that case, to get 8:16 for tomorrow.

Related

How to delay android repeating notification start

I am using this code to start notification that will repeat every 3 days:
public void setNotification() {
boolean alarmUp = (PendingIntent.getBroadcast(this, 10000,
new Intent(this, NotificationReceiver.class),
PendingIntent.FLAG_NO_CREATE) != null);
if (!alarmUp) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 21);
Intent myIntent = new Intent(this, NotificationReceiver.class);
int ALARM1_ID = 10000;
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this, ALARM1_ID, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
assert alarmManager != null;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() + AlarmManager.INTERVAL_DAY, AlarmManager.INTERVAL_DAY * 3, pendingIntent);
}
}
Everything looks good but I want my notification to start 1 day after first starting the application and calling this function. I thought that calendar.getTimeInMillis() + AlarmManager.INTERVAL_DAY part in:
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() + AlarmManager.INTERVAL_DAY, AlarmManager.INTERVAL_DAY * 3, pendingIntent);
is responsible for the first start. But it looks like it is not. Even though I set it to start after 1 day, notification shows up to user immediately after calling this function.
Help?
Use setInexactRepeating() instead of setRepeating(). When you use setInexactRepeating(), Android synchronizes repeating alarms from multiple apps and fires them at the same time.
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
AlarmManager.INTERVAL_DAY * 3, pendingIntent);
Note that:
ELAPSED_REALTIME: Fires the pending intent based on the amount of time since the device was booted, but doesn't wake up the device. The elapsed time includes any time during which the device was asleep.
RTC_WAKEUP: Wakes up the device to fire the pending intent at the specified time.

Need some help to fill in the blanks in code that schedules daily notifications

I've searched through Android studio documentation and found some pieces of code that should schedule daily notifications. Unfortunately, as I'm new to all of this, it has some missing pieces that I can't figure out.
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 20, alarmIntent);
What is this "context" in context.getSystemService, new Intent(context, AlarmReceiver.class), etc.? Is there anything else missing that is not here?
Its the application context. To be clear it is the information and data of the current Activity you want to use(e.g. the MainActivity). You can get it with
Context context = this.getApplicationContext();
Edit: For the sake of more general usage

Android Notification triggering on application startup

I'm trying to get my Daily Notification Service working properly but I am stuck with an issue.
I should receive a notification only at a specific time of the day in the future but I noticed that
if (time_that_i_set_for_notification < current_time_of_the_day) notification triggers at the boot of my app
That's wrong because in that condition, the notification should trigger only the next day, not in the instant I launch the app.
Here's my attempt to get the things working:
I call this in my MainActivity, onCreate() method:
private void scheduleNotification(int hour, int minute){
Intent notificationIntent = new Intent(this, NotificationReceiver.class);
notificationIntent.putExtra("notifId", notifId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, notifId, notificationIntent, 0);
// Set the alarm to start at approximately at a time
DatePicker datePicker = new DatePicker(this);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_MONTH, datePicker.getDayOfMonth());
if(calendar.getTime().compareTo(new Date()) < 0) calendar.add(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 12);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
}
I thought that adding if(calendar.getTime().compareTo(new Date()) < 0) calendar.add(Calendar.DAY_OF_MONTH, 1); I would've achieved the result I needed.
Thank you and have a nice day.
Before calling setInexactRepeating, add this check:
if (calendar.getTimeInMillis() < System.currentTimeMillis())
calendar.setTimeInMillis(calendar.getTimeInMillis() + AlarmManager.INTERVAL_DAY);
Hope this helps.
Ok there's a wrong check there, if you change it, you should be able to solve your issue.
Here we go:
Intent notificationIntent = new Intent(this, NotificationReceiver.class);
notificationIntent.putExtra("notifId", notifId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, notifId, notificationIntent, 0);
// Set the alarm to start at approximately at a time
DatePicker datePicker = new DatePicker(this);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_MONTH, datePicker.getDayOfMonth());
//if(calendar.getTime().compareTo(new Date()) < 0) calendar.add(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 14);
calendar.set(Calendar.MINUTE, 50);
if (calendar.getTimeInMillis() < System.currentTimeMillis()) calendar.setTimeInMillis(calendar.getTimeInMillis() + AlarmManager.INTERVAL_DAY);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
I commented //if(calendar.getTime().compareTo(new Date()) < 0) calendar.add(Calendar.DAY_OF_MONTH, 1);
because it should be unnecessary.
Let me know if it worked.
UPDATE: You should totally check whether the Service that handles your daily notification is high consume or not. A High-draining battery app would bother your users.

Issues scheduling alarms when getting the time to set the AlarmManger for using a TimePicker because of AM/PM

I'm programming an app that has a feature that the user can use to set an alarm for an SMS message to be send to someone. The problem I am having is say the user sets the Alarm-Manager to go off at 9:00 A.M. and it is currently 10:00 P.M. then the alarm immediately goes off. It doesn't recognize the fact that the alarm should be set for the next day.
Here is the code for setting up the AlarmManager:
Intent intentAlarm = new Intent(MainMenu.this, AlarmReceiver.class);
intentAlarm.putExtra("phoneNumber", phoneNumber);
intentAlarm.putExtra("message", message);
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), PendingIntent.getBroadcast(MainMenu.this, 1, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT));
Other than the AM/PM issue, the AlarmManager works well. I just don't know where to go from here and all of the documentation I am looking at just doesn't help.
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, 10); // use hour of day for am pm issue
cal1.set(Calendar.MINUTE, 00);
cal1.set(Calendar.SECOND, 00);
Calendar now = Calendar.getInstance();
if (now.after(cal1))
cal1.add(Calendar.DAY_OF_YEAR, 1);
// this code snippet add one day if the current time passed away
//else use cal1.set(year, month, day); for exact day
public void SetAlarm(Context context) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
// set alarm after 12 hours
long after = System.currentTimeMillis() + 12 * 60 * 60 * 1000;
am.set(AlarmManager.RTC_WAKEUP, after, pi);
}

How to cancel PendingIntent at specific time?

AlarmManager works perfectly when I have not declared cancel but do not fire when I declare the cancel..
Here is the code:
Calendar c= Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 37);
c.set(Calendar.SECOND, 0);
Toast.makeText(this, c.getTime().toString(), Toast.LENGTH_LONG).show();
intent = new Intent(TestAlarm.this, TestAlarmService.class);
pi = PendingIntent.getService(TestAlarm.this, 1, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi);
and cancel code:
c.add(Calendar.HOUR_OF_DAY, 0);
c.add(Calendar.MINUTE, 38);
c.add(Calendar.SECOND, 0);
PendingIntent pi1=PendingIntent.getService(TestAlarm.this, 1, intent, 0);
AlarmManager am1 = (AlarmManager) getSystemService(ALARM_SERVICE);
//stopService(intent);
am1.cancel(pi);
Now here I want to start my AlarmManager to go off at 12:37 and cancel after one or two minutes...But Whenever I use cancel code the AlarmManager never fires...
Thanks in Advance! :)
Change the line am1.cancel(pi); to am1.cancel(pi1); - you're cancelling the original PendingIntent
Also, in your cancel code, you're calling c.add() (which add on to the current date/time) instead of c.set() (which explicitly sets the next date/time). By calling c.add(Calendar.MINUTE, 38), you're actually adding 38 minutes to the current Calendar, instead of setting the time to 12:38;

Categories