DEV Community

Cover image for Flutter Web and Location
aseem wangoo
aseem wangoo

Posted on • Edited on

Flutter Web and Location

In case it helped :)
Pass Me A Coffee!!

Begin…

We will cover two points in this article…

  1. Detect user’s location using Mozilla Geolocation
  2. Calling location API for getting location

Overview of Mozilla Geolocation…

Article here: https://flatteredwithflutter.com/detect-user-location-in-flutter-web/

As per the documentation here,

The Geolocation API allows the user to provide their location to web applications if they so desire. For privacy reasons, the user is asked for permission to report location information.

This api can be accessed by calling navigator.geolocation After calling, it causes the user’s browser to ask them for permission to access their location data

Alt Text

After accepting the request, the browser will use the best available functionality on the device to get the location (for example, GPS). Now, we can access the location information via Geolocation.getCurrentPosition()

If the location retrieval is successful, the callback executes with a GeolocationPosition object 


Flutter Web and Mozilla Geolocation…

Time to call javascript from Flutter Web..

Step 1 : Importing JS package..

Add the following to your pubspec.yaml:

dependencies:  js: ^0.6.0

Step 2 : (Create the helper file)


Lets create a separate helper file called loc.dart We know that our geolocation is present inside navigator.geolocation (refer explanation above)..

For calling any JS library, we make use of @JS('YOUR LIBRARY') from the js package

@js
('navigator.geolocation')
library jslocation; // YOU CAN NAME WHATEVER YOU WANT

Here, navigator.geolocation is the library we want to invoke..The second line, library jslocation (you can name it whatever you want), in my case I named it jslocation …


Next, we know for accessing geolocation we need to invoke Geolocation.getCurrentPosition() (refer explanation above). For calling getCurrentPosition function, we again make use of js packageas

@js
('getCurrentPosition') //Geolocation API's getCurrentPosition

external void getCurrentPosition(Function success(GeolocationPosition pos));

In the first line, we invoke the getCurrentPosition. The second line, is the function definition, which gets called from dart side….

Note : Try to keep the JS function and the dart function names consistent, in our case it’s getCurrentPosition

Now, the geolocation API returns a callback for success, which we want to capture in dart side, hence we pass in a callback fxn to our dart function…

Function success(GeolocationPosition pos)

Step 3 : Define the Custom object (GeolocationPosition)

In order to pass or fetch a custom class from a JS, we need to define it using @JS() and @anonymous tags from js package

As per the docs, @anonymous is

A metadata annotation that indicates that a @js annotated class is structural and does not have a known JavaScript prototype.

@js
()
@anonymous
class GeolocationPosition {

  external factory GeolocationPosition({GeolocationCoordinates coords});

external GeolocationCoordinates get coords;
}

We use factory constructors for our class as they desugar to create JavaScript object literals with name-value pairs…

On the similar lines, we create GeolocationCoordinates,

@js
()
@anonymous
class GeolocationCoordinates {
  external factory GeolocationCoordinates({
    double latitude,
    double longitude,
  });

external double get latitude;
  external double get longitude;
}

Step 4 : Final Step (Calling from Dart)

We exposed our getCurrentPosition in Step 2, its time to call it now….We need to pass a function as a param to getCurrentPosition.. 

In order to pass a Dart function to a JS API, we need to do that using allowInterop or allowInteropCaptureThis.

OutlineButton(
onPressed: () {
getCurrentPosition(allowInterop((pos) {
setState(() {
_latitude = pos.coords.latitude;
_longitude = pos.coords.longitude;
});
}));
},
child: const Text('Mozilla GeoLocation'),
),

Calling API for location….

If the above method was too complicated for you, no worries, we got you covered..

Step 1 : Import http package

dependencies:  http: ^0.12.0+4

Step 2 : Call Location API

In our case, we have called,

https://geolocation-db.com/json/

This gives us response as : (Removed values for the demo)

{
"country_code":"",
"country_name":"",
"city":"",
"postal":null,
"latitude":1.2931,
"longitude":103.8558,
"IPv4":"119.74.94.182",
"state":""
}

In case it helped :)
Pass Me A Coffee!!

Hosted URL : https://fir-signin-4477d.firebaseapp.com/#/

Source code for Flutter Web App..

Top comments (3)

Collapse
 
imaduddinkhan profile image
Imad Ud Din Khan

Thank you so much brother, but kindly tell me I am always getting the same city from this api "geolocation-db.com/json/",
Am I doing this right in the following code. When I tap the city Karachi is showing and this error also "Error: Expected a value of type 'GeolocationPosition', but got one of type 'Geoposition'"

success(pos) {
try {
_latitude = pos.coords.latitude;
_longitude = pos.coords.longitude;
} catch (ex) {
print("Exception thrown : " + ex.toString());
}
}

InkWell(
onTap: () async {
final _val = await LocationAPI().fetchData();
setState(() => _city = _val);
getCurrentPosition(allowInterop((pos) => success(pos)));
},
child: const Icon(
Icons.my_location,
size: 13.0,
),
),

Collapse
 
aseemwangoo profile image
aseem wangoo

This means the type expected should be Geoposition instead of GeoLocationPosition. Play with console log of javascript to first manipulate the Geoposition object

Collapse
 
imaduddinkhan profile image
Imad Ud Din Khan

Your answer was not helpfull. The error says expected a value of type GeoLocationPosition and you are saying expected type should be geoposition. Please give me some code example, I am also not so good with javascript to paly with console.