Ошибка разрешения местоположения платформы с изолятами Flutter - PullRequest
2 голосов
/ 08 февраля 2020

Я пытаюсь запустить обновление местоположения в потоке изолята Flutter, ошибка присутствует только при запуске изолята. Запросы местоположения работают без проблем в основном потоке. Цель здесь - запустить его в качестве фоновой службы, работающей только с кодом дротика. Я использую плагин Geolocator для запросов местоположения.

Это ошибка, с которой я сталкиваюсь при запуске изолята:

Произошло исключение. FlutterError (ServicesBinding.defaultBinaryMessenger был доступен до инициализации привязки.

Я попытался включить WidgetsFlutterBinding.ensureInitialized() перед runApp, но без результатов. Глядя на стек вызовов ошибки, кажется, возникают проблемы при вызове платформы android: checkPermissionStatus Это происходит независимо от того, какой плагин местоположения я использую, он останавливается при проверке состояния разрешений.

Я подумал, что это может быть связано с ожиданием разрешения местоположения пользовательский ввод, но эта проверка не будет выполнена в потоке, не являющемся пользовательским интерфейсом?

См. этот простой файл main.dart для примера:

import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Isolate location test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Isolate location test'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Isolate isolate;
  bool isRunning = false;
  String output = '';
  ReceivePort receivePort;

  void start() async {
    receivePort = ReceivePort();
    await Isolate.spawn(locationUpdate, receivePort.sendPort);
    receivePort.listen((dynamic data) {
      setState(() {
        isRunning = true;
      });
    }, onDone: () {
      print("done");
    });
  }

  void stop() {
    if (isolate != null) {
      setState(() {
        isRunning = false;
      });
      receivePort.close();
      isolate.kill(priority: Isolate.immediate);
      isolate = null;
    }
  }

  static void locationUpdate(SendPort sendPort) async {
    Geolocator().checkGeolocationPermissionStatus().then((status) {
      sendPort.send(status);
    });
    // Geolocator().getCurrentPosition().then((pos) {
    //   sendPort.send(pos);
    // });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(child: Text(output)),
      floatingActionButton: FloatingActionButton(
        onPressed: isRunning ? stop : start,
        child: Icon(isRunning ? Icons.stop : Icons.play_circle_filled),
      ),
    );
  }
}
...