How to set multiple AlarmManagers? - android

I have an app that needs to set alarms for multiple days of the week, depending on what days the user sets them. I have it working where it triggers an alarm at the appropriate time, but am wanting to know how to do multiple without them overridding the current AlarmManager. For example, here is my test code:
final int alarmid = (int)System.currentTimeMillis(); //creates unique id for the alarm attached to the object
tempmainfrag.mainObjectList.returnSchedule(i).setAlarmId(alarmid);
for(int j = 0; j < 7; j++)
{
if(tempmainfrag.mainObjectList.returnSchedule(i).returnDays()[j]) //if this day of the week has an alarm
{
int adjustedday = j+2; //makes time for DAY_OF_WEEK where sunday = 1, monday = 2, etc.
if (adjustedday == 8)
adjustedday = 1;
Calendar startcal = Calendar.getInstance();
startcal.set(Calendar.DAY_OF_WEEK, adjustedday);
startcal.set(Calendar.HOUR_OF_DAY, tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[0]);
startcal.set(Calendar.MINUTE, tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1]);
startcal.set(Calendar.SECOND, 0);
Log.i("mydebug","Starting cal day of week: " + adjustedday);
Log.i("mydebug","Starting cal hour of day: " + tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[0]);
Log.i("mydebug","Starting minute: " + tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1]);
Intent intent = new Intent(this, SilenceHandler.class);
intent.putExtra("starttime",tempmainfrag.mainObjectList.returnSchedule(i));
intent.putExtra("alarm_message", "Test!"); //FOR TESTING
PendingIntent pendintent = PendingIntent.getBroadcast(this, alarmid, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmman = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmman.setRepeating(AlarmManager.RTC_WAKEUP, startcal.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, pendintent);
// startcal.set(Calendar.MINUTE, (tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1])+1);
// alarmman.setRepeating(AlarmManager.RTC_WAKEUP, startcal.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, pendintent);
}
}
The for loop iterates through days of the week, and at each iteration checks to see if the alarm should be set for that day. This code works (presumably), but to test if I could set another alarm on top of it I added in the last two lines of code that are commented out here. This makes the alarm go off a minute later, but not a minute earlier as well. I am doing this to demonstrate that if I want this code to work for multiple days of the week, the way the code is currently set up will just have the alarm set for the last day of the week that returns true. How can I make multiple alarms?

The problem is that although you are creating a unique ID for your PendingIntent, which would set separate alarms, in your test you are reusing the same PendingIntent, which would override your previous one. Create a new PendingIntent with a different alarmid to test this.

Related

how to set multiple alarms using sqlite data?

I am new to android ,here I am developing an alarm app for my working knowledge .
I have completed the following :
creating alarms and storing it into sqlite database.
Fetching all the alarms which has the status as active .
I have tried many stackoverflow post and their solutions and other blog posts which related to my doubt but I can't get a solution for my problem .
What is my problem is I am receiving number of alarm timings from sqlite database which I have set it before and I want to set all the alarms on the stored time .
Here I don't know how to set it .
Can anyone help me to set the multiple alarms .
I am really looking for someone's help to learn and experience these things please help me .
Thanks.
You need Alarm Manager and Pending Intent more.
for (int i = 0; i < ActivemyAlarms.size(); i++) {
int mHour = 0,mMin=0;
String amPm = null;
int mAlarmId = ActivemyAlarms.get(i).getALARM_ID(); //each alarm has an unique Id ,for differentiate one from another
String mAlarmTime = ActivemyAlarms.get(i).getALARM_TIME(); // alarm time (11:12:AM)
if (!(mAlarmTime == null)) {
String mtime = mAlarmTime; // alarm time format is 12hr format (ex : 11:12:AM)
String[] time = mtime.split(":");
mHour = Integer.parseInt(time[0].trim()); // get 11 hour
mMin = Integer.parseInt(time[1].trim()); // get 12 min
amPm = ((time[2].trim()));
}
Calendar calendar = Calendar.getInstance();
calendar.set(calendar.HOUR_OF_DAY, amPm!=null && amPm.equalsIgnoreCase("pm")?(mHour+12):mHour);
calendar.set(calendar.MINUTE, mMin);
calendar.set(calendar.SECOND, 0);
calendar.set(calendar.MILLISECOND, 0);
Intent intent = new Intent(this,AlarmReceiver.class); //calling my Alarm service class which plays a music on the specific time
final int _id = (int) System.currentTimeMillis(); // get calendar instance
//Use Alarm manager and Pending Intent
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, mAlarmId, intent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);
}
And to cancel any Alarm call alarmManager.cancel(PendingIntent) like;
Intent intent = new Intent(this,AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, mAlarmId, intent, 0);
alarmManager.cancel(alarmIntent);

