颤动实时跟踪

时间:2020-03-22 18:33:40

标签: flutter background location background-process

我是flutter开发的新手,具有android背景,我正在开发一个使用“ location”第三方api进行flutter实时跟踪的应用程序 链接:https://pub.dev/packages/location 在大多数设备中,当应用程序处于后台且未使用手机时,位置流会停止运行,过了一段时间后,我无法解决此问题,包括此api在内,但它不会再次启动该服务,链接:https://pub.dev/packages/background_fetch,但它们似乎并不能解决我的问题,如果有人对Flutter应用程序进行了跟踪,请务必分享。

谢谢

我要的结果。如果应用程序处于后台且未使用电话,则无论应获取电话位置的状态并将其发布到服务器上。

编辑:27-11-2020 事实证明,没有解决方案,这与颤动无关,但一般来说是android。 对于有此问题的人,请仔细阅读它在android 6.0及更高版本中引入的DOZE MODE。 我所做的解决方案是获得唤醒锁定,并保持屏幕处于打开状态以避免打ze睡模式,但这显然不是最优化的解决方案。

2 个答案:

答案 0 :(得分:0)

看看background_locator插件

import 'dart:async';
import 'dart:isolate';
import 'dart:ui';

import 'package:background_locator/background_locator.dart';
import 'package:background_locator/location_dto.dart';
import 'package:background_locator/location_settings.dart';
import 'package:flutter/material.dart';
import 'package:location_permissions/location_permissions.dart';

import 'file_manager.dart';
import 'location_callback_handler.dart';
import 'location_service_repository.dart';

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

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

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

  String logStr = '';
  bool isRunning;
  LocationDto lastLocation;
  DateTime lastTimeLocation;

  @override
  void initState() {
    super.initState();

    if (IsolateNameServer.lookupPortByName(
            LocationServiceRepository.isolateName) !=
        null) {
      IsolateNameServer.removePortNameMapping(
          LocationServiceRepository.isolateName);
    }

    IsolateNameServer.registerPortWithName(
        port.sendPort, LocationServiceRepository.isolateName);

    port.listen(
      (dynamic data) async {
        await updateUI(data);
      },
    );
    initPlatformState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  Future<void> updateUI(LocationDto data) async {
    final log = await FileManager.readLogFile();
    setState(() {
      if (data != null) {
        lastLocation = data;
        lastTimeLocation = DateTime.now();
      }
      logStr = log;
    });
  }

  Future<void> initPlatformState() async {
    print('Initializing...');
    await BackgroundLocator.initialize();
    logStr = await FileManager.readLogFile();
    print('Initialization done');
    final _isRunning = await BackgroundLocator.isRegisterLocationUpdate();
    setState(() {
      isRunning = _isRunning;
    });
    print('Running ${isRunning.toString()}');
  }

  @override
  Widget build(BuildContext context) {
    final start = SizedBox(
      width: double.maxFinite,
      child: RaisedButton(
        child: Text('Start'),
        onPressed: () {
          _onStart();
        },
      ),
    );
    final stop = SizedBox(
      width: double.maxFinite,
      child: RaisedButton(
        child: Text('Stop'),
        onPressed: () {
          onStop();
        },
      ),
    );
    final clear = SizedBox(
      width: double.maxFinite,
      child: RaisedButton(
        child: Text('Clear Log'),
        onPressed: () {
          FileManager.clearLogFile();
          setState(() {
            logStr = '';
          });
        },
      ),
    );
    String msgStatus = "-";
    if (isRunning != null) {
      if (isRunning) {
        msgStatus = 'Is running';
      } else {
        msgStatus = 'Is not running';
      }
    }
    final status = Text("Status: $msgStatus");

    String lastRunTxt = "-";
    if (isRunning != null) {
      if (isRunning) {
        if (lastTimeLocation == null || lastLocation == null) {
          lastRunTxt = "?";
        } else {
          lastRunTxt =
              LocationServiceRepository.formatDateLog(lastTimeLocation) +
                  "-" +
                  LocationServiceRepository.formatLog(lastLocation);
        }
      }
    }
    final lastRun = Text(
      "Last run: $lastRunTxt",
    );

    final log = Text(
      logStr,
    );

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter background Locator'),
        ),
        body: Container(
          width: double.maxFinite,
          padding: const EdgeInsets.all(22),
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[start, stop, clear, status, lastRun, log],
            ),
          ),
        ),
      ),
    );
  }

  void onStop() {
    BackgroundLocator.unRegisterLocationUpdate();
    setState(() {
      isRunning = false;
//      lastTimeLocation = null;
//      lastLocation = null;
    });
  }

  void _onStart() async {
    if (await _checkLocationPermission()) {
      _startLocator();
      setState(() {
        isRunning = true;
        lastTimeLocation = null;
        lastLocation = null;
      });
    } else {
      // show error
    }
  }

  Future<bool> _checkLocationPermission() async {
    final access = await LocationPermissions().checkPermissionStatus();
    switch (access) {
      case PermissionStatus.unknown:
      case PermissionStatus.denied:
      case PermissionStatus.restricted:
        final permission = await LocationPermissions().requestPermissions(
          permissionLevel: LocationPermissionLevel.locationAlways,
        );
        if (permission == PermissionStatus.granted) {
          return true;
        } else {
          return false;
        }
        break;
      case PermissionStatus.granted:
        return true;
        break;
      default:
        return false;
        break;
    }
  }

  void _startLocator() {
    Map<String, dynamic> data = {'countInit': 1};
    BackgroundLocator.registerLocationUpdate(
      LocationCallbackHandler.callback,
      initCallback: LocationCallbackHandler.initCallback,
      initDataCallback: data,
/*
        Comment initDataCallback, so service not set init variable,
        variable stay with value of last run after unRegisterLocationUpdate
 */
      disposeCallback: LocationCallbackHandler.disposeCallback,
      androidNotificationCallback: LocationCallbackHandler.notificationCallback,
      settings: LocationSettings(
          notificationChannelName: "Location tracking service",
          notificationTitle: "Start Location Tracking example",
          notificationMsg: "Track location in background example",
          wakeLockTime: 20,
          autoStop: false,
          distanceFilter: 10,
          interval: 5),
    );
  }
} 

答案 1 :(得分:0)

我使用平台通道解决了 Flutter 中的后台位置服务。我结合了 android 前台服务(是前台,在后台访问 GPS 位置不允许实时。)

enter image description here

我已经通过使用平台通道、Android 前台服务解决了适用于 Android 的实时后台定位 Flutter 应用程序。无论何时屏幕打开或关闭,它都能完美运行,您无需一直唤醒屏幕来获取位置更新。

图片来源:https://flutter.dev/

https://flutter.dev/docs/development/platform-integration/platform-channels