I have a service, which should start every hour. I am testing with a Note 3.
As this is Android KitKat I changed the code to:
AlarmManager am = (AlarmManager) this.getSystemService(ALARM_SERVICE);
int valueOfHour = 3600000;
long time = System.currentTimeMillis()+ (valueOfHour - (System.currentTimeMillis() % valueOfHour))+ 300000;
Log.i("Calculated Time:", time + " " + System.currentTimeMillis());
if(android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.KITKAT){
am.cancel(pintent);
am.setExact(AlarmManager.RTC_WAKEUP, time, pintent);
}
My problem is, that the Service is started at XX:05 (like I want it to) and also now and then at XX:34. I just don't know why. The calculated time is always right.
The code above is located in the onBind() Method.
Related
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...
I have a working alarm using the alarmManager class. If I set the alarm for any time before midnight of the current day everything is fine. If I want to set the alarm for the 7 a.m., however, and 7 a.m. has already come and gone for today, that of course does not work.
Is there a way to do this without implementing datepicker and dates into the program?
Below is a code sample. I can post more complete code if needed.
Intent myIntent = new Intent(AlarmActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(AlarmActivity.this, 0, myIntent, 0);
repeatInterval = LoadPreferences("repeatInterval", repeatInterval); //gets number of minutes reminder should repeat
repeatIntervalMilliseconds = repeatInterval * 1000 * 60; //converts repeating interval to milliseconds for setRepeating method
//Set a one time alarm
if (repeatInterval == 0) {
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
AlarmReceiver alarmReceiver = new AlarmReceiver(this); //http://stackoverflow.com/questions/16678763/the-method-getapplicationcontext-is-undefined
Toast.makeText(AlarmActivity.this, "Your one time reminder is now set for " + hourSet + ":" + minuteSetString + amPmlabel, Toast
.LENGTH_LONG)
.show();
}
//Set a repeating alarm
else {
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), repeatIntervalMilliseconds, pendingIntent);
AlarmReceiver alarmReceiver = new AlarmReceiver(this); //http://stackoverflow.com/questions/16678763/the-method-getapplicationcontext-is-undefined
Toast.makeText(AlarmActivity.this, "Your reminder is now set for " + hourSet + ":" + minuteSetString + amPmlabel + " and will " +
"repeat " +
"every " +
repeatInterval + " minutes.", Toast.LENGTH_LONG).show();
}
I am testing this solution as recommended by Mike M. I will know tomorrow morning if this works. Mike if you want to post the same solution separately, and this is successful (and I think it will be), I can award you points.
//Add 1 day to alarmTime if alarmTime has already gone by for today
calendarComparison = now.compareTo(alarmTime);
if (calendarComparison == 1){
alarmTime.add(Calendar.DATE, 1);
}
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.
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.
In Android we set an alarm by setting the time until it goes off in milliseconds. Is there an easy way to find how many milliseconds there are until a certain time (hh:mm) or do I just have to calculate it mathematically?
Thanks!
Save your current time in milliseconds as
Calandar calendar = Calendar.getInstance();
Long currenttime = calendar.getTimeInMillis();
Long settime= <your set time in milliseconds>;
Here you can calculate the difference as follows:
Long differencetime = settime - currenttime;
int dif=(int)differencetime/1000;
Here you can set the time in calendar:
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + dif);
Here you can set the alarm for the settime.
AlarmManager alarmManager1 = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager1.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pi1);
Check out the first argument for AlarmManager.set(): With RTC/RTC_WAKEUP, you can specify a fixed time rather than an elapsed time.
That said, if you need to use the elapsed time, it's pretty trivial to calculate the number of milliseconds that need to elapse. Worst case, you could use the Calendar and/or Date classes.
Date now = new Date(), b = new Date(year, month, day, hour, min);
b.getTime() - a.getTime();
And here's another way to get the time in milliseconds to a certain time:
Calendar c = Calendar.getInstance();
c.set(c.YEAR, c.MONTH, c.DAY_OF_MONTH, 17, 1, 0); // 5:01 pm
long alarmTime = c.getTimeInMillis();
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmNotification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime, 1000 * 60 * 60 * 24, pendingIntent); // Millisec * Second * Minute * Hour // Same time every day
RTC_WAKEUP allows the alarm to still activate when the phone is asleep. Use RTC if you want to wait until the user wakes up the phone themself.
Use am.set() if you don't want the alarm to repeat
Let me know if this helps.