Flutter GPS历史记录插件gps_history的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter GPS历史记录插件gps_history的使用

GPS History for Dart

模块旨在表示以 >= 1 秒频率记录的GPS点的历史。特性包括:

  • 三种类型的GPS点:一种仅包含最基本信息的简洁类型,一种包含更多元数据(如方向、速度等)的类型,这种类型对生成GPX文件非常有用。此外,还有一种表示在某地点停留时间较长的点,这可以用于减少数据库中的重复条目。

  • 不同的内存存储系统来存储GPS点:要么简单地基于列表,要么采用高效的二进制表示,每个点大约占用 14 到 22 字节(代价是精度略有损失,但该损失在GPS传感器的精度范围之内)。

  • 对Google位置历史JSON导出的极低内存且快速解析器。作为参考,使用Dart JSON库直接解析一个约500MB的历史文件大约需要2GB的内存,在Intel Core i7-8565U处理器上每秒可产生约140k个点,而自定义解析器几乎不增加额外内存开销,并且输出速度比前者快2.5到3.5倍。在移动设备上解析Google位置历史时无需担心内存不足的问题。

  • 模块化和可扩展架构:添加自己的点定义、容器或持久性机制。

  • 包含大量单元测试、示例、基准测试和文档。

  • 时间和距离处理的实用函数。

  • 支持空安全。

  • 第三方库依赖仅限于浅层功能,并且这些库都是主流且得到良好支持的。

示例

读取Google JSON文件

import 'dart:io';
import 'package:gps_history/gps_history.dart';
import 'package:gps_history/gps_history_convert.dart';

void main() async {
  final filename = 'data/g_history_sample.json';

  final file = File(filename);
  final gpsStays = GpcCompactGpsStay();

  final fileStream = file.openRead();

  final points = fileStream.transform(GoogleJsonHistoryDecoder(
      minSecondsBetweenDatapoints: 1, accuracyThreshold: 500));

  final stays = points.transform(
      PointsToStaysDecoder(maxTimeGapSeconds: 10, maxDistanceGapMeters: 10));

  await for (final s in stays) {
    gpsStays.add(s);
  }

  print('Read ${gpsStays.length} points');

  // 计算点的记录频率
  final intervals = <int>[];
  final durations = <int>[];
  final distances = <double>[];
  GpsStay? prevPoint;

  for (final s in gpsStays) {
    durations.add(s.endTime.difference(s.startTime).inSeconds);
    if (prevPoint != null) {
      final diff = s.time.difference(prevPoint.endTime).inSeconds;
      intervals.add(diff);

      final dist = distance(prevPoint, s);
      distances.add(dist);
    }
    prevPoint = s;
  }

  intervals.sort();
  durations.sort();
  distances.sort();

  if (intervals.isNotEmpty) {
    print('Intervals:');
    print('  min    = ${intervals[0]} s');
    print('  median = ${intervals[intervals.length ~/ 2]} s');
    print('  max    = ${intervals[intervals.length - 1]} s');
  }
  if (durations.isNotEmpty) {
    print('Durations:');
    print('  min    = ${durations[0]} s');
    print('  median = ${durations[durations.length ~/ 2]} s');
    print('  max    = ${durations[durations.length - 1]} s');
  }
  if (distances.isNotEmpty) {
    print('Distances:');
    print('  min    = ${distances[0].toStringAsFixed(2)} m');
    print('  median = ${distances[distances.length ~/ 2].toStringAsFixed(2)} m');
    print('  max    = ${distances[distances.length - 1].toStringAsFixed(2)} m');
  }
}

保存/重新加载数据

import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:gps_history/gps_history.dart';
import 'package:gps_history/gps_history_convert.dart';

void main() async {
  final databasePath = await getApplicationDocumentsDirectory();
  final db = await openDatabase(databasePath.path + '/gps_history.db', version: 1, onCreate: (db, version) async {
    await db.execute('CREATE TABLE gps_stay (id INTEGER PRIMARY KEY, latitude REAL, longitude REAL, startTime TEXT, endTime TEXT)');
  });

  final gpsStays = GpcCompactGpsStay();

  // 假设你已经从某个地方获取到了gpsStays对象
  await db.transaction((txn) async {
    final batch = txn.batch();
    for (var stay in gpsStays) {
      batch.insert('gps_stay', {
        'latitude': stay.latitude,
        'longitude': stay.longitude,
        'startTime': stay.startTime.toIso8601String(),
        'endTime': stay.endTime.toIso8601String()
      });
    }
    await batch.commit(noResult: true);
  });

  print('Data saved successfully.');

  // 重新加载数据
  final loadedStays = GpcCompactGpsStay();
  final loadedStaysList = await db.query('gps_stay');
  for (var stay in loadedStaysList) {
    final gpsStay = GpsStay(
      latitude: stay['latitude'],
      longitude: stay['longitude'],
      startTime: DateTime.parse(stay['startTime']),
      endTime: DateTime.parse(stay['endTime'])
    );
    loadedStays.add(gpsStay);
  }

  print('Data reloaded successfully.');
}

