#android #flutter #dart #geolocation #flutter-dependencies
#Android #flutter #dart #геолокация #flutter-зависимости
Вопрос:
У меня есть приложение navigator, которое будет определять текущее местоположение пользователя и сохранять историю масштабирования в базе данных. При перезапуске приложения я получу историю последнего масштабирования и покажу текущее местоположение пользователя с сохраненным масштабированием. Вот пример работы с эмулятором:
Android 9
API level 28
compileSdkVersion 30
minSdkVersion 16
targetSdkVersion 29
Код
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/great_places.dart';
import 'package:yandex_mapkit/yandex_mapkit.dart';
import 'package:geolocator/geolocator.dart';
import '../helpers/db_helper.dart';
class PlacesListScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return _Map();
}
}
class _Map extends StatefulWidget {
@override
_MapState createState() => _MapState();
}
class _MapState extends State<_Map> {
YandexMapController controller;
Placemark _lastMarkedPoint;
Placemark _lastMarkedUserPoint;
double _zoom;
StreamSubscription _locationSubscription;
Position _currentLocation;
Timer zoomDeleteTimer;
Timer zoomTimer;
Timer cameraTimer;
Future<Position> _determineLocation() async {
bool serviceEnabled;
LocationPermission permission;
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
return Future.error('Location services are disabled.');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.deniedForever) {
return Future.error(
'Location permissions are permantly denied, we cannot request permissions.');
}
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission != LocationPermission.whileInUse amp;amp;
permission != LocationPermission.always) {
return Future.error(
'Location permissions are denied (actual value: $permission).');
}
}
return await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
);
}
_listenLocation() {
_locationSubscription = Geolocator.getPositionStream(
desiredAccuracy: LocationAccuracy.high,
distanceFilter: 1,
).listen((Position position) async {
if (position != null) {
if (controller != null) {
print("SET USER POSITION");
controller.enableCameraTracking(
null,
cameraPositionChanged,
);
}
_setUserLocation(
Point(
latitude: position.latitude,
longitude: position.longitude,
),
);
print("Updated Position: " position.toString());
}
});
}
Future<void> fetchZoomHistory() async {
print("ZOOM HISTORY DATABASE");
final zoomList = await DBHelper.getData('zoom_history');
print(zoomList);
if (zoomList != null amp;amp; zoomList.length > 0) {
setState(() {
_zoom = double.parse(zoomList[0]['zoom']);
});
} else {
setState(() {
_zoom = 12.4;
});
}
}
Future<void> clearZoomHistory() async {
await DBHelper.delete('zoom_history');
print("ZOOM HISTORY DELETED");
}
@override
void initState() {
super.initState();
_determineLocation().then((value) {
setState(() {
_currentLocation = value;
});
});
_listenLocation();
fetchZoomHistory();
}
Future<void> _setUserLocation(Point point, [setMark = true]) async {
await controller.enableCameraTracking(
null,
cameraPositionChanged,
);
await controller.removePlacemark(_lastMarkedUserPoint);
if (setMark == true) {
var placemark = Placemark(
point: point,
opacity: 0.8,
iconName: 'lib/assets/arrow_blue.png',
);
_lastMarkedUserPoint = placemark;
await controller.addPlacemark(placemark);
}
await controller.move(
point: point,
zoom: _zoom,
animation: const MapAnimation(smooth: true),
);
}
Future<void> cameraPositionChanged(dynamic arguments) async {
if (zoomTimer != null) zoomTimer.cancel();
var zoom = arguments['zoom'];
if (_zoom != zoom) {
_zoom = zoom;
zoomTimer =
Timer.periodic(const Duration(milliseconds: 2000), (zoomTimer) async {
await clearZoomHistory();
print(zoom);
DBHelper.insert('zoom_history', {
'zoom': zoom,
});
zoomTimer.cancel();
});
}
}
void _setPlacesMark(YandexMapController controller, places) async {
for (var i = 0; i < places.items.length; i ) {
var point = Point(
latitude: places.items[i].latitude,
longitude: places.items[i].longitude,
);
var placemark = Placemark(
point: point,
opacity: 0.8,
iconName: 'lib/assets/tire4.png',
);
await controller.addPlacemark(placemark);
}
}
Future<void> addPlaceMark(Point point, YandexMapController controller) async {
if (_lastMarkedPoint != null) {
await controller.removePlacemark(_lastMarkedPoint);
}
var placemark = Placemark(
point: point,
opacity: 0.7,
iconName: 'lib/assets/place_red2.png',
);
_lastMarkedPoint = placemark;
await controller.addPlacemark(placemark);
}
static const Point _point = Point(latitude: 59.939095, longitude: 30.315868);
@override
void dispose() {
if (_locationSubscription != null) {
_locationSubscription.cancel();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Navigator'),
),
body: FutureBuilder(
future: Provider.of<GreatPlaces>(context, listen: false)
.fetchAndSetPlaces(),
builder: (ctx, snapshot) => snapshot.connectionState ==
ConnectionState.waiting
? Center(
child: CircularProgressIndicator(),
)
: Consumer<GreatPlaces>(
child: Center(
child: const Text('Places got not yet'),
),
builder: (ctx, greatPlaces, ch) => greatPlaces.items.length <= 0
? YandexMap(
onMapCreated:
(YandexMapController yandexMapController) async {
controller = yandexMapController;
Point setPoint;
if (_currentLocation != null) {
setPoint = Point(
latitude: _currentLocation.latitude,
longitude: _currentLocation.longitude,
);
await _setUserLocation(setPoint);
} else {
await _setUserLocation(setPoint, false);
}
},
onMapTap: (Point point) async {
await addPlaceMark(point, controller);
},
)
: YandexMap(
onMapCreated:
(YandexMapController yandexMapController) async {
controller = yandexMapController;
Point setPoint;
if (_currentLocation != null) {
setPoint = Point(
latitude: _currentLocation.latitude,
longitude: _currentLocation.longitude,
);
await _setUserLocation(setPoint);
} else {
await _setUserLocation(setPoint, false);
}
_setPlacesMark(controller, greatPlaces);
},
onMapTap: (Point point) async {
await addPlaceMark(point, controller);
},
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FloatingActionButton(
onPressed: () async {
await controller.zoomIn();
},
child: Icon(Icons.add, color: Colors.white),
backgroundColor: Colors.green,
heroTag: 'mapZoomIn',
),
FloatingActionButton(
onPressed: () async {
await controller.zoomOut();
},
child: Icon(Icons.remove, color: Colors.white),
backgroundColor: Colors.green,
heroTag: 'mapZoomOut',
),
FloatingActionButton(
onPressed: () {
_determineLocation().then((value) {
_currentLocation = value;
_setUserLocation(Point(
latitude: value.latitude,
longitude: value.longitude,
));
});
},
child: Icon(Icons.place, color: Colors.white),
backgroundColor: Colors.green,
heroTag: 'showUserLocation',
),
FloatingActionButton(
onPressed: () async {
await controller.move(
point: _point,
zoom: _zoom,
);
},
child: Icon(Icons.home, color: Colors.white),
backgroundColor: Colors.green,
heroTag: 'mapGoToHome',
),
],
),
);
}
}
Результат
<blockquote class="imgur-embed-pub" lang="en" data-id="lUY0L7h" ><a href="//imgur.com/lUY0L7h">Navigator App</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
Почему оно не работает на реальном устройстве правильно?
Загрузите APK здесь для тестирования
Комментарии:
1. Что происходит на реальном устройстве?
2. Местоположение и GPS включены на реальном устройстве??
3. На реальном устройстве не обнаружено местоположение, также кнопки местоположение пользователя и кнопка home. История масштабирования также не сохраняется в моем случае. @SergeyGlotov
4. Местоположение и GPS включены @MRazaImtiaz