Flutter - <asynchronous suspension> with geocoder package - flutter

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.

Related

Position.longitude or latitude returns null and most of the time returns nothing

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);
}
}
}

GPS off message, and continous location update flutter

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

How to get latitude and longitude in flutter

I can figure out how to get the user's latitude and longitude together, but need to get them individually to utilise the Geolocator().distanceBetween function from the Geolocator package. My code below keeps getting the error:
Unhandled Exception: NoSuchMethodError: The getter 'latitude' was called on null.
Receiver: null
Tried calling: latitude
Future<Position> getLocation() async {
var currentLocation;
try {
currentLocation = await geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best);
} catch (e) {
currentLocation = null;
}
return currentLocation;
}
void calculateDistance() async {
getLocation().then((position) {
userLocation = position;
});
final double myPositionLat = userLocation.latitude;
final double myPositionLong = userLocation.longitude;
final double TPLat = 51.5148731;
final double TPLong = -0.1923663;
final distanceInMetres = await Geolocator().distanceBetween(myPositionLat, myPositionLong, TPLat, TPLong)/1000;
print(distanceInMetres);
}
Try this :
void calculateDistance() async {
getLocation().then((position) {
userLocation = position;
final double myPositionLat = userLocation.latitude;
final double myPositionLong = userLocation.longitude;
final double TPLat = 51.5148731;
final double TPLong = -0.1923663;
final distanceInMetres = await Geolocator().distanceBetween(myPositionLat, myPositionLong, TPLat, TPLong)/1000;
print(distanceInMetres);
});
}
or another way of doing this is :
void calculateDistance() async {
userLocation = await getLocation();
final double myPositionLat = userLocation.latitude;
final double myPositionLong = userLocation.longitude;
final double TPLat = 51.5148731;
final double TPLong = -0.1923663;
final distanceInMetres = await Geolocator().distanceBetween(myPositionLat, myPositionLong, TPLat, TPLong)/1000;
print(distanceInMetres);
}

Flutter - Get geocode address from coordinates

