locked
Setting AlarmManager to repeat given a specific time RRS feed

  • Question

  • User24557 posted

    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;
    }
    

    As usual, I've asked this on StackOverflow so answer where ever you feel like.

    Monday, April 28, 2014 1:37 AM

All replies

  • User24557 posted

    Still looking for help on this issue.

    Tuesday, April 29, 2014 6:17 PM
  • User24557 posted

    I've yet to implement this fully but I'm thinking of just going with a Timer instead of AlarmManager.

    I'll use this to get 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 use a 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);
    
    Friday, May 2, 2014 6:48 PM
  • User57571 posted

    Does this works even when the application goes background/dead or the device is restarted?

    Wednesday, July 23, 2014 6:12 PM
  • User1393 posted

    Unless he has his service restart on boot then it will not start the timer again. Also, if you're service gets killed the timer will be reset when the OS starts the service again. Here is the method I've used to set an alarm in the future

    public static long GetMilisecondsUntilNextCheck(DateTime next)
    {
            DateTime now = DateTime.Now;
            DateTime todayAtTime = now.Date.AddHours(next.Hour).AddMinutes(next.Minute);
            DateTime nextInstance = now <= todayAtTime ? todayAtTime : todayAtTime.AddDays(1);
            TimeSpan span = nextInstance - now;
            using (var cal = Java.Util.Calendar.GetInstance(Java.Util.TimeZone.Default))
            {
                cal.Set (Java.Util.CalendarField.Millisecond, 0);
                cal.Add(Java.Util.CalendarField.Millisecond, (int)span.TotalMilliseconds);
                return cal.TimeInMillis;
            }
      }
    

    Then use the miliseconds you get from the method above to do this

    Intent intent = new Intent(Context.ApplicationContext, typeof(T));
    PendingIntent pintent = PendingIntent.GetService(Context.ApplicationContext, 0, intent, 0);
    AlarmManager alarm = (AlarmManager) Context.ApplicationContext.GetSystemService(Context.AlarmService);
    alarm.SetRepeating(AlarmType.RtcWakeup, (long)millisToAlarm, AlarmManager.IntervalDay, pintent);
    
    Thursday, July 24, 2014 1:36 PM
  • User17213 posted

    Do you have more code on the above use of AlarmManager such as what T looks like. Also registering the alarm and any Manifest code. I'm struggling with trying to get a background alarm to go off but the abundance of Eclipse code is difficult to translate to Xamarin.

    Any help would be appreciated

    Friday, August 22, 2014 2:32 PM
  • User94657 posted

    class ViewBinder : Java.Lang.Object,SimpleCursorAdapter.IViewBinder

        {
    
            public bool SetViewValue (View view, Android.Database.ICursor cursor, int columnIndex)
            {
                if (columnIndex == 2) {
                    long ms = cursor.GetLong (columnIndex);
    
                    DateTime date = 
                        new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds (ms).ToLocalTime ();
    
                    TextView textView = (TextView)view;
                    textView.Text = date.ToLongDateString ();
    
                    return true;
                }
                return false;
            }     
        }
    
    
    
        public  long GetDateTimeMS (int yer, int month, int day, int hor, int min)
    
        {
    
    
            Calendar cal = new Calendar.GetIntance (Java.Util.Locale.Default);
    

    i got error in .GetIntance what can i do how can i remove it

            cal.Set (Calendar.DayOfMonth, 15);
            cal.Set (Calendar.HourOfDay, hor);
            cal.Set (Calendar.Minute, min);
            cal.Set (Calendar.Month, Calendar.December);
            cal.Set (Calendar.Year, 2011);
    
            return cal.TimeInMillis;
    
    
    
    
    
       i got error in .GetIntance what can i do how can i remove it 
    
    Monday, January 5, 2015 12:43 PM
  • User116546 posted

    @JeremyKieley did you get the solution?

    Tuesday, April 28, 2015 12:20 PM
  • User221813 posted

    You're using AlarmType.ElapsedRealtimeWakeup instead of AlarmType.RtcWakeup. * ELAPSEDREALTIME—Fires the pending intent based on the amount of time since the device was booted, but doesn’t wake up the device. The elapsed time includes any time during which the device was asleep. * ELAPSEDREALTIMEWAKEUP—Wakes up the device and fires the pending intent after the specified length of time has elapsed since device boot. * RTC—Fires the pending intent at the specified time but does not wake up the device. * RTCWAKEUP—Wakes up the device to fire the pending intent at the specified time. Source: https://developer.android.com/training/scheduling/alarms.html#set

    Saturday, June 3, 2017 11:32 AM
  • User340021 posted

    This worked for me:

    Calendar dayCalendar = Calendar.GetInstance(Java.Util.TimeZone.Default);
                dayCalendar.Set(CalendarField.HourOfDay, 8); 
                dayCalendar.Set(CalendarField.Minute, 39);
                dayCalendar.Set(CalendarField.Second, 0);
    
                manager.SetRepeating(AlarmType.RtcWakeup, dayCalendar.TimeInMillis, AlarmManager.IntervalDay, pendingIntent);
    

    I used the Java.Util.Calendar for my dayCalendar variable.

    Wednesday, October 4, 2017 4:40 AM