Question

I'm not able to get the AlarmManager to work correctly with a Calendar or GregorianCalendar object.

Global.StartingTime is a static DateTime object in another class. It's hour property returns the time in 24-Hour clock format.

Attempt 1 - Using Calendar - Result: Doesn't fire

public void SetAlarm()
{
        if (Global.StartingTime == null || Global.StartingTime == DateTime.MinValue) return;

        Calendar now = Calendar.GetInstance (Java.Util.TimeZone.Default);
        Calendar alarmTime = Calendar.GetInstance (Java.Util.TimeZone.Default);

        alarmTime.Set(CalendarField.HourOfDay, Global.StartingTime.Hour);
        alarmTime.Set(CalendarField.HourOfDay, Global.StartingTime.Minute);
        if (alarmTime.Before(now))
            alarmTime.Add(CalendarField.DayOfMonth, 1);

        AlarmManager am = (AlarmManager) _context.GetSystemService (Context.AlarmService);
        Intent intent = new Intent(_context, typeof(MainReceiver));
        intent.PutExtra (ALARM_ACTION, true);
        PendingIntent pi = PendingIntent.GetBroadcast (_context, 0, intent, 0);
        am.SetRepeating (AlarmType.ElapsedRealtimeWakeup, alarmTime.TimeInMillis, AlarmManager.IntervalDay, pi);
        AlarmSet = true;
}

Attempt 2 - Using GregorianCalendar - Result: Fires right away, not at the given hour and minute.

public void SetAlarm()
{
        if (Global.StartingTime == null || Global.StartingTime == DateTime.MinValue) return;

        GregorianCalendar now = new GregorianCalendar ();
        now.TimeInMillis = SystemClock.ElapsedRealtime();

        GregorianCalendar alarmTime = new GregorianCalendar ();
        alarmTime.Add(CalendarField.DayOfYear, now.Get(CalendarField.DayOfYear));
        alarmTime.Set(CalendarField.HourOfDay, Global.StartingTime.Hour);
        alarmTime.Set(CalendarField.Minute, Global.StartingTime.Minute);
        alarmTime.Set(CalendarField.Second, now.Get(CalendarField.Second));
        alarmTime.Set(CalendarField.Millisecond, now.Get(CalendarField.Millisecond));
        alarmTime.Set(CalendarField.Date, now.Get(CalendarField.Date));
        alarmTime.Set(CalendarField.Month, now.Get(CalendarField.Month));

        if (alarmTime.Before (now))
            alarmTime.Add (CalendarField.DayOfYear, 1);

        AlarmManager am = (AlarmManager) _context.GetSystemService (Context.AlarmService);
        Intent intent = new Intent(_context, typeof(MainReceiver));
        intent.PutExtra (ALARM_ACTION, true);
        PendingIntent pi = PendingIntent.GetBroadcast (_context, 0, intent, 0);
        am.SetRepeating (AlarmType.RtcWakeup, alarmTime.TimeInMillis, AlarmManager.IntervalDay, pi);
        AlarmSet = true;
}
Was it helpful?

Solution

I've decided to just go with a Timer instead of AlarmManager which seems to work well in my specific case (the app is constantly running a service and I don't need to use AlarmManager to wake it up).

This gets the time until alarm

public int GetTimeInterval(DateTime dt)
{
    DateTime now = DateTime.Now;
    if (dt <= now) {
        dt = dt.AddDays(1);
    }

    return (dt - now).TotalMilliseconds;
}

Then I'm using a System.Threading.Timer that sends out a broadcast

var IntervalOfOneDay = 86400000; // 24 hours in milliseconds
var interval = GetTimeInterval(alarmTime);
timer = New System.Threading.Timer(func, null, interval, IntervalOfOneDay);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top