Flutter repeat alarm on user selected week days

390

Add the startAt parameter. In this code it'll start at 8am of the current day. You can change to to whenever you need it to start

AndroidAlarmManager.periodic(
   const Duration(minutes: 30), 0,
   printHello,
   startAt: DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 8, 0),
);
Share:
390
Admin
Author by

Admin

Updated on December 30, 2022

Comments

  • Admin
    Admin over 1 year

    If my user sets some data like:

    day : "Sunday"
    startTime: 8:00 A.M
    endTime: 8:00 P.M
    frequency: 30 minutes
    

    I want to fire an alarm after each 30 minutes starting from 8:00 A.M so, 8:00 A.M, 8:30 A.M, 9:00 A.M, 9:30 A.M ....

    Now I'm using android_alarm_manager_plus for my application and this is what I have done till now:

    AndroidAlarmManager.periodic(
       const Duration(minutes: 0, seconds: 1),
       0, 
       printHello, // callback function, for now I'm just printing "hello world"
    );
    

    How can I set an alarm on the user selected day, time and frequency?

    Update 1:

    AndroidAlarmManager.periodic(
       const Duration(minutes: _frequency!), //Evaluation of this constant expression throws an exception.
       0,
       printHello,
       startAt: DateTime(
         DateTime.now().year,
         DateTime.now().month,
         DateTime.now().day,
         _startTime, //The argument type 'TimeOfDay?' can't be assigned to the parameter type 'int'
         0,
       ),
    );
    

    How I'm storing data:

    int? frequency;
    TimeOfDay? startTime;
    

    My TimeOfDay selector:

      void selectStartTime() async {
        final TimeOfDay? newTime = await showTimePicker(
          context: context,
          initialTime: _startTime!,
          initialEntryMode: TimePickerEntryMode.input,
        );
        if (newTime != null) {
          setState(() {
            _startTime = newTime;
          });
        }
      }
    

    Update 2: Okay, so I checked the source code for android alarm manager plus and I think they don't support what I'm trying to do out of the box.

    This is the code for their periodic timer:

      static Future<bool> periodic(
        Duration duration,
        int id,
        Function callback, {
        DateTime? startAt,
        bool exact = false,
        bool wakeup = false,
        bool rescheduleOnReboot = false,
      }) async {
        // ignore: inference_failure_on_function_return_type
        assert(callback is Function() || callback is Function(int));
        assert(id.bitLength < 32);
        final now = _now().millisecondsSinceEpoch;
        final period = duration.inMilliseconds;
        final first =
            startAt != null ? startAt.millisecondsSinceEpoch : now + period;
        final handle = _getCallbackHandle(callback);
        if (handle == null) {
          return false;
        }
        final r = await _channel.invokeMethod<bool>('Alarm.periodic', <dynamic>[
          id,
          exact,
          wakeup,
          first,
          period,
          rescheduleOnReboot,
          handle.toRawHandle()
        ]);
        return (r == null) ? false : r;
      }
    

    Is it possible to create another custom function to do what I want? The custom function would look something like this:

      static Future<bool> customPeriodic(
        int id, // id
        Duration repeatAfter, // repeats after each m time(ex: 7 days)
        int frequency, // fire alarm after each n minutes(ex: 30 mins)
        Function callBack, {
        DateTime? startAt, // serve as start tune
        DateTime? endAt, // serve as end time
        bool exact = false,
        bool wakeup = false,
        bool rescheduleOnReboot = false,
      }) async {
        return true;
      }
    
  • Admin
    Admin almost 3 years
    hey thanks for the suggestion but it doesn't work. I've updated my post with the updated code. Can you please check it?
  • zinbrox
    zinbrox almost 3 years
    Your code seems correct, have you tried picking a time in the future as the first call won't run if the startAt time is already passed.
  • Admin
    Admin almost 3 years
    Hey, I just had to remove the const and the first problem is gone. But there's still the issue of dynamically setting the day and startTime which should be int. But I'm storing the data in TimeOfDay
  • zinbrox
    zinbrox almost 3 years
    Hey sorry for the late reply, if you're using TimeOfDay you can access the hour by newTime.hour. If you need to select day to start, you can map the day to a DateTime object, but it's probably easier to use this package