I've implemented a reliable way of getting user lat,long coordinates in an app I'm creating, but can't seem to turn these coordinates into a placemark.
I'd also like to figure out what I need to use to print this data.
This is what I'm trying to get this data with:
List<Placemark> place = [];
void _getPlace() async {
List<Placemark> newPlace = await _geolocator.placemarkFromCoordinates(_position.latitude, _position.longitude);
print(newPlace);
setState(() {
place = newPlace;
});
}
Thanks
Edit:
After CopsOnRoad's response, I'm getting this error:
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception:
NoSuchMethodError: The method 'placemarkFromCoordinates' was called on null.
Receiver: null
Tried calling: placemarkFromCoordinates(51.4998, -0.129)
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
#1 _NearbyPageState._getPlace
package:tr/pages/nearby.dart:128
<asynchronous suspension>
#2 _NearbyPageState._controlCard.<anonymous closure>
package:tr/pages/nearby.dart:629
#3 GestureRecognizer.invokeCallback
package:flutter/…/gestures/recognizer.dart:182
#4 TapGestureRecognizer._checkUp
package:flutter/…/gestures/tap.dart:365
#5 TapGestureRecognizer.acceptGesture
package:flutter/…/gestures/tap.dart:312
#6 GestureArenaManager.sweep
package:flutter/…/gestures/arena.dart:156
#7 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent
package:flutter/…/gestures/binding.dart:222
#8 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (p<…>
Update:
Use geocoding
import 'package:geocoding/geocoding.dart';
List<Placemark> placemarks = await placemarkFromCoordinates(52.2165157, 6.9437819);
Old solution:
You are already there, extra stuff that you need is:
String _address = ""; // create this variable
void _getPlace() async {
List<Placemark> newPlace = await _geolocator.placemarkFromCoordinates(_position.latitude, _position.longitude);
// this is all you need
Placemark placeMark = newPlace[0];
String name = placeMark.name;
String subLocality = placeMark.subLocality;
String locality = placeMark.locality;
String administrativeArea = placeMark.administrativeArea;
String postalCode = placeMark.postalCode;
String country = placeMark.country;
String address = "${name}, ${subLocality}, ${locality}, ${administrativeArea} ${postalCode}, ${country}";
print(address);
setState(() {
_address = address; // update _address
});
}
Placemark has been removed from geolocator starting from version 6.0.0 and moved to geocoding.
Starting from version 6.0.0 the geocoding features (placemarkFromAddress and placemarkFromCoordinates) are no longer part of the geolocator plugin. We have moved these features to their own plugin: geocoding. This new plugin is an improved version of the old methods.
To translate latitude and longitude into an address with geocoding use
List<Placemark> placemarks = await placemarkFromCoordinates(52.2165157, 6.9437819);
Use pub.dev flutter_geocoding
https://pub.dev/packages/flutter_geocoding
OR
I have used swift 'GMSGeocoder' and java 'android.location.Geocoder' and applied it to flutter.I think it is more efficient than the library Geocode in pub.dev.
My example code
Geocode library java and swift add by yourself
java
#Override
public void configureFlutterEngine(#NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), "samples.flutter.dev/latlng")
.setMethodCallHandler(
(call, result) -> {
double lat = call.argument("lat");
double lng = call.argument("lng");
result.success("return value lat and lng");
}
);
}
swift
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/latlng",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: #escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "latlng" else {
result(FlutterMethodNotImplemented)
return
}
self?.latlng(call,result: result)
})
GMSServices.provideAPIKey("")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func latlng(_ call: FlutterMethodCall,result:FlutterResult) {
if let args = call.arguments as? Dictionary<String, Any>,
let lat = args["lat"] as? Double ,let lng = args["lng"] as? Double {
result("return latlng result" )
} else {
result(FlutterError.init(code: "bad args", message: nil, details: nil))
}
}
flutter
Future<void> _getBatteryLevel(double a, double b) async {
String latlng;
try {
final String result = await const MethodChannel('samples.flutter.dev/latlng').invokeMethod(
'latlng', <String, dynamic>{"lat": a, "lng": b});
latlng = result;
} on PlatformException catch (e) {
latlng = "Failed to get latlng level: '${e.message}'.";
}
}
first, you have include lib -geolocator: ^3.0.1 in pubspec.yaml
///Get current location
Geolocator _geolocator = Geolocator();
String latitude = "";
String longitude = "";
String address = "";
Try this solution -
///Call this function
_fetchLocation() async {
Position position = await _geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best);///Here you have choose level of distance
latitude = position.latitude.toString() ?? '';
longitude = position.longitude.toString() ?? '';
var placemarks = await _geolocator.placemarkFromCoordinates(position.latitude, position.longitude);
address ='${placemarks.first.name.isNotEmpty ? placemarks.first.name + ', ' : ''}${placemarks.first.thoroughfare.isNotEmpty ? placemarks.first.thoroughfare + ', ' : ''}${placemarks.first.subLocality.isNotEmpty ? placemarks.first.subLocality+ ', ' : ''}${placemarks.first.locality.isNotEmpty ? placemarks.first.locality+ ', ' : ''}${placemarks.first.subAdministrativeArea.isNotEmpty ? placemarks.first.subAdministrativeArea + ', ' : ''}${placemarks.first.postalCode.isNotEmpty ? placemarks.first.postalCode + ', ' : ''}${placemarks.first.administrativeArea.isNotEmpty ? placemarks.first.administrativeArea : ''}';
print("latitude"+latitude);
print("longitude"+longitude);
print("adreess"+address);
}
try {
await Geolocator()
.placemarkFromCoordinates(value[0], value[1])
.then((result) {
Placemark placeMark = result[0];
String name = placeMark.name;
String subLocality = placeMark.subLocality;
String locality = placeMark.locality;
String administrativeArea = placeMark.administrativeArea;
String postalCode = placeMark.postalCode;
String country = placeMark.country;
String address =
"${name}, ${subLocality}, ${locality}, ${administrativeArea} ${postalCode}, ${country}";
print(address);
});
} on PlatformException catch (e) {
print(e);
}
With Geolocator Plugin new version (from version 6.0.0). Geocoding features (placemarkFromAddress and placemarkFromCoordinates) are no longer part of the geolocator plugin. This method have moved these features to their own plugin: geocoding
Future getLatAndlong() async{
cl = await Geolocator.getCurrentPosition().then((value)=>value);
lat = cl.latitude;
long = cl.longitude;
_kGooglePlex = CameraPosition(
target: LatLng(lat,long),
zoom:14
);
List<Placemark> placemarks = await placemarkFromCoordinates(
lat, long);
print("country"+placemarks[0].country!);
print("area"+placemarks[0].administrativeArea!);
print("locality"+placemarks[0].locality!);
print("sublocality"+placemarks[0].subLocality!);
print("postlocality"+placemarks[0].postalCode!);
print("street"+placemarks[0].street!);
setState(() {
countrycurrent = placemarks[0].country!;
localcurrent = placemarks[0].administrativeArea!;
madinacurrent = placemarks[0].subLocality!;
curren=countrycurrent+","+localcurrent+","+madinacurrent;
});
mymarker.add(
Marker(
infoWindow: InfoWindow(
title: placemarks[0].country! + "," +
placemarks[0].administrativeArea! +
"," + placemarks[0].locality!
),
draggable: true,
icon:
BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueOrange),
markerId: MarkerId("4"),
position: LatLng(lat, long)),
);}

NoSuchMethodError the method was called on Null

in this code below WeatherModel tried to get current location of android phone,
my problem here is once I start runing it show NoSuchMethod Found, and it says reciever is null,
as I tried a lot of debugging just to see where is my problem.
I now understand that my problem is when I create instance of Location() in WeatherModel, longitude and latitude are null, it never gets value and I dont know why...
Sorry for my bad english :(
const apiKey = 'e3653190f2b1d4803287b3074ecfe618';
const apiWeatherURL = 'https://api.openweathermap.org/data/2.5/weather';
class WeatherModel {
Future<dynamic> getLocationWeather() async {
Location location = Location();
NetworkHelper networkHelper = NetworkHelper(
'https://api.openweathermap.org/data/2.5/weather?lat=${location.latitude}&lon=${location.longitude}&appid=$apiKey');
var weatherData = networkHelper.getData();
return weatherData;
}
}
.....
class Location {
double latitude;
double longitude;
Future<void> getCurrentLocation() async {
try {
Position _position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
longitude = _position.longitude;
print(longitude);
latitude = _position.latitude;
print(latitude);
} catch (e) {
print(e);
}
}
}
.........
class NetworkHelper {
NetworkHelper(this.url);
final url;
Future getData() async {
http.Response response = await http.get(url);
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
print(" Sarkawtua $data");
return data;
} else
print("Error ${response.statusCode} keshay Internet");
}
}
Because you instance fields are not updated, so they are null. You have method for getting current location but it's not fired in getLocationWeather.
Future<dynamic> getLocationWeather() async {
Location location = Location();
await location.getCurrentLocation();
NetworkHelper networkHelper = NetworkHelper(
'https://api.openweathermap.org/data/2.5/weather?lat=${location.latitude}&lon=${location.longitude}&appid=$apiKey');
var weatherData = await networkHelper.getData();
return weatherData;
}
Edit: You also must await networkHelper.getData() method to get not Future Object.