Search code examples
flutterdartandroid-alarms

Flutter repeat alarm on user selected week days


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

Solution

  • 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),
    );