Hi and thank you for your help.
I have an application that uses AlarmManager to set one alarm a day for the next weeks, months...
and
I have the following problem that I will try to explain in the following lines:
Today is Wednesday,
I open the application and set my alarms for MON, TUE, WED, THU, FRI, SAT, SUN... as soon as I set the alarms:
ALL the alarms for MON and TUE go immediately off I end up with 4 instances of the Activity !!!!
Please how do I avoid this???
Please see a piece of my code:
// SET THE ALARM FOR STARTING THE ACTIVITY
Intent smon = new Intent(ctxt, VideoActivty.class);
smon.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent psmon = PendingIntent.getActivity(ctxt, 0, smon, 0);
Calendar calSet = Calendar.getInstance();
calSet.set(Calendar.DAY_OF_WEEK, 2);
calSet.set(Calendar.HOUR_OF_DAY, hsmon);
calSet.set(Calendar.MINUTE, msmon);
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
mgr.setRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
7 * 24 * 60 * 60 * 1000, psmon);
// SET THE ALARM FOR KILLING THE ACTIVITY
Intent fmon = new Intent(ctxt, VideoActivty.class);
fmon.putExtra("finish", true);
PendingIntent pfmon = PendingIntent.getActivity(ctxt, 0, fmon, 0);
calSet.set(Calendar.DAY_OF_WEEK, 2);
calSet.set(Calendar.HOUR_OF_DAY, hfmon);
calSet.set(Calendar.MINUTE, mfmon);
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
mgr.setRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
7 * 24 * 60 * 60 * 1000, pfmon);
This is the Activity:
public class VideoActivty extends Activity {
private VideoView video;
private MediaController ctlr;
private PowerManager.WakeLock wl;
private KeyguardLock keyguard;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//
PowerManager pm = (PowerManager) this
.getSystemService(this.POWER_SERVICE);
wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
keyguard = km.newKeyguardLock("MyApp");
keyguard.disableKeyguard();
getWindow().setFormat(PixelFormat.TRANSLUCENT);
VideoView videoHolder = new VideoView(this);
//if you want the controls to appear
videoHolder.setMediaController(new MediaController(this));
Uri video = Uri.parse("android.resource://" + getPackageName() + "/"
+ R.raw.ingress); //do not add any extension
//if your file is named sherif.mp4 and placed in /raw
//use R.raw.sherif
videoHolder.setVideoURI(video);
setContentView(videoHolder);
videoHolder.start();
videoHolder.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.start();
}
});
}
@Override
protected void onNewIntent (Intent i){
if( i.getBooleanExtra("finish",false) ){
wl.release();
keyguard.reenableKeyguard();
finish();
}
}
}
As the API page of AlarmManager states regarding the set(...) and setRepeating(...) methods:
"If the stated trigger time is in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval."
So, if for example you are on Wednesday, then the AlarmManager will fire the events of: Sunday, Monday, Tuesday and (possibly) Wednesday. It will actually fire only one for all of them.
Here is how I avoid this. Not sure it is the best way, but it works smoothly.
Let's say that you store the day of the week, the hour and the minute of the day in which you want to fire your AlarmManager in the following variables:
final int myAlarmDayOfTheWeek = ...;
final int myAlarmHour = ...;
final int myAlarmMinute = ...;
Of course, here I'm assuming you store the day of the week with the same convention of the Calendar class, i.e.:
Sunday = Calendar.SUNDAY = 1
Monday = Calendar.MONDAY = 2
... ... ...
Saturday = Calendar.SATURDAY = 7
Then:
Calendar timestamp = Calendar.getInstance();
//Check whether the day of the week was earlier in the week:
if( myAlarmDayOfTheWeek > timestamp.get(Calendar.DAY_OF_WEEK) ) {
//Set the day of the AlarmManager:
time.add(Calendar.DAY_OF_YEAR, (myAlarmDayOfTheWeek - timestamp.get(Calendar.DAY_OF_WEEK)));
}
else {
if( myAlarmDayOfTheWeek < timestamp.get(Calendar.DAY_OF_WEEK) ) {
//Set the day of the AlarmManager:
timestamp.add(Calendar.DAY_OF_YEAR, (7 - (timestamp.get(Calendar.DAY_OF_WEEK) - myAlarmDayOfTheWeek)));
}
else { // myAlarmDayOfTheWeek == time.get(Calendar.DAY_OF_WEEK)
//Check whether the time has already gone:
if ( (myAlarmHour < timestamp.get(Calendar.HOUR_OF_DAY)) || ((myAlarmHour == timestamp.get(Calendar.HOUR_OF_DAY)) && (myAlarmMinute < timestamp.get(Calendar.MINUTE))) ) {
//Set the day of the AlarmManager:
timestamp.add(Calendar.DAY_OF_YEAR, 7);
}
}
}
//Set the time of the AlarmManager:
timestamp.set(Calendar.HOUR_OF_DAY, myAlarmHour);
timestamp.set(Calendar.MINUTE, myAlarmMinute);
timestamp.set(Calendar.SECOND, 0);
Note that by using Calendar.DAY_OF_YEAR in the Calendar.add(...), you don't even need to take care of the change of the month...
If you are in the first condition (i.e. myAlarmDayOfTheWeek > timestamp.get(Calendar.DAY_OF_WEEK)), you can also just use Calendar.set(...) with Calendar.DAY_OF_WEEK as field and myAlarmDayOfTheWeek as value.
Now, you just need to setup your AlarmManager. For example:
final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, timestamp.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, myAlarmPendingIntent);
Please, also avoid calculating the day interval (i.e. 24 * 60 * 60 * 1000) every time, but use AlarmManager.INTERVAL_DAY (or at most 86400000) instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With