AlarmManager shifts time by 12 hours

I'm trying to create periodical notifications.
So, I created a function to reschedule new notification time:
private void rescheduleNotification(Context context) {
long nextNotifTime = System.currentTimeMillis();
// Schedule next notification in 15 minutes
nextNotifTime += 15 * 60 * 1000;
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(nextNotifTime);
// It's an old version with the same result
//calendar.add(Calendar.MINUTE, 15);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm:ss", Locale.ENGLISH);
this.logEvent(" Next notification time is: " + sdf.format(calendar.getTimeInMillis()));
Intent intent = new Intent(context, WordsBcReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager manager = (AlarmManager)context.getSystemService(ALARM_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= 23) {
manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextNotifTime, pendingIntent);
} else {
manager.set(AlarmManager.RTC_WAKEUP, nextNotifTime, pendingIntent);
}
this.logEvent(" Set next notification time: " + sdf.format(nextNotifTime));
}
Sometimes it runs correctly, but sometimes notification time shifts by exactly 12 hours.
I added special function to log all time manipulations, so the log contains:
29/12/17 11:30:36: Next notification time is: 29/12/17 12:00:36
29/12/17 11:30:36: Set next notification time: 29/12/17 12:00:36
seems OK, but adb shell dumpsys alarm says:
type=0 whenElapsed=+11h34m13s906ms when=2017-12-30 00:00:36
I tried to use Calendar (I to exclude some periods later), but result was the same.
Can't find the problem...

Setting notifications based on timepicker and Spinner value

I have two time picker and spinner with value 1 to 10, I want to make number of local notification selected from spinner between time selected from two time picker for eg from 2 pm to 6 pm I want to show six notification and it should notify every day between selected time range with selected value, I have used alarm manager for this but it showing just one notification also used set repeating.
Also I tried to first find time difference from two picker in millis and applied some logic but nothing seems to be good. Please give me some logic or sample code will be appreciated.
Some code snippet is
Intent myIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
myIntent, 0);
long next = 0;
for (int i = 0; i < spinnervalue ); i++) {
Log.e("checkkkk ", "" + "checkkkk");
alarmManager.set(AlarmManager.RTC_WAKEUP, next, pendingIntent);
next += diff_millis;
}
This snippet should work, perhaps with a few changes.
Here i am getting the difference between the 2 time pickers in milliseconds and += to the current time in milliseconds. Giving each pending intent a different ID and telling it to update and existing one if available (allows you to reset them if you know the ID (counter).
You have to divide the difference by the spinner chosen in order to get evenly spaced millisecond differences.
//Assume timepicker2 > timepicker1
int hours1 = timePicker1.getCurrentHour();
int minutes1 = timePicker1.getCurrentMinute();
int hours2 = timePicker2.getCurrentHour();
int minutes2 = timePicker2.getCurrentMinute();
int hourDiff = hours2-hours1;
int minutesDiff = minutes2-minutes1
int millisecondsDiff = hourDiff*60*60*1000;
millisecondsDiff += minutesDiff*60*1000;
Double period_diff = millisecondsDiff/spinnerValue;
//This is for the intent difference
int counter = 0;
long next = System.currentTimeMillis() + period_diff;
for (int i = 0; i < spinnervalue ); i++) {
Intent myIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, counter++, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Log.e("checkkkk ", "" + "checkkkk");
alarmManager.set(AlarmManager.RTC_WAKEUP, next, pendingIntent);
next += period_diff;
}
Don't take the snippet to work definitively as it's a quick jot down, but it should give you a general idea of where you should be looking.
Another idea would be to use i as the counter so you know in what range the IDs are.
http://developer.android.com/reference/android/app/AlarmManager.html#set%28int,%20long,%20android.app.PendingIntent%29
If the stated trigger time is in the past, the alarm will be triggered
immediately. If there is already an alarm for this Intent scheduled
(with the equality of two intents being defined by
filterEquals(Intent)), then it will be removed and replaced by this
one.
So setting this in a loop isn't what you want.
Your value for millis needs to be a time. 0 would indicate epoch (January 1st, 1970). What you probably want is "SystemClock.elapsedRealtime() + someValue" passed in for that parameter.