将Google JSON文件转换为SQLite数据库

import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:gps_history/gps_history.dart';
import 'package:gps_history/gps_history_convert.dart';

void main() async {
  final databasePath = await getApplicationDocumentsDirectory();
  final db = await openDatabase(databasePath.path + '/gps_history.db', version: 1, onCreate: (db, version) async {
    await db.execute('CREATE TABLE gps_stay (id INTEGER PRIMARY KEY, latitude REAL, longitude REAL, startTime TEXT, endTime TEXT)');
  });

  final filename = 'data/g_history_sample.json';

  final file = File(filename);
  final gpsStays = GpcCompactGpsStay();

  final fileStream = file.openRead();

  final points = fileStream.transform(GoogleJsonHistoryDecoder(
      minSecondsBetweenDatapoints: 1, accuracyThreshold: 500));

  final stays = points.transform(
      PointsToStaysDecoder(maxTimeGapSeconds: 10, maxDistanceGapMeters: 10));

  await for (final s in stays) {
    gpsStays.add(s);
  }

  print('Read ${gpsStays.length} points');

  await db.transaction((txn) async {
    final batch = txn.batch();
    for (var stay in gpsStays) {
      batch.insert('gps_stay', {
        'latitude': stay.latitude,
        'longitude': stay.longitude,
        'startTime': stay.startTime.toIso8601String(),
        'endTime': stay.endTime.toIso8601String()
      });
    }
    await batch.commit(noResult: true);
  });

  print('Data saved successfully.');
}

更多关于Flutter GPS历史记录插件gps_history的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter GPS历史记录插件gps_history的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用gps_history插件来获取GPS历史记录的示例代码。请注意,gps_history插件可能不是Flutter官方插件,因此你可能需要在pubspec.yaml文件中添加相应的依赖项(假设该插件存在于pub.dev上)。

首先,确保在pubspec.yaml文件中添加gps_history插件的依赖项(假设插件名为gps_history,并且已经在pub.dev上发布):

dependencies:
  flutter:
    sdk: flutter
  gps_history: ^x.y.z  # 替换为实际版本号

然后,运行flutter pub get来安装该插件。

接下来,在你的Flutter项目中,你可以按照以下步骤使用gps_history插件来获取GPS历史记录。

1. 导入插件

在你的Dart文件中导入gps_history插件:

import 'package:gps_history/gps_history.dart';

2. 请求权限

由于访问GPS历史记录需要权限,你需要在Android和iOS上请求相应的权限。以下是一个简单的权限请求示例(你可能需要根据实际情况调整):

Android

AndroidManifest.xml文件中添加权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

iOS

Info.plist文件中添加权限描述:

<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>

3. 使用插件获取GPS历史记录

以下是一个使用gps_history插件获取GPS历史记录的示例代码:

import 'package:flutter/material.dart';
import 'package:gps_history/gps_history.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('GPS History Example'),
        ),
        body: GPSHistoryScreen(),
      ),
    );
  }
}

class GPSHistoryScreen extends StatefulWidget {
  @override
  _GPSHistoryScreenState createState() => _GPSHistoryScreenState();
}

class _GPSHistoryScreenState extends State<GPSHistoryScreen> {
  List<GPSHistoryPoint> _historyPoints = [];

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

  Future<void> _getGPSHistory() async {
    try {
      bool permissionGranted = await GPSHistory.requestLocationPermission();
      if (permissionGranted) {
        List<GPSHistoryPoint> historyPoints = await GPSHistory.getHistory();
        setState(() {
          _historyPoints = historyPoints;
        });
      } else {
        print('Location permission denied');
      }
    } catch (e) {
      print('Error fetching GPS history: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: _historyPoints.length,
      itemBuilder: (context, index) {
        GPSHistoryPoint point = _historyPoints[index];
        return ListTile(
          title: Text('Latitude: ${point.latitude}, Longitude: ${point.longitude}'),
          subtitle: Text('Timestamp: ${point.timestamp}'),
        );
      },
    );
  }
}

class GPSHistoryPoint {
  final double latitude;
  final double longitude;
  final DateTime timestamp;

  GPSHistoryPoint({required this.latitude, required this.longitude, required this.timestamp});
}

注意:上述代码中的GPSHistoryPoint类是一个假设的类,用于存储GPS历史记录点。实际的gps_history插件可能会有自己的数据结构,你需要根据插件的文档进行调整。此外,GPSHistory.getHistory()方法也是一个假设的方法,你需要根据插件的实际API进行替换。

由于gps_history插件的具体API和实现细节可能有所不同,建议查阅该插件的官方文档或源代码以获取准确的信息。如果插件不支持直接获取GPS历史记录,你可能需要寻找其他方法或插件来实现该功能。

回到顶部