Обратный вызов Android Alarm Manager не работает - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь использовать плагин Android Alarm Manager для таймера и выполнения кода в фоновом режиме, но не могу заставить его работать правильно.Если я устанавливаю что-то вроде "print (" v ")" в качестве обратного вызова - все работает нормально, но когда я пытаюсь сделать что-то дополнительное, это просто не работает.

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'dart:isolate';

class MyApp extends StatefulWidget {
  _MyAppState createState() => _MyAppState();
}



startTimer(sendport) async {
  await AndroidAlarmManager.oneShot(
      Duration(seconds: 60), 0, timerCallback(sendport),
      wakeup: true, exact: true);
}

timerCallback(sendport) {
  sendport.send("DONE");
}

class _MyAppState extends State<MyApp> {
  ReceivePort receivePort = ReceivePort();
  SendPort sendport;

  @override
  void initState() {
    super.initState();
    AndroidAlarmManager.initialize();
    receivePort.listen((v) {
      print(v);
    });
  }

  @override
  Widget build(BuildContext context) {
    RaisedButton(
      onPressed: startTimer(sendport),
      child: Text("Start"),
    );
  }
}

Я ожидаю, что кодчтобы отправить сообщение через 1 минуту, вместо этого я получаю сообщение сразу после выполнения и получаю сообщение об ошибке "/ flutter (11424): [ОШИБКА: flutter / lib / ui / ui_dart_state.cc (148)] Необработанное исключение: 'dart: ui / plugins.dart ': Неудачное утверждение: строка 62:' ':' callback 'не должен быть нулевым. "

1 Ответ

0 голосов
/ 19 мая 2019

Изоляторы могут находить друг друга, регистрируя и просматривая имена с помощью IsolateNameServer

Вам нужно имя для порта, который могут видеть основной изолятор и обратный вызов, кажется, что глобальная константадля этого все в порядке.

Обратный вызов таймера, переданный AlarmManager.oneShot , не имеет параметра, поэтому ему нужно найти имя порта, чтобы найти SendPort для использования, когда онработает.

Зарегистрируйте имя порта для SendPort главного изолята при настройке - вам все еще нужен ReceivePort в MyAppState , но вам не нужен SendPort.

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'dart:isolate';
import 'dart:ui';

const String portName = "MyAppPort";

class MyApp extends StatefulWidget {
    _MyAppState createState() => _MyAppState();
}



startTimer() async {
    await AndroidAlarmManager.oneShot(
        Duration(seconds: 60), 0, timerCallback,
        wakeup: true, exact: true);
}

timerCallback() {
    SendPort sendPort = IsolateNameServer.lookupPortByName(portName);
    if (sendPort != null) {
        sendport.send("DONE");
    }
}

class _MyAppState extends State<MyApp> {
    ReceivePort receivePort = ReceivePort();

    @override
    void initState() {
        super.initState();
        IsolateNameServer.registerPortName(receivePort.sendPort, portName)
        AndroidAlarmManager.initialize();
        receivePort.listen((v) {
            print(v);
        });
    }

    @override
    Widget build(BuildContext context) {
        RaisedButton(
            onPressed: startTimer(),
            child: Text("Start"),
        );
  }
...