Begin…
We will cover two points in this article…
- Detect user’s location using Mozilla Geolocation
- 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
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":""
}
Hosted URL : https://fir-signin-4477d.firebaseapp.com/#/
Top comments (3)
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,
),
),
This means the type expected should be Geoposition instead of GeoLocationPosition. Play with console log of javascript to first manipulate the Geoposition object
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.