Location, location, location…

What if I want to detect user’s location in Flutter Web ? How can I call JS function from Flutter Web? Hmmm…

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…

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

Flutter Web and Location
Flutter Web and Location

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/#/

Source code for Flutter Web App..

1 Comment

Valuable comments