0

I'm trying to get a timer (down to the hundredths of seconds) to work in Flutter even when the app is closed. I initially tried to use isolates as I thought they would work yet after testing with a Pixel 4 running Android 11 I found that it was still not firing correctly when the app was closed. After some googleing I came across Android Alarm Manager and I have everything set up again yet it doesn't appear that the periodic function is firing correctly. Heres the BLoC map for triggering the counter:

Stream<TimerState> _mapTimerStartedToState(TimerStarted start) async* {
     AndroidAlarmManager.initialize();
     port.listen((_) async => await _incrementCounter());
     startCounter();
     print(_counter);
     yield TimerRunInProgress(start.duration);
  }

Here's the startCounter() function:

void startCounter() async {
     prefs = await SharedPreferences.getInstance();
     if (!prefs.containsKey(countKey)) {
       await prefs.setInt(countKey, 0);
     }
     IsolateNameServer.registerPortWithName(
      port.sendPort,
      isolateName,
     );
     await AndroidAlarmManager.periodic(
       Duration(milliseconds: 100),
       // Ensure we have a unique alarm ID.
       Random().nextInt(pow(2, 31)),
       callback,
       exact: true,
       wakeup: true,
     );


 }

And then here's my callback:

static Future<void> callback() async {
     print('Alarm fired!');
     // Get the previous cached count and increment it.
     final prefs = await 
     SharedPreferences.getInstance();
     int currentCount = prefs.getInt(countKey);
     await prefs.setInt(countKey, currentCount + 1);
     // This will be null if we're running in the background.
     print(currentCount);
     uiSendPort ??= IsolateNameServer.lookupPortByName(isolateName);
uiSendPort?.send(null);
  }

Am I on the right path here? Can AndroidAlarmManager do what I'm trying to do? I'm not exactly sure why the isolate approach didn't work on its own either, the only explanation I got was that I needed to use AndroidAlarmManager. Now, the events aren't firing at the 100 ms rate as I told them to and are instead firing 1 to several minutes apart.

Samuel Drescher
  • 457
  • 1
  • 3
  • 13
  • you don't need to count any timers when your app is in background - you can get the current time when your app switches to foreground and update your timers – pskink Nov 15 '20 at 20:27
  • Do you have any references i could look at for this? I'm fairly new – Samuel Drescher Nov 15 '20 at 21:13

1 Answers1

0

Android restricts the frequencies for alarms. You cannot schedule alarms as frequently as 100 milliseconds with AlarmManager.

Please refer the note in red background on : https://developer.android.com/reference/android/app/AlarmManager

Note: Beginning with API 19 (Build.VERSION_CODES.KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, android.app.PendingIntent) and setExact(int, long, android.app.PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.

bluenile
  • 5,673
  • 3
  • 16
  • 29