Andrious / code_samples

A repository of sample code and class utility examples.
0 stars 0 forks source link

[Alarm Manager] Callback doesn't get excuted properly! #1

Open flashawy opened 4 years ago

flashawy commented 4 years ago

Hi, I have a class that has the business logic of a timer screen .. it is simple stuff at the end of the constructor of this class I call testAlarmManager.

  void testAlarmManager() async {
    await AlarmManager.init(
      exact: true,
      alarmClock: true,
      wakeup: true,
    );

    await AlarmManager.oneShot(
        const Duration(seconds: 15), Random().nextInt(pow(2, 31)), (int id) => printHello());
  }

outside this class - but in the same dart file - I have this function

void printHello() { print('*** Hello from alarm manager callback ***'); }

after 15 seconds .. I get this printed to the console

I/flutter ( 4652): {}

not the message that should be printed

If I replace AlarmManager.oneShot with AndroidAlarmManager.oneShot things work fine even if I keep AlarmManager.init to do the initialization

 void testAlarmManager() async {
    await AlarmManager.init(
      exact: true,
      alarmClock: true,
      wakeup: true,
    );

    await AndroidAlarmManager.oneShot(
        const Duration(seconds: 180), Random().nextInt(pow(2, 31)), printHello);
  }
Andrious commented 4 years ago

Ah! Ok, let me take a look into this. One moment.

Andrious commented 4 years ago

I was wondering where that empty brackets, '{}', was coming from. I found it to be an extraneous command in the utility class and was removed. As for the line, Hello from alarm manager callback , not being printed---I'm not getting that problem. It's coming up every time. The lastest, alarm_manage.dart, is in the repo.

Below is the very test code I was using. I've incorporated your code in there and appears to be working. Please, download the latest version in the repo. as well as this and see how you fare.

import 'dart:math' show Random, pow;
import 'package:flutter/material.dart';

import 'alarm_manager.dart' show AlarmManager;
import 'package:shared_preferences/shared_preferences.dart'
    show SharedPreferences;

/// The [SharedPreferences] key to access the alarm fire count.
const String _countKey = 'count';

/// Global [SharedPreferences] object.
SharedPreferences _prefs;

void main() => runApp(AlarmManagerExampleApp());

class AlarmManagerExampleApp extends StatelessWidget {
  AlarmManagerExampleApp() {
    testAlarmManager();
  }

  void testAlarmManager() async {
    await AlarmManager.init(
      exact: true,
      alarmClock: true,
      wakeup: true,
    );

    await AlarmManager.oneShot(const Duration(seconds: 15),
        Random().nextInt(pow(2, 31)), (int id) => printHello());
  }

  void printHello() {
    print('*** Hello from alarm manager callback ***');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        debugShowCheckedModeBanner: false,
        home: FutureBuilder<bool>(
            future: initSettings(),
            initialData: false,
            builder: (_, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                return _AlarmHomePage(
                    title: 'Notification & Alarms in Flutter');
              } else {
                return Container(
                    child: Center(child: CircularProgressIndicator()));
              }
            }));
  }

  Future<bool> initSettings() async {
    bool init = await AlarmManager.init(
      exact: true,
      alarmClock: true,
      wakeup: true,
    );
    _prefs = await SharedPreferences.getInstance();
    if (!_prefs.containsKey(_countKey)) _prefs.setInt(_countKey, 0);
    //   return init;
    return true;
  }
}

class _AlarmHomePage extends StatefulWidget {
  _AlarmHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _AlarmHomePageState createState() => _AlarmHomePageState();
}

class _AlarmHomePageState extends State<_AlarmHomePage> {
  @override
  Widget build(BuildContext context) {
    final textStyle = Theme.of(context).textTheme.headline4;
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Alarm fired $_counter times',
              style: textStyle,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Total alarms fired: ',
                  style: textStyle,
                ),
                Text(
                  _prefs.getInt(_countKey).toString(),
                  key: ValueKey('BackgroundCountText'),
                  style: textStyle,
                ),
              ],
            ),
            RaisedButton(
              child: Text(
                'Schedule OneShot Alarm',
              ),
              key: ValueKey('RegisterOneShotAlarm'),
              onPressed: () async {
                await AlarmManager.init(
                  exact: true,
                  alarmClock: true,
                  wakeup: true,
                );
                await AlarmManager.oneShot(
                  const Duration(seconds: 5),
                  // Ensure we have a unique alarm ID.
                  Random().nextInt(pow(2, 31)),
                  (int id) => _incrementCounter(),
                );

                if (AlarmManager.hasError) print(AlarmManager.getError());
              },
            ),
          ],
        ),
      ),
    );
  }

  int _counter = 0;
  Future<void> _incrementCounter() async {
    int currentCount = _prefs.getInt(_countKey);
    await _prefs.setInt(_countKey, currentCount + 1);
    // Ensure we've loaded the updated count from the background isolate.
    await _prefs.reload();
    setState(() {
      _counter++;
    });
    print('Increment counter!');
  }
}
flashawy commented 4 years ago

Unfortunatly I am getting all sorts of weird behavior.. but it is more likely related to my configuration

I tried the code you provided.. it didn't fire the callback.. the '{}' are gone but nothing else gets printed. but now when I replace AlarmManager.oneShot with AndroidAlarmManager.oneShot it doesn't work (unlike in my code which does work)

The thing is It is hard to figure out the reason because no build or runtime errors are shown .

BTW..

The sample app you provide doesn't work.. but when I click the "Schedule OneShot Alarm" button.. I get this error in the console

Exception: PlatformException(error, Attempt to invoke interface method 'void io.flutter.plugin.common.BinaryMessenger.setMessageHandler(java.lang.String, io.flutter.plugin.common.BinaryMessenger$BinaryMessageHandler)' on a null object reference, null)

maybe my configuration doesn't let the plugin to initialize properly. but I don't know what or how to fix it.

flashawy commented 4 years ago

and by weird behavior I mean that some times if I switch the app between the background and foreground the message gets printed.. but fare late than the specified time duration.

Andrious commented 4 years ago

Oh my. Truly, I do not have the troubles you're having. I've not seen that error message before. Have you 'Googled' that particular error?
Curious what that comes from.

Exception: PlatformException(error, Attempt to invoke interface method 'void io.flutter.plugin.common.BinaryMessenger.setMessageHandler(java.lang.String, io.flutter.plugin.common.BinaryMessenger$BinaryMessageHandler)' on a null object reference, null)