1

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?

David S
  • 31
  • 5
  • Try using [SetExactAndAllowWhileIdle](https://developer.android.com/reference/android/app/AlarmManager.html#setExactAndAllowWhileIdle(int,%20long,%20android.app.PendingIntent)) instead of `SetInexactRepeating`, this method isn't repeating, so you have to declare the next job to be run at the service which the pendingIntent opens. – York Shen Jan 05 '18 at 09:15
  • Thank you for this advice, but when I attempt to call this function or SetAndAllowWhileIdle I get an exception Java.Lang.NoSuchMethodError. With the ordinary Set method the program runs, even if I don't get the alarm. I am compiling with Android 7.1. – David S Jan 09 '18 at 02:22
  • You could refer to : https://stackoverflow.com/questions/47311545/schedule-alarm-manager-to-run-a-method-every-thursday/47330902#47330902 – York Shen Jan 09 '18 at 02:24
  • I see in https://github.com/Etar-Group/Etar-Calendar/issues/155 that the method will only work on devices with Android version >= 23. My phone has version 22, so it looks like I cannot use this method. I will try with the standard Set method, manually resetting each day. – David S Jan 09 '18 at 02:40
  • If there is any prolem, please feel free to ask. :) – York Shen Jan 09 '18 at 02:45

0 Answers0