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,5 +1,8 @@
|
||||
import 'package:animations/animations.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/bima_nutzer.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/spur_gefunden.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/snack_bar_helper.dart';
|
||||
import 'package:fforte/screens/sharedMethods/check_required.dart';
|
||||
import 'package:fforte/screens/sharedMethods/save_template.dart';
|
||||
import 'package:fforte/screens/sharedWidgets/datum.dart';
|
||||
import 'package:fforte/screens/sharedWidgets/var_text_field.dart';
|
||||
import 'package:fforte/l10n/app_localizations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
class ExcursionMain extends StatefulWidget {
|
||||
final bool isTemplate;
|
||||
@@ -34,6 +41,18 @@ class ExcursionMain extends StatefulWidget {
|
||||
class _ExcursionMainState extends State<ExcursionMain> {
|
||||
int currentStep = 0;
|
||||
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
|
||||
Map<String, Map<String, dynamic>> rmap = {
|
||||
@@ -55,6 +74,7 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
||||
"BimaAGV": {"controller": TextEditingController(), "required": false},
|
||||
|
||||
// Step 2
|
||||
"Weg": {"controller": TextEditingController(), "required": false},
|
||||
"Wetter": {"controller": TextEditingController(), "required": false},
|
||||
"Temperat": {"controller": TextEditingController(), "required": false},
|
||||
"RegenVor": {"controller": TextEditingController(), "required": false},
|
||||
@@ -100,6 +120,27 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
||||
|
||||
@override
|
||||
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) {
|
||||
for (var key in widget.existingData!.keys) {
|
||||
rmap[key]!["controller"]!.text =
|
||||
@@ -130,7 +171,6 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
||||
return puff;
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Step> getSteps() => [
|
||||
@@ -253,6 +293,27 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
||||
title: Text(AppLocalizations.of(context)!.umstaendeUndAktionen),
|
||||
content: Column(
|
||||
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
|
||||
VarTextField(
|
||||
textController: rmap["Wetter"]!["controller"]!,
|
||||
@@ -390,7 +451,6 @@ class _ExcursionMainState extends State<ExcursionMain> {
|
||||
currentStep += 1;
|
||||
});
|
||||
} else {
|
||||
|
||||
if (widget.isSent) {
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
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