Android repeating alarm (AlarmManager.INTERVAL_DAY)

I am trying to implement a daily alarm.
Intent intent = new Intent(mActivity, AlarmReceiver.class);
intent.putExtra("weekdays", weekdays);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mActivity.getApplicationContext(), weekdays ? WEEKDAYS_ID : WEEKENDS_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar current = Calendar.getInstance();
time.set(Calendar.SECOND, 0); // time a type of Calendar object which is set from TimePicker
long timeDifference = time.getTimeInMillis() - current.getTimeInMillis();
long triggerAt = (timeDifference > 0 ? time.getTimeInMillis() : AlarmManager.INTERVAL_DAY + timeDifference);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAt, AlarmManager.INTERVAL_DAY, pendingIntent);
It works fine if I set a time in future.
But if the time difference is negative (current time- 8:00, picked time- 7:45), the repeating alarm is set instantly and the broadcast receiver is fired!
Though I have added AlarmManager.INTERVAL_DAY with the timeDifference to set it after a day, it isn't working.
Also, The AlarmManager.INTERVAL_DAY value is (86400000) which is smaller than the current time in milis (1387869223432), so adding it doesn't make much difference!
What am I missing here?
Ok, this is not working.
long triggerAt = (timeDifference > 0 ? time.getTimeInMillis() : time.getTimeInMillis() + AlarmManager.INTERVAL_DAY + timeDifference);
After debugging, I found that if I set earlier time, then add one day time - difference then the trigger time gets lower than the current time!
Alarm time: 1388073636969 (8am) current time: 1388130756977 (11:50pm)
Difference: -57120008
Alarm to be Triggered: 1388102916961
// its alarm time (8am) + one day interval (1 day) -difference (4hr)
How come trigger time gets smaller than current time??
You should add currentTimeInMillis too
current.getTimeInMillis() + AlarmManager.INTERVAL_DAY + timeDifference
If timeDifference is -15 minutes, the above statement will add-up to,
current time + 24 hours - 15 minutes, which is what you want I presume.
AlarmManager.INTERVAL_DAY : Available inexact recurrence interval recognized by setInexactRepeating(int, long, long, PendingIntent) when running on Android prior to API 19.

Scheduling a task for certain days of the week in Android

As the title implies, I'm looking to schedule a task to run on certain days at certain times. For example, I might have it run at 5:00 every Tuesday and Thursday. I've seen several scheduling methods for Android, but all of them seem to operate in the form of "do task after n delay" or "do task every n seconds".
Now I could probably jury-rig it by having it calculate the time to the next execution during the execution of the task itself, but that seems inelegant. Is there some better way to do this?
You've to set an Alarm to perform those tasks. Most probably you will end up calling a Service once the alarm is triggered:
private void setAlarmToCheckUpdates() {
Calendar calendar = Calendar.getInstance();
if (calendar.get(Calendar.HOUR_OF_DAY)<22){
calendar.set(Calendar.HOUR_OF_DAY, 22);
} else {
calendar.add(Calendar.DAY_OF_YEAR, 1);//tomorrow
calendar.set(Calendar.HOUR_OF_DAY, 22); //22.00
}
Intent myIntent = new Intent(this.getApplicationContext(), ReceiverCheckUpdates.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, myIntent,0);
AlarmManager alarmManager = (AlarmManager)this.getApplicationContext().getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
However, if you need to set specifically a day:
int weekday = calendar.get(Calendar.DAY_OF_WEEK);
if (weekday!=Calendar.THURSDAY){//if we're not in thursday
//we calculate how many days till thursday
//days = The limit of the week (its saturday) minus the actual day of the week, plus how many days till desired day (5: sunday, mon, tue, wed, thur). Modulus of it.
int days = (Calendar.SATURDAY - weekday + 5) % 7;
calendar.add(Calendar.DAY_OF_YEAR, days);
}
//now we just set hour to 22.00 and done.
Above code is a little bit tricky and mathematic. If you wan't something stupid aswell as easy:
//dayOfWeekToSet is a constant from the Calendar class
//c is the calendar instance
public static void SetToNextDayOfWeek(int dayOfWeekToSet, Calendar c){
int currentDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
//add 1 day to the current day until we get to the day we want
while(currentDayOfWeek != dayOfWeekToSet){
c.add(Calendar.DAY_OF_WEEK, 1);
currentDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
}
}

Categories

Resources