I am developing an Android app using Xamarin. I am trying to figure out how to have it send notifications using AlarmManager with a variable interval. I have figured out how to trigger a notification and have it sent on a fixed interval (say every five minutes). But in some cases I would like to have the interval more dynamic. For instance, let's say I would like to get notified every day a sunset. Since the interval between sunsets are varying, how do I schedule a notification that has an interval that will change?
Here is my code that works for a fix interval:
public void SendNotification( int id
, string title
, string message
, DateTime notifyTime
, long interval)
{
if ( ! _channelInitialized)
{
CreateNotificationChannel();
}
var intent = new Intent(AndroidApp.Context
, typeof(AlarmHandler));
intent.PutExtra(TitleKey
, title);
intent.PutExtra(MessageKey
, message);
var pendingIntent = PendingIntent.GetBroadcast(AndroidApp.Context
, id
, intent
, PendingIntentFlags.UpdateCurrent);
var triggerTime = GetNotifyTime(notifyTime);
var alarmManager = AndroidApp.Context
.GetSystemService(Context.AlarmService) as AlarmManager;
alarmManager?.SetRepeating(AlarmType.RtcWakeup
, triggerTime
, interval
, pendingIntent);
}
CodePudding user response:
It all depends on how exact your alarm should go off and if you know the intervals beforehand or if they are dynamically gotten.
So, if you know the intervals beforehand you can just set multiple alarms (by using different ids on the PendingIntent
, docs) to go off on exactly the specified intervals using
- setExact(Android.App.AlarmType type, long triggerAtMillis, Android.App.PendingIntent? operation)
- setExactAndAllowWhileIdle(Android.App.AlarmType type, long triggerAtMillis, Android.App.PendingIntent? operation)
- setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation)
e.g. idk your specific scenario but here you have a generic example with two alarms:
var baseline = Java.Lang.JavaSystem.CurrentTimeMillis(); // Time from 1970
var time1 = baseline TimeSpan.FromSeconds(5332).TotalMilliseconds;
var time2 = baseline TimeSpan.FromSeconds(8900).TotalMilliseconds;
var id1 = DateTime.Now().TotalMilliseconds
var pendingIntentWithId1 = PendingIntent.GetBroadcast(AndroidApp.Context
, id1
, intent
, PendingIntentFlags.UpdateCurrent);
var pendingIntentWithId2 = PendingIntent.GetBroadcast(AndroidApp.Context
, id1 1
, intent
, PendingIntentFlags.UpdateCurrent);
var alarmManager = AndroidApp.Context
.GetSystemService(Context.AlarmService) as AlarmManager;
alarmManager?.SetExact(AlarmType.RtcWakeup,
time1,
pendingIntentWithId1);
alarmManager?.SetExact(AlarmType.RtcWakeup,
time2,
pendingIntentWithId2);
If the intervals/time to go off need to be dynamically updated you need to create a Service
that runs on the background and updates the alarms on the AlarmManager
, or every time you receive on the BroadcastReceiver
you set the next alarm time to go off.
Be careful on setting exact alarms because they are resource consuming and if possible you should set inexact alarms.
Also if you're setting exact alarms remember to have the proper permission set if you are targeting Android 12 :
- SCHEDULE_EXACT_ALARM (this is target Android 12 )
- USE_EXACT_ALARM (this is target Android 13 )
Most of the times SCHEDULE_EXACT_ALARM
is enough, the later one can be used in the next cases:
Your app is an alarm clock app or a timer app. Your app is a calendar app that shows notifications for upcoming events