I have written a cross-platform application using Xamarin Forms in Visual Studio 2017 for members of a social group, which provides reminders of coming events and a means to reply to invitations to attend them. Everything works in the Android version except for the reminder system. (I am leaving iOS until later.) I find that I usually get a notification the next morning, but not after that.
The reminder system is divided into several parts.
In OnCreate() in MainActivity.cs I have the following code
// Set the icon for notifications
LocalNotificationsImplementation.NotificationIconId = Resource.Drawable.icon;
// Prepare the periodic alarm.
// The following is based on code in example 'BackgroundTasks' in
// https://github.com/adamped/BackgroundTasks
// BackgroundReceiver sends a message to the main app to trigger
// action on receipt of the alarm by code in IntroductionPage.xaml.cs
var alarmIntent = new Intent(this, typeof(BackgroundReceiver));
var pending = PendingIntent.GetBroadcast(this, 0, alarmIntent,
PendingIntentFlags.UpdateCurrent);
// Set the time for alarms, once every day, in the hour following 5am.
// How many hours till 6am?
int hours_till_6 = 30 - DateTime.Now.Hour;
if (hours_till_6 > 24)
hours_till_6 -= 24;
long time_since_boot = SystemClock.ElapsedRealtime();
long first_alarm = time_since_boot + hours_till_6 * AlarmManager.IntervalHour;
// Set the alarm
var alarmManager = GetSystemService(AlarmService).JavaCast<AlarmManager>();
alarmManager.SetInexactRepeating(AlarmType.ElapsedRealtime,
first_alarm, AlarmManager.IntervalDay, pending);
The reason for setting the time for the alarm in this way is that I want users’ apps to alarm at slightly different times, as each one will make a web request to check for new events. This is by the way.
Then in BackgroundReceiver.cs I have the following code to send the alarm on to code in my top-level project
// Based on example in https://xamarinhelp.com/xamarin-background-tasks/
// See also MainActivity.cs for where this is set up to be called
[BroadcastReceiver]
public class BackgroundReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Call back to main application via messaging service
MessagingCenter.Send<object>(this, "SendNotifications");
}
}
Finally in the constructor of my first page I have
// Prepare to receive a message each day.
// Messages are sent from BackgroundReceiver in Android, controlled
// by AlarmManager in MainActivity.
// *** IOS version not yet implemented.
MessagingCenter.Subscribe<object>(this, "SendNotifications", (s) => {
Device.BeginInvokeOnMainThread(PrepareSendNotifications);
});
And later the function
private void PrepareSendNotifications()
// Prepare and send notifications of occasions which are coming in the next few days.
// Send the notifications using the LocalNotifications plugin.
{
/* This version is just for testing and this posting.
The original looks at coming occasions, and notifies accordingly */
CrossLocalNotifications.Current.Cancel(0);
CrossLocalNotifications.Current.Show("Alarm", "BZEM notification time", 0);
}
I find that I usually get a notification the next morning, but not after that.
Can anyone please advise what I need to change to make this work reliably, or whether a different approach is recommended?
As a further question, can anyone advise how to implement this functionality in iOS, which does not appear to have an equivalent to AlarmManager?