dart 如何使Flutter Workmanager插件和Location插件协同工作

zsohkypk  于 2023-10-13  发布在  Flutter
关注(0)|答案(2)|浏览(145)
    • 1.问题描述**

我的目标是构建一个Flutter应用程序,使用this workmanager pluginthis location plugin定期获取位置更新。但是当我的Workmanager回调函数被触发时,我无法正确加载Location插件。我得到这个错误:

MissingPluginException(No implementation found for method getLocation on channel lyokone/location)

所以基本上,问题是当Workmanager插件试图运行dart代码时,它不会加载Location插件。

    • 2.我研究过的其他资源**

我发现其他人也面临着同样的问题,在这里,herehere
据我所知,解决这些问题的办法可以归结为:创建一个名为 * www.example.com * 的文件,它扩展了 * FlutterApplication *,并注册了您的插件。CustomApplication.java

    • 3.到目前为止我的代码**

我试着做一个最低限度的应用程序,实现我需要的功能:
1.我实现了Workmanager插件(工作正常)
1.我实现了位置插件(工程罚款)
1.我试图合并这些功能(不工作)
要想知道我在每一步都做了什么,请看这里:https://gitlab.com/tomoerlemans/workmanager_with_location/-/commits/master.(此存储库也可用于快速复制问题)。
相关代码文件如下:

    • main. dart**
import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';
import 'package:location/location.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Workmanager.initialize(callbackDispatcher, isInDebugMode: true);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              onPressed: () {
                Workmanager.registerPeriodicTask(
                    "1", "simpleTask");
              },
              child: Text("Start workmanager"),
            ),
            RaisedButton(
              onPressed: () {
                getLocation();
              },
              child: Text("Get current location"),
            ),
          ],
        ),
      ),
    );
  }
}

void callbackDispatcher() {
  Workmanager.executeTask((task, inputData) {
    print("Native called background task at ${DateTime.now().toString()}");
    getLocation();
    return Future.value(true);
  });
}

void getLocation() async {
  LocationData currentLocation;
  var location = new Location();
  try {
    currentLocation = await location.getLocation();
  } on Exception catch (e) {
    print("Error obtaining location: $e");
    currentLocation = null;
  }
  print("Location altitude: ${currentLocation.altitude}");
  print("Location longitude: ${currentLocation.longitude}");
}
    • pubspec. yaml**
name: background_location
description: A new Flutter project.

version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  workmanager: ^0.2.0
  location: ^2.3.5

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true
    • CustomApplication. java**
package io.flutter.plugins;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import be.tramckrijte.workmanager.WorkmanagerPlugin;
import com.lyokone.location.LocationPlugin;

public class CustomApplication extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback {
    @Override
    public void onCreate() {
        super.onCreate();
        WorkmanagerPlugin.setPluginRegistrantCallback(this);

    }
    @Override
    public void registerWith(PluginRegistry registry) {
        WorkmanagerPlugin.registerWith(registry.registrarFor("be.tramckrijte.workmanager.WorkmanagerPlugin"));
        LocationPlugin.registerWith(registry.registrarFor("com.lyokone.location.LocationPlugin"));
    }
}
    • AndroidManifest. xml**
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.background_location">        
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:name="io.flutter.plugins.CustomApplication"
        android:label="background_location"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

最后,我正在运行以下版本的Dart/Flutter/etc:

Flutter 1.12.13+hotfix.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 27321ebbad (10 weeks ago) • 2019-12-10 18:15:01 -0800
Engine • revision 2994f7e1e6
Tools • Dart 2.7.0
ilmyapht

ilmyapht1#

我还没有尝试过什么背景位置跟踪,但考虑到你只想从背景位置跟踪,那么我认为workmanager + geolocater会工作。你应该看到这个项目ha_client它使用workmanager和geolocater一起获得坐标
另外,你使用的位置包有它自己的背景位置跟踪,这是在实验Background Location Updates

eagi6jfj

eagi6jfj2#

有了这两个插件,你可以安排一个一次性的任务,并将当前位置传递给它。
be.tramckrijte.workmanager有限制(它甚至声明并不是所有的东西都被支持)。通过Dart组合这两个插件可能会一事无成,因为应用程序并不总是运行。即使有一个简单的_callback_dispatcher_registration.dart,它显示了它是如何工作的,这将回调到Flutter引擎,而不是查询其他插件。
编写和调度一个位置感知的ListenableWorker可能是在运行任务时获取GPS定位的最佳选择-除非有任何方法可以在后台运行时通过Flutter引擎查询LocationPlugin插件。我的意思是,如果ListenableWorker是位置感知的,它不需要从其他地方获取位置。Threading in WorkManager的字面意思是:
ListenableWorkerWorkerCoroutineWorkerRxWorker的基类。它面向Java开发人员 *,他们必须与基于回调的异步API *(如FusedLocationProviderClient)进行交互。
因此,ListenableWorkerWorkerCoroutineWorker将是可扩展的适用类。iOS实现的等价物是一个位置感知的后台服务。Flutter引擎可以启动/停止它们,提供启动参数或接收回调,但在后台运行的代码通常不会是Dart,因为它应该独立运行。

相关问题