added tracking function. Not testet on a walk yet. Also the notifiation doesnt work
time forgot to save tracking file
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
<application
|
<application
|
||||||
android:label="fforte"
|
android:label="fforte"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
|||||||
@@ -156,6 +156,9 @@
|
|||||||
"heulen": "Heulen",
|
"heulen": "Heulen",
|
||||||
"sonstiges": "Sonstiges",
|
"sonstiges": "Sonstiges",
|
||||||
"hinweise": "Hinweise",
|
"hinweise": "Hinweise",
|
||||||
"zurueckgelegteStrecke": "Zurückgelegte Strecke"
|
"zurueckgelegteStrecke": "Zurückgelegte Strecke",
|
||||||
|
"tracking": "Tracking",
|
||||||
|
"couldntDeterminePosition": "Position konnte nicht ermittelt werden",
|
||||||
|
"trackingRunningInBackground": "Die Tracking funktion läuft im Hintergrund"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -661,6 +661,11 @@
|
|||||||
|
|
||||||
"hinweise": "clues",
|
"hinweise": "clues",
|
||||||
|
|
||||||
"zurueckgelegteStrecke": "Distance traveled"
|
"zurueckgelegteStrecke": "Distance traveled",
|
||||||
|
|
||||||
|
"tracking": "Tracking",
|
||||||
|
|
||||||
|
"couldntDeterminePosition": "couldn't determine position",
|
||||||
|
|
||||||
|
"trackingRunningInBackground": "The tracking service is running in the background"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1048,6 +1048,24 @@ abstract class AppLocalizations {
|
|||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Distance traveled'**
|
/// **'Distance traveled'**
|
||||||
String get zurueckgelegteStrecke;
|
String get zurueckgelegteStrecke;
|
||||||
|
|
||||||
|
/// No description provided for @tracking.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Tracking'**
|
||||||
|
String get tracking;
|
||||||
|
|
||||||
|
/// No description provided for @couldntDeterminePosition.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'couldn\'t determine position'**
|
||||||
|
String get couldntDeterminePosition;
|
||||||
|
|
||||||
|
/// No description provided for @trackingRunningInBackground.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'The tracking service is running in the background'**
|
||||||
|
String get trackingRunningInBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||||
|
|||||||
@@ -484,4 +484,13 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get zurueckgelegteStrecke => 'Zurückgelegte Strecke';
|
String get zurueckgelegteStrecke => 'Zurückgelegte Strecke';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tracking => 'Tracking';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get couldntDeterminePosition => 'Position konnte nicht ermittelt werden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trackingRunningInBackground => 'Die Tracking funktion läuft im Hintergrund';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -484,4 +484,13 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get zurueckgelegteStrecke => 'Distance traveled';
|
String get zurueckgelegteStrecke => 'Distance traveled';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tracking => 'Tracking';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get couldntDeterminePosition => 'couldn\'t determine position';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trackingRunningInBackground => 'The tracking service is running in the background';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ class ExcursionDBHelper implements IDb {
|
|||||||
@override
|
@override
|
||||||
onCreateDatabases(Database excursionDB, int version) async {
|
onCreateDatabases(Database excursionDB, int version) async {
|
||||||
await excursionDB.execute(
|
await excursionDB.execute(
|
||||||
'CREATE TABLE excursion (ID INTEGER PRIMARY KEY AUTOINCREMENT, LogDat TEXT, Rudel TEXT, Teilnehmer TEXT, Jahr TEXT, Dauer TEXT, MHund INTEGER, MLeine TEXT, BLand TEXT, Lkr TEXT, BeiOrt TEXT, BimaName TEXT, Wetter TEXT, Temperat TEXT, RegenVor TEXT, KmRad TEXT, KmAuto TEXT, KmFuss TEXT, KmTotal TEXT, KmAuProz TEXT, KmFuProz TEXT, KmRaProz TEXT, SpGut TEXT, SpMittel, SpSchlecht TEXT, SpurFund TEXT, SpurLang TEXT, SpurTiere Text, SpSicher TEXT, WelpenSp TEXT, WelpenAnz TEXT, WpSicher TEXT, LosungGes TEXT, LosungAnz TEXT, LosungGen TEXT, UrinAnz TEXT, UrinGen TEXT, OestrAnz TEXT, OestrGen TEXT, HaarAnz TEXT, HaarGen TEXT, LosungKm TEXT, GenetiKm TEXT, Hinweise TEXT, Bemerk TEXT, IntKomm TEXT, BimaNr TEXT, BimaNutzer TEXT, BimaAGV TEXT, FallNum INTEGER, Sent INTEGER DEFAULT 0)',
|
'CREATE TABLE excursion (ID INTEGER PRIMARY KEY AUTOINCREMENT, LogDat TEXT, Rudel TEXT, Teilnehmer TEXT, Jahr TEXT, Dauer TEXT, MHund INTEGER, MLeine TEXT, BLand TEXT, Lkr TEXT, BeiOrt TEXT, BimaName TEXT, Wetter TEXT, Temperat TEXT, RegenVor TEXT, KmRad TEXT, KmAuto TEXT, KmFuss TEXT, KmTotal TEXT, KmAuProz TEXT, KmFuProz TEXT, KmRaProz TEXT, SpGut TEXT, SpMittel, SpSchlecht TEXT, SpurFund TEXT, SpurLang TEXT, SpurTiere Text, SpSicher TEXT, WelpenSp TEXT, WelpenAnz TEXT, WpSicher TEXT, LosungGes TEXT, LosungAnz TEXT, LosungGen TEXT, UrinAnz TEXT, UrinGen TEXT, OestrAnz TEXT, OestrGen TEXT, HaarAnz TEXT, HaarGen TEXT, LosungKm TEXT, GenetiKm TEXT, Hinweise TEXT, Bemerk TEXT, IntKomm TEXT, BimaNr TEXT, BimaNutzer TEXT, BimaAGV TEXT, FallNum INTEGER, Weg TEXT, Sent INTEGER DEFAULT 0)',
|
||||||
);
|
);
|
||||||
await excursionDB.execute(
|
await excursionDB.execute(
|
||||||
'CREATE TABLE excursionTemplates (ID INTEGER PRIMARY KEY AUTOINCREMENT, LogDat TEXT, Rudel TEXT, Teilnehmer TEXT, Jahr TEXT, Dauer TEXT, MHund INTEGER, MLeine TEXT, BLand TEXT, Lkr TEXT, BeiOrt TEXT, BimaName TEXT, Wetter TEXT, Temperat TEXT, RegenVor TEXT, KmRad TEXT, KmAuto TEXT, KmFuss TEXT, KmTotal TEXT, KmAuProz TEXT, KmFuProz TEXT, KmRaProz TEXT, SpGut TEXT, SpMittel, SpSchlecht TEXT, SpurFund TEXT, SpurLang TEXT, SpurTiere Text, SpSicher TEXT, WelpenSp TEXT, WelpenAnz TEXT, WpSicher TEXT, LosungGes TEXT, LosungAnz TEXT, LosungGen TEXT, UrinAnz TEXT, UrinGen TEXT, OestrAnz TEXT, OestrGen TEXT, HaarAnz TEXT, HaarGen TEXT, LosungKm TEXT, GenetiKm TEXT, Hinweise TEXT, Bemerk TEXT, IntKomm TEXT, BimaNr TEXT, BimaNutzer TEXT, BimaAGV TEXT, FallNum INTEGER)',
|
'CREATE TABLE excursionTemplates (ID INTEGER PRIMARY KEY AUTOINCREMENT, LogDat TEXT, Rudel TEXT, Teilnehmer TEXT, Jahr TEXT, Dauer TEXT, MHund INTEGER, MLeine TEXT, BLand TEXT, Lkr TEXT, BeiOrt TEXT, BimaName TEXT, Wetter TEXT, Temperat TEXT, RegenVor TEXT, KmRad TEXT, KmAuto TEXT, KmFuss TEXT, KmTotal TEXT, KmAuProz TEXT, KmFuProz TEXT, KmRaProz TEXT, SpGut TEXT, SpMittel, SpSchlecht TEXT, SpurFund TEXT, SpurLang TEXT, SpurTiere Text, SpSicher TEXT, WelpenSp TEXT, WelpenAnz TEXT, WpSicher TEXT, LosungGes TEXT, LosungAnz TEXT, LosungGen TEXT, UrinAnz TEXT, UrinGen TEXT, OestrAnz TEXT, OestrGen TEXT, HaarAnz TEXT, HaarGen TEXT, LosungKm TEXT, GenetiKm TEXT, Hinweise TEXT, Bemerk TEXT, IntKomm TEXT, BimaNr TEXT, BimaNutzer TEXT, BimaAGV TEXT, FallNum INTEGER, Weg TEXT)',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import 'package:animations/animations.dart';
|
import 'package:animations/animations.dart';
|
||||||
import 'package:fforte/enums/databases.dart';
|
import 'package:fforte/enums/databases.dart';
|
||||||
|
import 'package:fforte/screens/addCam/exceptions/location_disabled_exception.dart';
|
||||||
|
import 'package:fforte/screens/addCam/exceptions/location_forbidden_exception.dart';
|
||||||
|
import 'package:fforte/screens/addCam/services/geolocator_service.dart';
|
||||||
import 'package:fforte/screens/excursion/widgets/anzahlen.dart';
|
import 'package:fforte/screens/excursion/widgets/anzahlen.dart';
|
||||||
import 'package:fforte/screens/excursion/widgets/bima_nutzer.dart';
|
import 'package:fforte/screens/excursion/widgets/bima_nutzer.dart';
|
||||||
import 'package:fforte/screens/excursion/widgets/hinweise.dart';
|
import 'package:fforte/screens/excursion/widgets/hinweise.dart';
|
||||||
@@ -7,13 +10,17 @@ import 'package:fforte/screens/excursion/widgets/hund_u_leine.dart';
|
|||||||
import 'package:fforte/screens/excursion/widgets/letzter_niederschlag.dart';
|
import 'package:fforte/screens/excursion/widgets/letzter_niederschlag.dart';
|
||||||
import 'package:fforte/screens/excursion/widgets/spur_gefunden.dart';
|
import 'package:fforte/screens/excursion/widgets/spur_gefunden.dart';
|
||||||
import 'package:fforte/screens/excursion/widgets/strecke_u_spurbedingungen.dart';
|
import 'package:fforte/screens/excursion/widgets/strecke_u_spurbedingungen.dart';
|
||||||
|
import 'package:fforte/screens/excursion/widgets/tracking.dart';
|
||||||
import 'package:fforte/screens/helper/add_entries_dialog_helper.dart';
|
import 'package:fforte/screens/helper/add_entries_dialog_helper.dart';
|
||||||
|
import 'package:fforte/screens/helper/snack_bar_helper.dart';
|
||||||
import 'package:fforte/screens/sharedMethods/check_required.dart';
|
import 'package:fforte/screens/sharedMethods/check_required.dart';
|
||||||
import 'package:fforte/screens/sharedMethods/save_template.dart';
|
import 'package:fforte/screens/sharedMethods/save_template.dart';
|
||||||
import 'package:fforte/screens/sharedWidgets/datum.dart';
|
import 'package:fforte/screens/sharedWidgets/datum.dart';
|
||||||
import 'package:fforte/screens/sharedWidgets/var_text_field.dart';
|
import 'package:fforte/screens/sharedWidgets/var_text_field.dart';
|
||||||
import 'package:fforte/l10n/app_localizations.dart';
|
import 'package:fforte/l10n/app_localizations.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:geolocator/geolocator.dart';
|
||||||
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
class ExcursionMain extends StatefulWidget {
|
class ExcursionMain extends StatefulWidget {
|
||||||
final bool isTemplate;
|
final bool isTemplate;
|
||||||
@@ -34,6 +41,18 @@ class ExcursionMain extends StatefulWidget {
|
|||||||
class _ExcursionMainState extends State<ExcursionMain> {
|
class _ExcursionMainState extends State<ExcursionMain> {
|
||||||
int currentStep = 0;
|
int currentStep = 0;
|
||||||
late bool isTemplate;
|
late bool isTemplate;
|
||||||
|
Position currentPosition = Position(
|
||||||
|
longitude: 10.0,
|
||||||
|
latitude: 51.0,
|
||||||
|
timestamp: DateTime.now(),
|
||||||
|
accuracy: 0.0,
|
||||||
|
altitude: 0.0,
|
||||||
|
heading: 0.0,
|
||||||
|
speed: 0.0,
|
||||||
|
speedAccuracy: 0.0,
|
||||||
|
altitudeAccuracy: 0.0,
|
||||||
|
headingAccuracy: 0.0,
|
||||||
|
);
|
||||||
|
|
||||||
// all TextEditingController because its easier
|
// all TextEditingController because its easier
|
||||||
Map<String, Map<String, dynamic>> rmap = {
|
Map<String, Map<String, dynamic>> rmap = {
|
||||||
@@ -55,6 +74,7 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
|||||||
"BimaAGV": {"controller": TextEditingController(), "required": false},
|
"BimaAGV": {"controller": TextEditingController(), "required": false},
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
|
"Weg": {"controller": TextEditingController(), "required": false},
|
||||||
"Wetter": {"controller": TextEditingController(), "required": false},
|
"Wetter": {"controller": TextEditingController(), "required": false},
|
||||||
"Temperat": {"controller": TextEditingController(), "required": false},
|
"Temperat": {"controller": TextEditingController(), "required": false},
|
||||||
"RegenVor": {"controller": TextEditingController(), "required": false},
|
"RegenVor": {"controller": TextEditingController(), "required": false},
|
||||||
@@ -100,6 +120,27 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
GeolocatorService.deteterminePosition()
|
||||||
|
.then((result) => currentPosition = result)
|
||||||
|
.catchError((error) {
|
||||||
|
if (error is LocationDisabledException) {
|
||||||
|
if (mounted) {
|
||||||
|
SnackBarHelper.showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
AppLocalizations.of(context)!.locationDisabled,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (error is LocationForbiddenException) {
|
||||||
|
if (mounted) {
|
||||||
|
SnackBarHelper.showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
AppLocalizations.of(context)!.locationForbidden,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentPosition;
|
||||||
|
});
|
||||||
|
|
||||||
if (widget.existingData?.isNotEmpty ?? false) {
|
if (widget.existingData?.isNotEmpty ?? false) {
|
||||||
for (var key in widget.existingData!.keys) {
|
for (var key in widget.existingData!.keys) {
|
||||||
rmap[key]!["controller"]!.text =
|
rmap[key]!["controller"]!.text =
|
||||||
@@ -130,7 +171,6 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
|||||||
return puff;
|
return puff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List<Step> getSteps() => [
|
List<Step> getSteps() => [
|
||||||
@@ -253,6 +293,27 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
|||||||
title: Text(AppLocalizations.of(context)!.umstaendeUndAktionen),
|
title: Text(AppLocalizations.of(context)!.umstaendeUndAktionen),
|
||||||
content: Column(
|
content: Column(
|
||||||
children: [
|
children: [
|
||||||
|
// ---------- Tracking
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed:
|
||||||
|
() => Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return Tracking(
|
||||||
|
weg: rmap["Weg"]!["controller"]!,
|
||||||
|
startPosition: LatLng(
|
||||||
|
currentPosition.latitude,
|
||||||
|
currentPosition.longitude,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(AppLocalizations.of(context)!.tracking),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
|
||||||
// ---------- Weather
|
// ---------- Weather
|
||||||
VarTextField(
|
VarTextField(
|
||||||
textController: rmap["Wetter"]!["controller"]!,
|
textController: rmap["Wetter"]!["controller"]!,
|
||||||
@@ -390,7 +451,6 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
|||||||
currentStep += 1;
|
currentStep += 1;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (widget.isSent) {
|
if (widget.isSent) {
|
||||||
Navigator.pushNamedAndRemoveUntil(
|
Navigator.pushNamedAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
|
|||||||
186
lib/screens/excursion/widgets/tracking.dart
Normal file
186
lib/screens/excursion/widgets/tracking.dart
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:fforte/l10n/app_localizations.dart';
|
||||||
|
import 'package:fforte/screens/helper/snack_bar_helper.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_map/flutter_map.dart';
|
||||||
|
import 'package:geolocator/geolocator.dart';
|
||||||
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
|
class Tracking extends StatefulWidget {
|
||||||
|
final LatLng startPosition;
|
||||||
|
final TextEditingController weg;
|
||||||
|
const Tracking({super.key, required this.startPosition, required this.weg});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<Tracking> createState() => _TrackingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TrackingState extends State<Tracking> {
|
||||||
|
List<LatLng> pathList = [];
|
||||||
|
StreamSubscription<Position>? positionStream;
|
||||||
|
bool positionStreamRunning = false;
|
||||||
|
|
||||||
|
Random rand = Random();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
// TODO debugging (i guess)
|
||||||
|
pathList.add(
|
||||||
|
LatLng(widget.startPosition.latitude, widget.startPosition.longitude),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (widget.weg.text.isNotEmpty) {
|
||||||
|
for (var element in widget.weg.text.split(";")) {
|
||||||
|
List<String> posSplit = element.split(",");
|
||||||
|
try {
|
||||||
|
posSplit[0] = posSplit[0].substring(0, 9);
|
||||||
|
posSplit[1] = posSplit[1].substring(0, 9);
|
||||||
|
} on RangeError {
|
||||||
|
// ignore because the double is short enough then
|
||||||
|
}
|
||||||
|
|
||||||
|
pathList.add(
|
||||||
|
LatLng(double.parse(posSplit.first), double.parse(posSplit[1])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
if (positionStream != null) positionStream!.cancel();
|
||||||
|
bool isFirst = true;
|
||||||
|
if (pathList.isNotEmpty) {
|
||||||
|
for (var pos in pathList) {
|
||||||
|
if (!isFirst) {
|
||||||
|
widget.weg.text += ";";
|
||||||
|
} else {
|
||||||
|
isFirst = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.weg.text += "${pos.latitude},${pos.longitude}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
final LocationSettings streamLocationSettings = LocationSettings(
|
||||||
|
accuracy: LocationAccuracy.high,
|
||||||
|
distanceFilter: 10,
|
||||||
|
);
|
||||||
|
|
||||||
|
void onTrackingStart() async {
|
||||||
|
// // notification handling for tracking in background notification
|
||||||
|
// PermissionStatus permissionStatus =
|
||||||
|
// await NotificationPermissions.getNotificationPermissionStatus();
|
||||||
|
//
|
||||||
|
// if (permissionStatus != PermissionStatus.granted) {
|
||||||
|
// await NotificationPermissions.requestNotificationPermissions();
|
||||||
|
// }
|
||||||
|
|
||||||
|
positionStream = Geolocator.getPositionStream(
|
||||||
|
locationSettings: AndroidSettings(
|
||||||
|
accuracy: LocationAccuracy.high,
|
||||||
|
distanceFilter: 0,
|
||||||
|
foregroundNotificationConfig:
|
||||||
|
mounted
|
||||||
|
? ForegroundNotificationConfig(
|
||||||
|
notificationTitle:
|
||||||
|
AppLocalizations.of(context)!.trackingRunningInBackground,
|
||||||
|
notificationText: "",
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
).listen((Position? position) {
|
||||||
|
if (position != null) {
|
||||||
|
// pathList.add(LatLng(position.latitude, position.longitude));
|
||||||
|
setState(() {
|
||||||
|
pathList.add(LatLng(rand.nextInt(5) + 40, position.longitude));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (mounted) {
|
||||||
|
SnackBarHelper.showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
AppLocalizations.of(context)!.couldntDeterminePosition,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(AppLocalizations.of(context)!.tracking),
|
||||||
|
// leading: IconButton(onPressed: () {}, icon: Icon(Icons.arrow_back_rounded)),
|
||||||
|
actions: [
|
||||||
|
if (positionStreamRunning)
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
positionStreamRunning = false;
|
||||||
|
positionStream!.cancel();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.stop_rounded),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (positionStreamRunning) {
|
||||||
|
positionStreamRunning = false;
|
||||||
|
positionStream?.pause();
|
||||||
|
} else {
|
||||||
|
positionStreamRunning = true;
|
||||||
|
onTrackingStart();
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
icon:
|
||||||
|
positionStreamRunning
|
||||||
|
? Icon(Icons.pause)
|
||||||
|
: Icon(Icons.play_arrow),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: FlutterMap(
|
||||||
|
mapController: MapController(),
|
||||||
|
options: MapOptions(
|
||||||
|
interactionOptions: const InteractionOptions(
|
||||||
|
flags:
|
||||||
|
InteractiveFlag.pinchZoom |
|
||||||
|
InteractiveFlag.drag |
|
||||||
|
InteractiveFlag.pinchMove,
|
||||||
|
),
|
||||||
|
initialCenter: widget.startPosition,
|
||||||
|
initialZoom: 16.0,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TileLayer(
|
||||||
|
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||||
|
userAgentPackageName: 'com.example.app',
|
||||||
|
),
|
||||||
|
if (pathList.isNotEmpty)
|
||||||
|
PolylineLayer(
|
||||||
|
polylines: [
|
||||||
|
Polyline(strokeWidth: 2.0, points: pathList, color: Colors.red),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
CircleLayer(
|
||||||
|
circles: [
|
||||||
|
CircleMarker(
|
||||||
|
color: Colors.blue,
|
||||||
|
point: pathList.isEmpty ? widget.startPosition : pathList.last,
|
||||||
|
radius: 5,
|
||||||
|
useRadiusInMeter: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user