I have an app that sends periodic alarms every day of the week, through the method setRepeating from AlarmManager:
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(INTENT_TAG_ALERT_ID, lastAlertId.getId()+"");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, idRandom, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cDate.getTimeInMillis(), ((AlarmManager.INTERVAL_DAY)*7), pendingIntent);
And then get the alarm on my AlarmReceiver defined on manifest as a Receiver:
<receiver
android:name=".manager.alarm.AlarmReceiver"
android:exported="true">
</receiver>
The problem is when the user changes the Date/Time from his phone for a day or 2 in the future, I receive several calls from the receiver (depending on the number of days chosen). Since I use a setRepeating method I can't validate if the alarm was sent at the right time.
I know this is normal procedure as described on here: "A trigger time. If the trigger time you specify is in the past, the alarm triggers immediately.", but I want to prevent it.
I thought of putting a listener to know when the user changes the date and time of his phone, to unschedule all the alarms and then schedule them again, as you can see bellow:
public class DateTimeChangedBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_TIMEZONE_CHANGED) || action.equals(Intent.ACTION_TIME_CHANGED) || action.equals(Intent.ACTION_DATE_CHANGED)) {
AlarmScheduler.unscheduleAllAlarms();
//and then
AlarmScheduler.scheduleAllAlarms();
}
}
}
And the manifest:
<receiver android:name=".manager.alarm.DateTimeChangedBroadcastReceiver"
android:priority="1000">
<intent-filter>
<action android:name="android.intent.ACTION_TIMEZONE_CHANGED"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.ACTION_TIME"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DATE_CHANGED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.TIME_SET"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.ACTION_TIME_CHANGED"/>
</intent-filter>
</receiver>
But in this solution, the receiver of time changes come after the receiver from the alarm, so it doesn't serve me much...
Is there a way to choose the order of my receivers?
Is there a better way to do this?
I also though of putting a listener to clock time, to store it. if the user changes the hour I should only validate the difference... but I believe I can get a better way to do this (preferentially not involving another listener on the app)
You don't need multiple receivers to handle this. Do the following in:
AlarmReceiver.java
@Override
public void onReceive(Context context, Intent intent) {
//Handle the logics here.
//This function is called every time alarm repeats.
//So simply find out if you need an alarm right now and pop alarm.
}
XML
<receiver android:name=".manager.alarm.AlarmReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.ACTION_TIMEZONE_CHANGED"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.ACTION_TIME"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DATE_CHANGED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.TIME_SET"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.ACTION_TIME_CHANGED"/>
</intent-filter>
</receiver>
The alarm receiver is called as per your interval or on date change etc... You can then detect what caused the alarm receiver to be triggered and just act on it. Using multiple receiver is just overkill for this purpose.
Hope this helps.
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