i made an app which uses the geolocator package to check for GPS and get the location of the user, and i use the provider package to handle the state. The problem is, when the GPS is switched off, a red screen appears that says the latitude was null, i would like to implement a screen to tell the user to switch on the GPS, and update the location accordingly.
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:geolocator/geolocator.dart';
import 'package:latlong/latlong.dart';
class MapState with ChangeNotifier {
bool locationServiceActive = true;
MapController _mapController;
MapController get mapController => _mapController;
static var _initialPosition;
var _lastPosition = _initialPosition;
LatLng get initialPosition => _initialPosition;
LatLng get lastPosition => _lastPosition;
MapState(){
checkGPS();
_getUserLocation();
}
checkGPS() async{
bool conn = await Geolocator().isLocationServiceEnabled();
if(conn == false){
locationServiceActive = false;
} else {
locationServiceActive = true;
}
notifyListeners();
}
void _getUserLocation() async{
Position position = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
print("/////////////////////////////////////////////////////////////////////////////////position");
print(position);
_initialPosition = LatLng(position.latitude, position.longitude);
notifyListeners();
}
}
update:-
i changed my _getUserLocation function to a stream, which works much better if the user switched on or off the gps (and it uses the last known location if the gps is off)... but it doesn't print the statement in the terminal if the position is null which is weird, only when there is lat and lng!!!
here is the modification i made...
void _getUserLocation() async{
Position position = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
var geolocator = Geolocator();
var locationOptions = LocationOptions(accuracy: LocationAccuracy.high, distanceFilter: 10);
StreamSubscription<Position> positionStream = geolocator.getPositionStream(locationOptions).listen(
(Position position) {
print("/////////////////////////////////////////////////////////////////////////// position");
print(position == null ? 'Unknown' : position.latitude.toString() + ', ' + position.longitude.toString());
});
_initialPosition = LatLng(position.latitude, position.longitude);
notifyListeners();
}
If you want to notify the user about the GPS, you can use something like this
#override
void initState() {
super.initState();
initPlatformState();
location.onLocationChanged.listen((result) {
currentLocation = result;
// your code
});
});
}
void initPlatformState() async {
LocationData currentLocation;
try {
currentLocation = await location.getLocation();
error = "";
} on PlatformException catch (e) {
if (e.code == 'PERMISSION_DENIED')
error = 'Permission Denied';
else if (e.code == 'PERMISSION_DENIED_NEVER_ASK')
error =
'Permission denied - please ask the user to enable it from the app settings';
currentLocation = null;
}
setState(() {
currentLocation = currentLocation;
});
}
Here, you are listening to the location stream if enabled. In case it is not then it throws an error. The package being used here is location
Related
Here is the code , as I mentioned most of the time it returns nothing, but once it has returned null, the permission is enabled and nothing wrong with it.
class _LoadingScreenState extends State<LoadingScreen> {
double latitude;
double longitude ;
#override
void initState() {
getLocation();
}
void getLocation() async{
Location location = new Location();
await location.getCurrentLocation();
latitude = (location.latitude);
longitude= (location.longitude);
getData();
}
void getData() async{
http.Response response = await http.get(Uri.parse('https://samples.openweathermap.org/data/2.5/weather?lat=$latitude&lon=$longitude &appid= $apiKey'));
if(response.statusCode == 200){
String data = response.body ;
var decodedData = jsonDecode(data);
// var longitude = decodedData["coord"]["lon"];
var weatherDescription = decodedData["weather"][0]["description"];
int id = decodedData["weather"][0]["id"];
double temp = decodedData["main"]["temp"];
String city = decodedData["name"];
print("hi");
print(id);
print(temp);
print(city);
print(latitude);
print(longitude);
}
else {
print(response.statusCode);
}
}
and here is the location class , the permission is enabled and nothing wrong with it.
import 'package:geolocator/geolocator.dart';
import 'package:flutter/material.dart';
class Location{
double latitude ;
double longitude ;
Future <void> getCurrentLocation() async{
// bool servicestatus = await Geolocator.isLocationServiceEnabled();
//
// servicestatus ? print("GPS service is enabled"): print("GPS service is disabled.");
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.low);
latitude = position.latitude;
longitude = position.longitude;
}
catch (exception){
print(exception);
}
}
}
As the title says, I'm not being able to call Geolocator.getCurrentPosition() more than once. I have logged the issue with the package team, but I'm wondering if it's something I'm doing wrong.
Future getLocation() async {
var currentLocation;
try {
currentLocation = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.medium,
);
} catch (e) {
currentLocation = null;
}
return currentLocation;
}
void getLocation1() async {
var location = await getLocation();
print(location);
print("First");
}
void getLocation2() async {
var location = await getLocation();
print(location);
print("Second");
}
#override
void initState() {
super.initState();
getLocation1();
getLocation2();
}
The console prints "Second" but not "First". When I remove the getLocation2() call, the console prints "First". They are not able to be called in the same frame, and I don't know why this changed. Am I doing anything wrong?
I am assuming you are experiencing this behavior on iOS or macOS. The reason is that Apple doesn't allow multiple active calls to the location stream. What happens is that the getLocation2 method closes the active request currently running by the getLocation1 call.
The easiest way to workaround this, is to return the same Future if the first request has not been finished yet:
late Future<Position> _positionFuture;
Future<Position> getLocation() async {
if (_positionFuture != null && !_positionFuture!.isCompleted) {
return _positionFuture;
}
_positionFuture = Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.medium,
);
return _positionFuture;
}
void getLocation1() async {
var location = await getLocation();
print(location);
print("First");
}
void getLocation2() async {
var location = await getLocation();
print(location);
print("Second");
}
#override
void initState() {
super.initState();
getLocation1();
getLocation2();
}
How can I get the user's GPS (current address) on launch and then use that throughout the app where needed? I'd like to be able to use both options of the coordinates and written address being output. I'd like to have it be string data instead of text widget, so that then I can use it in other widgets where appropriate. Here's what I have so far, but I can't figure out how to incorporate this into my app properly and extract and implement that data.
Oh, also how to make it update periodically for when then user changes locations?
Any ideas?
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
class FindMe extends StatefulWidget {
initState() {
FindMe();
}
#override
_FindMeState createState() => _FindMeState();
}
class _FindMeState extends State<FindMe> {
String currentAddress = '';
late Position currentposition;
Future<String> _determinePosition() async {
bool serviceEnabled;
LocationPermission permission;
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
Fluttertoast.showToast(msg: 'Please enable Your Location Service');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
Fluttertoast.showToast(msg: 'Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
Fluttertoast.showToast(msg:'Location permissions are permanently denied, we cannot request permissions.');
}
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.bestForNavigation);
try {
List<Placemark> placemarks = await placemarkFromCoordinates(position.latitude, position.longitude);
Placemark place = placemarks[0];
setState(() {
currentposition = position;
currentAddress = "${place.locality}, ${place.postalCode}, ${place.country}";
});
} catch (e) {
print(e);
}
return currentAddress;
}
#override
Widget build(BuildContext context) {
_determinePosition();
return Text(
currentAddress,
style: const TextStyle(color: Colors.black),
);
}
}
You could use state-management solutions like blocor riverpod to do this.
With Riverpod one solution could look like this:
class LocationService {
Future<String> determinePosition(){...}
}
...
final locationServiceProvider = Provider((ref) => LocationService());
final positionProvider = FutureProvider((ref) => ref.watch(locationServiceProvider).determinePosition);
...
// in a consumer widget
build(BuildContext context, WidgetRef ref){
final position = ref.watch(positionProvider);
// do something with the position
}
You can then access the value in your position provider from different parts of your app.
I need to get the city name from Longitude and Latitude.
I do not found a single package to do that, so I use location package to get Long and Lat and used geocoder to get the city name.
But I keep have this error and have no result :
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: PlatformException(failed, Failed, null, null)
and this one after it on the console: < asynchronous suspension >
Here is my code :
class _ProfileScreenState extends State<ExploreScreen> {
dynamic currentLocation;
double userLongitude;
double userLatitude;
Coordinates coordinates;
var addresses;
var first;
#override
initState() {
super.initState();
_getCurrentLongAndLat();
_getCurrentPosition(userLatitude, userLatitude);
}
Future _getCurrentLongAndLat() async {
currentLocation = LocationData;
var error;
var location = new Location();
try {
currentLocation = await location.getLocation();
userLatitude = currentLocation.latitude;
userLongitude = currentLocation.longitude;
print('$userLatitude $userLatitude');
} on PlatformException catch (e) {
if (e.code == 'PERMISSION_DENIED') {
error = 'Permission denied';
}
currentLocation = null;
}
}
Future _getCurrentPosition(double long, double lat) async {
coordinates = new Coordinates(userLatitude, userLongitude);
addresses = await Geocoder.local.findAddressesFromCoordinates(coordinates);
print(addresses.first);
}
}
I realized flutter packages geolocator and location conflict with each other sometimes.
Try using geolocator to get your current position:
Future _getCurrentPosition() async {
Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high).then((Position position) {
setState(() {
_currentPosition = position;
userLongitude = position.longitude;
userLatitude = position.latitude;
});
});
}
It is a Future, so you can use await to really wait for results and after that call the getAddress function with the userLat and userLng.
I have old flutter project, I added web support to it, Now ,I am trying to get my Location in flutter web , So i added location to my page.
this is my code:
#override
void initState() {
super.initState();
_getLocation();
}
Future _getLocation() async {
Location location = new Location();
var _permissionGranted = await location.hasPermission();
_serviceEnabled = await location.serviceEnabled();
if (_permissionGranted != PermissionStatus.granted || !_serviceEnabled) {
_permissionGranted = await location.requestPermission();
_serviceEnabled = await location.requestService();
} else {
print("-----> $_serviceEnabled");
setState(() {
_serviceEnabled = true;
_loading = false;
});
}
try {
final LocationData currentPosition = await location.getLocation();
setState(() {
longitude = currentPosition.longitude.toString();
latitude = currentPosition.latitude.toString();
print(
'${widget.url}?BranchName=&latitude=${latitude}&longitude=${longitude}');
_loading = false;
});
} on PlatformException catch (err) {
_loading = false;
print("-----> ${err.code}");
}
}
After getting Location permission by chrome,
Nothing happening!
In vsCode console i just got this error:
Error: [object GeolocationPositionError]
at Object.createErrorWithStack (http://localhost:43705/dart_sdk.js:4351:12)
at Object._rethrow (http://localhost:43705/dart_sdk.js:37962:16)
at async._AsyncCallbackEntry.new.callback (http://localhost:43705/dart_sdk.js:37956:13)
at Object._microtaskLoop (http://localhost:43705/dart_sdk.js:37788:13)
at _startMicrotaskLoop (http://localhost:43705/dart_sdk.js:37794:13)
at http://localhost:43705/dart_sdk.js:33303:9
**USING #JS('navigator.geolocation')
I also try this, but never success method called and nothing heppen.
This works now(all platforms including web), June 2021, with the Location package.
final Location location = new Location();
_locationData = await location.getLocation();
print(_locationData.latitude);
See full details here:
pub.dev/packages/location
Dart currently has an issue with the Geolocation API. Consider writing an interop library or using mine. Link below Geolocation PolyFill