Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
CLOUARD Regis
Vikazimut - App
Commits
3a24c4d2
Commit
3a24c4d2
authored
Mar 27, 2021
by
CLOUARD Regis
Browse files
Added GPS tracking
close
#7
parent
f3f0db97
Changes
33
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
3a24c4d2
# Application
Android
Vikazimut
# Application
Mobile
Vikazimut
## Le projet Vikazimut
Vikazimut est un projet d'étudiants en informatique de l'
[
ENSICAEN
](
https://www.ensicaen.fr
)
.
Le projet répond à une demande de l'association
[
Vik'Azim
](
https://vikazim.fr
)
visant la réalisation d'une application
Android
pour la pratique de la course d'orientation.
visant la réalisation d'une application
mobile
pour la pratique de la course d'orientation.
L’application
mobile
Vikazimut a pour objectif de faciliter la pratique de la course
L’application Vikazimut a pour objectif de faciliter la pratique de la course
d’orientation. Elle remplace la carte papier, la boussole et le poinçon de validation
des points de contrôle.
...
...
@@ -20,7 +20,8 @@ L’orienteur utilise l’application pour se repérer à partir de la carte et
aux points de contrôle avec le lecteur de code QR, le lecteur de tag NFC ou la position GPS.
L’application affiche en fin du parcours des statistiques sur la réalisation du parcours :
le temps total, le temps intermédiaire entre chaque balise et le tracé du parcours réalisé.
le temps total, le temps intermédiaire entre chaque balise, le dénivelé positif cumulé et
le tracé du parcours réalisé.
L’application se présente sous deux modes : un mode course où l’orienteur n’est pas aidé pour
sa localisation et un mode promenade où l’orienteur est positionné sur la carte en temps réel.
...
...
assets/i
con
s/arrow.png
→
assets/i
mage
s/arrow.png
View file @
3a24c4d2
File moved
assets/i
con
s/person.png
→
assets/i
mage
s/person.png
View file @
3a24c4d2
File moved
lib/course/abstract_mode_course_widget.dart
View file @
3a24c4d2
...
...
@@ -19,7 +19,6 @@ import 'package:Vikazimut_flutter/utils/time.dart';
import
'package:audioplayer/audioplayer.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:intl/intl.dart'
;
import
'package:path_provider/path_provider.dart'
;
import
'package:sprintf/sprintf.dart'
;
import
'package:vibration/vibration.dart'
;
...
...
@@ -52,6 +51,8 @@ abstract class AbstractModeCourseWidget extends StatelessWidget implements GpsPo
bool
_startPressed
=
false
;
OrienteeringMap
_map
;
MapView
?
_mapView
;
// int _screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
// BroadcastReceiver _compassBroadcastReceiver;
...
...
@@ -152,7 +153,7 @@ abstract class AbstractModeCourseWidget extends StatelessWidget implements GpsPo
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
UserManual
()));
break
;
case
2
:
//
forceControlPointValidation();
forceControlPointValidation
();
skipCurrentControlPoint
();
break
;
case
3
:
...
...
@@ -192,10 +193,12 @@ abstract class AbstractModeCourseWidget extends StatelessWidget implements GpsPo
case
ConnectionState
.
waiting
:
return
new
Text
(
'Image loading...'
);
// TODO i18n
default
:
if
(
snapshot
.
hasError
)
if
(
snapshot
.
hasError
)
{
return
new
Text
(
'Error:
${snapshot.error}
'
);
else
return
MapView
(
snapshot
.
data
!,
map
.
getBoundingBox
());
}
else
{
_mapView
=
MapView
(
snapshot
.
data
!,
map
.
getBoundingBox
());
return
_mapView
!;
}
}
},
),
...
...
@@ -213,6 +216,10 @@ abstract class AbstractModeCourseWidget extends StatelessWidget implements GpsPo
return
navigatorKey
.
currentContext
!;
}
MapView
?
getMapView
()
{
return
_mapView
;
}
// @override
// void onResume() {
// super.onResume();
...
...
lib/course/device/chronometer.dart
View file @
3a24c4d2
...
...
@@ -68,7 +68,7 @@ class _ChronometerState extends State<Chronometer> {
}
void
update
(
timeString
)
{
print
(
"update :
$timeString
"
);
//
print("update : $timeString");
setState
(()
{
_timeString
=
timeString
;
});
...
...
lib/course/device/geolocation.dart
deleted
100644 → 0
View file @
f3f0db97
import
'dart:async'
;
import
'package:flutter/material.dart'
;
import
'package:geolocator/geolocator.dart'
;
// /// Defines the main theme color.
// final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor(
// const Color.fromRGBO(48, 49, 60, 1));
//
// void main() {
// runApp(BaseflowPluginExample(
// pluginName: 'Geolocator',
// githubURL: 'https://github.com/Baseflow/flutter-geolocator',
// pubDevURL: 'https://pub.dev/packages/geolocator',
// pages: [GeolocatorWidget.createPage()],
// ));
// }
//
// /// Example [Widget] showing the functionalities of the geolocator plugin
// class GeolocatorWidget extends StatefulWidget {
// /// Utility method to create a page with the Baseflow templating.
// static ExamplePage createPage() {
// return ExamplePage(Icons.location_on, (context) => GeolocatorWidget());
// }
//
// @override
// _GeolocatorWidgetState createState() => _GeolocatorWidgetState();
// }
//
// class _GeolocatorWidgetState extends State<GeolocatorWidget> {
// final List<_PositionItem> _positionItems = <_PositionItem>[];
// StreamSubscription<Position> _positionStreamSubscription;
//
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// backgroundColor: Theme.of(context).backgroundColor,
// body: ListView.builder(
// itemCount: _positionItems.length,
// itemBuilder: (context, index) {
// final positionItem = _positionItems[index];
//
// if (positionItem.type == _PositionItemType.permission) {
// return ListTile(
// title: Text(positionItem.displayValue,
// textAlign: TextAlign.center,
// style: TextStyle(
// color: Colors.white,
// fontWeight: FontWeight.bold,
// )),
// );
// } else {
// return Card(
// child: ListTile(
// tileColor: themeMaterialColor,
// title: Text(
// positionItem.displayValue,
// style: TextStyle(color: Colors.white),
// ),
// ),
// );
// }
// },
// ),
// floatingActionButton: Stack(
// children: <Widget>[
// Positioned(
// bottom: 80.0,
// right: 10.0,
// child: FloatingActionButton.extended(
// onPressed: () async {
// await Geolocator.getLastKnownPosition().then((value) => {
// _positionItems.add(_PositionItem(
// _PositionItemType.position, value.toString()))
// });
// setState(() {});
// },
// label: Text("getLastKnownPosition"),
// ),
// ),
// Positioned(
// bottom: 10.0,
// right: 10.0,
// child: FloatingActionButton.extended(
// onPressed: () async {
// await Geolocator.getCurrentPosition().then((value) => {
// _positionItems.add(_PositionItem(
// _PositionItemType.position, value.toString()))
// });
//
// setState(
// () {},
// );
// },
// label: Text("getCurrentPosition")),
// ),
// Positioned(
// bottom: 150.0,
// right: 10.0,
// child: FloatingActionButton.extended(
// onPressed: _toggleListening,
// label: Text(() {
// if (_positionStreamSubscription == null) {
// return "getPositionStream = null";
// } else {
// return "getPositionStream = ${_positionStreamSubscription.isPaused ? "off" : "on"}";
// }
// }()),
// backgroundColor: _determineButtonColor(),
// ),
// ),
// Positioned(
// bottom: 220.0,
// right: 10.0,
// child: FloatingActionButton.extended(
// onPressed: () => setState(_positionItems.clear),
// label: Text("clear positions"),
// ),
// ),
// Positioned(
// bottom: 290.0,
// right: 10.0,
// child: FloatingActionButton.extended(
// onPressed: () async {
// await Geolocator.checkPermission().then((value) => {
// _positionItems.add(_PositionItem(
// _PositionItemType.permission, value.toString()))
// });
// setState(() {});
// },
// label: Text("getPermissionStatus"),
// ),
// ),
// ],
// ),
// );
// }
//
// bool _isListening() => !(_positionStreamSubscription == null ||
// _positionStreamSubscription.isPaused);
//
// Color _determineButtonColor() {
// return _isListening() ? Colors.green : Colors.red;
// }
//
// void _toggleListening() {
// if (_positionStreamSubscription == null) {
// final positionStream = Geolocator.getPositionStream();
// _positionStreamSubscription = positionStream.handleError((error) {
// _positionStreamSubscription.cancel();
// _positionStreamSubscription = null;
// }).listen((position) => setState(() => _positionItems.add(
// _PositionItem(_PositionItemType.position, position.toString()))));
// _positionStreamSubscription.pause();
// }
//
// setState(() {
// if (_positionStreamSubscription.isPaused) {
// _positionStreamSubscription.resume();
// } else {
// _positionStreamSubscription.pause();
// }
// });
// }
//
// @override
// void dispose() {
// if (_positionStreamSubscription != null) {
// _positionStreamSubscription.cancel();
// _positionStreamSubscription = null;
// }
//
// super.dispose();
// }
// }
//
// enum _PositionItemType {
// permission,
// position,
// }
//
// class _PositionItem {
// _PositionItem(this.type, this.displayValue);
//
// final _PositionItemType type;
// final String displayValue;
// }
\ No newline at end of file
lib/course/device/gps_tracker_service.dart
View file @
3a24c4d2
...
...
@@ -7,8 +7,8 @@ import 'package:geolocator/geolocator.dart';
import
'kalman_filter.dart'
;
class
GpsTrackerService
{
static
final
int
MIN_TIME_FOR_UPDATE_IN_S
=
2
;
static
final
int
MIN_DISTANCE_FOR_UPDATE_IN_M
=
1
;
static
const
int
MIN_TIME_FOR_UPDATE_IN_S
=
2
;
static
const
int
MIN_DISTANCE_FOR_UPDATE_IN_M
=
1
;
/* Accuracy is defined as the radius of 68% confidence in meters. */
static
const
int
MAX_ACCURACY_IN_M
=
30
;
...
...
@@ -31,13 +31,6 @@ class GpsTrackerService {
GpsTrackerService
();
// static final int SERVICE_NOTIFICATION_ID = 12345678;
// @Override
// public void onCreate() {
// super.onCreate();
// _locationListener = new InnerLocationListener();
// }
void
startGPS
()
{
if
(
_positionStreamSubscription
==
null
)
{
final
positionStream
=
Geolocator
.
getPositionStream
(
...
...
lib/course/sport_mode_course_widget.dart
View file @
3a24c4d2
...
...
@@ -4,6 +4,7 @@ import 'package:Vikazimut_flutter/map/orienteering_map.dart';
import
'package:Vikazimut_flutter/map/view/LocationLayer.dart'
;
import
'package:Vikazimut_flutter/map/view/MapView.dart'
;
import
'package:Vikazimut_flutter/result/Result.dart'
;
import
'package:Vikazimut_flutter/result/SportResultDisplayActivity.dart'
;
import
'package:flutter/material.dart'
;
import
'package:geolocator/geolocator.dart'
;
...
...
@@ -22,8 +23,7 @@ class SportModeCourseWidget extends AbstractModeCourseWidget {
@override
void
displayResult
(
int
itemIndex
)
{
print
(
"ici displayresult"
);
Navigator
.
push
(
getContext
(),
MaterialPageRoute
(
builder:
(
context
)
=>
Result
(
itemIndex
)));
Navigator
.
push
(
getContext
(),
MaterialPageRoute
(
builder:
(
context
)
=>
SportResultDisplayActivity
(
itemIndex
)));
// Intent intent = new Intent(this, SportResultDisplayActivity.class);
}
...
...
@@ -76,7 +76,7 @@ class SportModeCourseWidget extends AbstractModeCourseWidget {
// @Override
// public void onClick( DialogInterface dialog, int which ) {
// dialog.dismiss();
//
onCall
Rescu
e();
onCall
Assistanc
e
();
// }
// })
// .setNegativeButton(getString(R.string.no_aid), null);
...
...
@@ -87,42 +87,42 @@ class SportModeCourseWidget extends AbstractModeCourseWidget {
void
handleStopCourse
(
Course
course
)
{
course
.
setAssistanceCount
(
_assistanceCount
);
super
.
handleStopCourse
(
course
);
if
(
_locationNewOverlay
!=
null
)
{
_locationNewOverlay
?.
stop
();
}
//
if (_locationNewOverlay != null) {
//
_locationNewOverlay?.stop();
//
}
}
void
onCall
Rescu
e
()
{
//
MapView mapView = getMapView();
//
addLocationOverlayOnMap(mapView);
//
recenter();
void
onCall
Assistanc
e
()
{
//
MapView mapView = getMapView();
//
addLocationOverlayOnMap(mapView);
//
recenter();
}
void
addLocationOverlayOnMap
(
final
MapView
mapView
)
{
if
(
_locationNewOverlay
==
null
&&
isStarted
())
{
// _locationNewOverlay = new LocationLayer(mapView);
// mapView.addLayer(_locationNewOverlay);
// _locationNewOverlay?.start();
// final Handler handler = new Handler();
// handler.postDelayed(new Runnable() {
// @
O
verride
// public void run() {
// if (_locationNewOverlay != null) {
// if (isStarted()) {
//
_assistanceCount++;
// }
// mapView.removeLayer(_locationNewOverlay);
// _locationNewOverlay = null;
// }
// }
// }, 15000);
}
//
if (_locationNewOverlay == null && isStarted()) {
//
_locationNewOverlay = new LocationLayer(mapView);
//
mapView.addLayer(_locationNewOverlay);
//
_locationNewOverlay?.start();
//
final Handler handler = new Handler();
//
handler.postDelayed(new Runnable() {
//
@
o
verride
//
public void run() {
//
if (_locationNewOverlay != null) {
//
if (isStarted()) {
//
_
assistanceCount++;
//
}
//
mapView.removeLayer(_locationNewOverlay);
//
_locationNewOverlay = null;
//
}
//
}
//
}, 15000);
//
}
}
void
recenter
()
{
// GeodesicPoint last
Loca
tion = getLastLocation();
// if (last
Loca
tion != null) {
// getMapView().setCenter(last
Loca
tion);
// GeodesicPoint
?
last
Posi
tion = getLastLocation();
// if (last
Posi
tion != null) {
// getMapView().setCenter(last
Posi
tion);
// }
}
}
lib/course/walk_mode_course_widget.dart
View file @
3a24c4d2
...
...
@@ -6,6 +6,7 @@ import 'package:Vikazimut_flutter/map/view/FlatRouteLayer.dart';
import
'package:Vikazimut_flutter/map/view/LocationLayer.dart'
;
import
'package:Vikazimut_flutter/map/view/MapView.dart'
;
import
'package:Vikazimut_flutter/result/Result.dart'
;
import
'package:Vikazimut_flutter/result/WalkResultDisplayActivity.dart'
;
import
'package:flutter/material.dart'
;
import
'package:geolocator/geolocator.dart'
;
...
...
@@ -16,35 +17,34 @@ class WalkModeCourseWidget extends AbstractModeCourseWidget {
LocationLayer
?
_locationNewOverlay
;
WalkModeCourseWidget
(
OrienteeringMap
selectedMap
)
:
super
(
selectedMap
)
{
// setContentView(R.layout.activity_walk_course);
// super.onCreate(savedInstanceState);
setChronometerVisibility
(
false
);
// MapView mapView = getMapView();
// addRouteOverlayOnMap(mapView);
// addLocationOverlayOnMap(mapView);
MapView
?
mapView
=
getMapView
();
if
(
mapView
!=
null
)
{
addRouteOverlayOnMap
(
mapView
);
addLocationOverlayOnMap
(
mapView
);
}
}
@override
void
initializeCourseMenu
(
Menu
?
menu
,
ValidationMode
validationFormat
)
{
//
TODO: implement initializeCourseMenu
//
Nothing to do
}
@override
void
displayResult
(
int
itemIndex
)
{
Navigator
.
push
(
getContext
(),
MaterialPageRoute
(
builder:
(
context
)
=>
Result
(
itemIndex
)));
// Intent activity = new Intent(this, WalkResultDisplayActivity.class);
Navigator
.
push
(
getContext
(),
MaterialPageRoute
(
builder:
(
context
)
=>
WalkResultDisplayActivity
(
itemIndex
)));
}
@override
void
handleStartCourse
()
{
super
.
handleStartCourse
();
//
_locationNewOverlay.start();
super
.
handleStartCourse
();
_locationNewOverlay
?
.
start
();
}
@override
void
handleStopCourse
(
Course
course
)
{
super
.
handleStopCourse
(
course
);
//
_locationNewOverlay.stop();
super
.
handleStopCourse
(
course
);
_locationNewOverlay
?
.
stop
();
}
@override
...
...
@@ -58,21 +58,20 @@ class WalkModeCourseWidget extends AbstractModeCourseWidget {
}
}
void
onCallCenter
()
{
GeodesicPoint
?
lastLocation
=
getLastLocation
();
if
(
lastLocation
!=
null
)
{
//
getMapView().setCenter(lastLocation);
getMapView
()
!
.
setCenter
(
lastLocation
);
}
}
void
addLocationOverlayOnMap
(
MapView
mapView
)
{
//
_locationNewOverlay = new LocationLayer(mapView);
//
mapView.addLayer(_locationNewOverlay);
_locationNewOverlay
=
new
LocationLayer
(
mapView
);
mapView
.
addLayer
(
_locationNewOverlay
!
);
}
void
addRouteOverlayOnMap
(
MapView
mapView
)
{
//
_routeOverlay = new FlatRouteLayer(mapView);
//
mapView.addLayer(_routeOverlay);
_routeOverlay
=
new
FlatRouteLayer
(
mapView
);
mapView
.
addLayer
(
_routeOverlay
!
);
}
}
lib/history/history_item.dart
View file @
3a24c4d2
import
'package:Vikazimut_flutter/database/course_result_entity.dart'
;
import
'package:Vikazimut_flutter/result/Result.dart'
;
import
'package:Vikazimut_flutter/result/SportResultDisplayActivity.dart'
;
import
'package:Vikazimut_flutter/translations.dart'
;
import
'package:flutter/material.dart'
;
...
...
@@ -26,7 +27,7 @@ class HistoryItem extends StatelessWidget {
onPressed:
()
{
print
(
"valeur id =
${item.totalTime}
"
);
print
(
"valeur id =
${item.id}
"
);
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
Result
(
item
.
id
!)));
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
Sport
Result
DisplayActivity
(
item
.
id
!)));
},
child:
Row
(
children:
<
Widget
>[
...
...
lib/map/LargeBitmapFactory.dart
deleted
100644 → 0
View file @
f3f0db97
//package map; //TODO
///**
// * Loads a bitmap image into memory.
// */
//final class LargeBitmapFactory {
// public static final long MAXIMUM_BITMAP_SIZE = 5000L * 5000L;
//
// private LargeBitmapFactory() {
// }
//
// static Bitmap decodeSampledBitmapFromResource( String pathName, int requiredWidth, int requiredHeight ) {
// final BitmapFactory.Options options = new BitmapFactory.Options();
// options.inJustDecodeBounds = true;
// BitmapFactory.decodeFile(pathName, options);
// options.inSampleSize = calculateTheLargestInSampleSizeValueThatIsAPowerOf2(options.outWidth, options.outHeight, requiredWidth, requiredHeight);
// options.inJustDecodeBounds = false;
// return BitmapFactory.decodeFile(pathName, options);
// }
//
// static int calculateTheLargestInSampleSizeValueThatIsAPowerOf2( int imageWidth, int imageHeight, int requiredWidth, int requiredHeight ) {
// int imageSize = Math.max(imageWidth, imageHeight);
// int requiredSize = Math.max(requiredWidth, requiredHeight);
// double zoom = imageSize / (double) requiredSize;
// double requiredMaxZoom = zoom * (2.0 / MAX_SCALE);
// if (requiredMaxZoom < 1.0) {
// requiredMaxZoom = 1.0;
// }
// int power2 = (int) Math.round(Math.log(requiredMaxZoom) / Math.log(2));
// int scale = (int) Math.pow(2, power2);
// int currentWidth = imageWidth / scale;
// while (currentWidth * (imageHeight / scale) > MAXIMUM_BITMAP_SIZE) {
// scale *= 2;
// }
// return scale;
// }
//}
lib/map/geodesic_point.dart
View file @
3a24c4d2
...
...
@@ -32,12 +32,6 @@ class GeodesicPoint {
_timeInMillis
=
timeInMillis
;
}
// @NonNull
// @Override
// public String toString() {
// return _latitude + "," + _longitude + ", " + _timeInMillis + ", " + _altitude;
// }
//
// @Override
// public boolean equals( Object o ) {
// if (this == o) {
...
...
lib/map/view/AbstractRouteLayer.dart
View file @
3a24c4d2
import
'dart:collection'
;
import
'package:Vikazimut_flutter/map/geodesic_point.dart'
;
import
'package:Vikazimut_flutter/map/view/MapView.dart'
;
import
'package:flutter/material.dart'
;
import
'Layer.dart'
;
abstract
class
AbstractRouteLayer
implements
Layer
{
//
final MapView _mapView;
final
MapView
_mapView
;
late
List
<
GeodesicPoint
>
_route
;
late
GeodesicPoint
_lastLocation
;
//
// AbstractRouteLayer( MapView mapView ) {
// _mapView = mapView;
// }
//
AbstractRouteLayer
(
MapView
mapView
)
:
_mapView
=
mapView
;
void
drawRoute
(
List
<
GeodesicPoint
>
route
,
GeodesicPoint
lastLocation
)
{
_route
=
route
;
_lastLocation
=
lastLocation
;
//
_mapView.invalidate();
_mapView
.
invalidate
();
}
@override
void
draw
(
Canvas
canvas
)
{
//
if (_route
== null || _route.size()
< 2) {
//
return;
//
}
//
drawPolyLine(canvas, _route, _lastLocation);
if
(
_route
.
length
<
2
)
{
return
;
}
drawPolyLine
(
canvas
,
_route
,
_lastLocation
);
}
//
// abstract void drawPolyLine( Canvas canvas, List<GeodesicPoint> route, GeodesicPoint lastLocation );
//
// Point convertGeodesicPointToMapPoint( GeodesicPoint currentPoint ) {
// return _mapView.convertGeoPointIntoMapCoordinates(currentPoint.getLatitude(), currentPoint.getLongitude());
// }
// @override
// void onResume() {
// }
//
// @override
// void onPause() {
// }
void
drawPolyLine
(
Canvas
canvas
,
List
<
GeodesicPoint
>
route
,
GeodesicPoint
lastLocation
);
Offset
convertGeodesicPointToMapPoint
(
GeodesicPoint
currentPoint
)
{
return
_mapView
.
convertGeoPointIntoMapCoordinates
(
currentPoint
.
getLatitude
(),
currentPoint
.
getLongitude
());
}
@override
void
onResume
()
{}
@override
void
onPause
()
{}
@override
void
stop
()
{}
...
...
lib/map/view/ColoredRouteLayer.dart
View file @
3a24c4d2
import
'package:Vikazimut_flutter/map/geodesic_point.dart'
;