Auto-detect a user country and locale in Flutter
Tags: appwrite, flutter, localedetector, hackmamba
Published: 2022-11-14 20:33:31

According to the Oxford dictionary, geo-fencing involves using GPS or radio frequency identification (RFID) technology to create a virtual geographic boundary, enabling software to trigger a response when a mobile device enters or leaves a particular area. A famous use case of geo-fencing in the modern era of software is PayPal, which provides service to a user's location.

This tutorial aims to show how to manage the geo-fencing of applications available to a specific country. Thus, this article will explain how to auto-detect a user's country and locale in Flutter using Appwrite's locale API.

During this tutorial, we will display the location information of a user currently logged in. [Here](https://github.com/muyiwexy/appwrite-flutter-locale-master/tree/Locale-detector) [](https://github.com/muyiwexy/appwrite-flutter-locale-master)is the link to the GitHub repository containing all the code for this current project.


## Prerequisites

The processes involved in this tutorial are relatively uncomplicated to follow but can be cumbersome. Thus, we strongly advise the reader to have the following prerequisites settled:


- [Xcode](https://developer.apple.com/xcode/) (with developer account for Mac users).
- Either [IOS Simulator](https://developer.apple.com/documentation/xcode/running-your-app-in-the-simulator-or-on-a-device), [Android Studio](https://developer.android.com/studio), or [Chrome web browser](https://support.google.com/chrome/answer/95346?hl=en-GB&co=GENIE.Platform%3DDesktop) to run our application.
- Docker Installation (recommended), [DigitalOcean droplet](https://marketplace.digitalocean.com/apps/appwrite), or [Gitpod](https://gitpod.io/#https://github.com/appwrite/integration-for-gitpod).
- An Appwrite instance. Check out this [article](https://dev.to/hackmamba/create-a-local-appwrite-instance-in-3-steps-19n9) for the setup.
- For this tutorial, we need to set up the boilerplate containing the user signup and login feature. Here is a link to the [article](https://tealfeed.com/user-authentication-using-appwrite-flutter-ujuqm) and [repository](https://github.com/muyiwexy/appwrite-flutter-locale-master/tree/master).


## Creating an Appwrite project and setting up the platform

Before we delve into the coding aspects, we will need to create a new `Appwrite` project. To do that, we will start by heading to our browser and typing the `hostname or IP address` in our browser to open up the `Appwrite console`. Next, we will create a new project by clicking `create project`, followed by adding the `project name and an ID` (ID can be autogenerated).


![create project](https://paper-attachments.dropbox.com/s_4E3FAD040931FEB6B7941EF3B73647F9CAC05974B4A84BBC9751DD517299E544_1664053744093_Screenshot+38.png)
![project info](https://paper-attachments.dropbox.com/s_4E3FAD040931FEB6B7941EF3B73647F9CAC05974B4A84BBC9751DD517299E544_1664053744113_Screenshot+39.png)


Finally, within the home section, we will scroll down, select create platform, and in the popup, select `Flutter`. Within the Flutter section, we will choose `Android` and input our `application name and package name` (we can find them in our app-level `build.gradle` file by heading to `android>app folder`).


![project platform](https://paper-attachments.dropbox.com/s_4E3FAD040931FEB6B7941EF3B73647F9CAC05974B4A84BBC9751DD517299E544_1664053674434_Screenshot+5.png)

![flutter app registration](https://paper-attachments.dropbox.com/s_4E3FAD040931FEB6B7941EF3B73647F9CAC05974B4A84BBC9751DD517299E544_1664068306777_Screenshot+42.png)



## Cloning the Flutter project

In this section, we will need to clone the [repository](https://github.com/muyiwexy/appwrite-flutter-locale-master/tree/master) specified in the prerequisites. To do that, we will click on the link to the repository, and within the repository, we will click on `code` and download it as a zip file. To use the other methods, check out the GitHub [docs](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) on how to clone a repository.

![repo home](https://paper-attachments.dropboxusercontent.com/s_4E3FAD040931FEB6B7941EF3B73647F9CAC05974B4A84BBC9751DD517299E544_1665664932346_Screenshot+50.png)
![clone repo](https://paper-attachments.dropboxusercontent.com/s_4E3FAD040931FEB6B7941EF3B73647F9CAC05974B4A84BBC9751DD517299E544_1665664932357_Screenshot+51.png)


The content of this repository is a user verification template that checks whether there is an account or active login session in our Appwrite console.


## Connecting Appwrite to the Flutter project

Next, we must connect the Flutter application to the Appwrite console. This feature varies from one platform to another; thus, we will show how to connect the console to IOS and Android devices.

**I****o****S**
First, we will need to obtain the `bundle ID`, which we can do by going to the `project.pbxproj` file (`ios > Runner.xcodeproj > project.pbxproj`) and search for our `PRODUCT_BUNDLE_IDENTIFIER`.

Now, we will head to the `Runner.xcworkspace` folder in the applications IOS folder in the project directory on [Xcode](https://developer.apple.com/xcode/). Now, we want to select the Runner target, and to do this, we will select the Runner project in the Xcode project navigator and then find the Runner target. Next, we will select `General` and `IOS 11.0` in the `deployment info section` as the target.

**Android**
To do this, copy the `XML` script below and paste it below the activity tag in the `Androidmanifest.xml` file (to find this file, head to `android > app > src > main`).


```xml
<activity android:name="com.linusu.flutter_web_auth_2.CallbackActivity" android:exported="true">
    <intent-filter android:label="flutter_web_auth_2">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="appwrite-callback-[PROJECT-ID]" />
    </intent-filter>
</activity>
```


> Note: change [PROJECT-ID] to the id you used when creating the Appwrite project

Finally, we will add two dependencies to our project — the Appwrite package and provider. To do this, we will head to the `pubspec.yaml` file and add the packages below to the dependencies list:


```yaml
provider: ^6.0.3
appwrite: ^6.0.0
```

 
Now, we can move on to creating the project components.
 

## Getting started

Now, we will work on the home page section of our project. The home page will display the user's locale information, and to achieve that, we will need to make slight changes to the `authenticate.dart` file in the cloned repository and create a model class for the locale list object. Let’s begin!

**app_constants.dart**
This file contains only some specific information like our `endpoint`, `projectID`, or any other ID, if applicable, created in our Appwrite console. Thus, we will start by creating a class called `Appconstants` and create two static constants: `endpoint` and `projectID`. Here is an implementation of the explanation above: 
 

```dart
class Appconstants {
  static const String projectid = "<projectID>";
  static const String endpoint = "http://localhost/v1";
}
```

**localedata.dart**
In this file, we will create a model class to determine the data structure; in this case, we are defining the design of a `JSON` object, [locale](https://appwrite.io/docs/models/locale).

We will start by creating a new class and static constants for the data of the `JSON` objects. Next, we will create a new class outside our previous one, map out the data we want to use as instance variables, and then create a constructor for those instances. Next, we will create a function that will accept JSON as input, and we are good to go.

We have below the implementation of the explanation above:

```dart
class LocaleFields {
  static const String ip = "ip";
  static const String countrycode = "countryCode";
  static const String country = "country";
  static const String continentcode = "continentCode";
  static const String continent = "continent";
  static const String eu = "eu";
  static const String currency = "currency";
}
class LocaleData {
  String ip;
  String countryCode;
  String country;
  String continentCode;
  String continent;
  bool eu;
  String currency;
  LocaleData(
      {required this.ip,
      required this.countryCode,
      required this.country,
      required this.continentCode,
      required this.continent,
      required this.eu,
      required this.currency});
  LocaleData.fromJson(Map<String, dynamic> json)
      : this(
            ip: json[LocaleFields.ip],
            countryCode: json[LocaleFields.countrycode],
            country: json[LocaleFields.country],
            continentCode: json[LocaleFields.continentcode],
            continent: json[LocaleFields.continent],
            eu: json[LocaleFields.eu] == 1,
            currency: json[LocaleFields.currency]);
  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data[LocaleFields.ip] = ip;
    data[LocaleFields.continent] = continent;
    data[LocaleFields.continentcode] = continentCode;
    data[LocaleFields.country] = country;
    data[LocaleFields.countrycode] = countryCode;
    data[LocaleFields.eu] = eu ? 1 : 0;
    data[LocaleFields.currency] = currency;
    return data;
  }
}

```

**authenticate.dart**
According to the article specified in the prerequisites, this file contains the signup and login functions. For this tutorial, we want to update it so that it will contain the locale functions we will use within the `homepage.dart` file.

Therefore, we will start by calling the `Appwrite locale API` and call the model class we created earlier. Next, we will create a getter for the model class and a new Appwrite locale. Finally, we will create an `async function _localise()` and use it to get the locale object of the currently logged-in user (the data specified in the model class). We will also create a log-out function that deletes the user's session from Appwrite once we click a button. Here is the implementation of this explanation below:

{% embed https://gist.github.com/muyiwexy/480d4b945d3e3d5fd963142c0a2e40f6 %}


**homepage.dart**
Finally, we have reached the last component of our project. In this file, we want to display the location information of a currently logged-in user. To do that, we will create a stateful widget to check whether there is available locale information on the currently logged-in user.


{% embed https://gist.github.com/muyiwexy/919ff94309a0193273d9f3065ec9153f %}


Next, within the build method, we will create an `Appbar` widget that will contain a centered title and exit action button, which, when clicked, initiates that signout function we created earlier. Finally, we will wrap the body in a `Consumer` widget and then return a `ListView` widget containing a row of `Text` widgets that will display the location information provided by the model class created earlier.

{% embed https://gist.github.com/muyiwexy/f93be98fd55efe32b9c5d921200fbea0 %}



Here is the final result of how our code works:


![result](https://paper-attachments.dropbox.com/s_4E3FAD040931FEB6B7941EF3B73647F9CAC05974B4A84BBC9751DD517299E544_1664070215979_www_screencapture_com_2022-9-25_02_37.gif)

> Note: the IP address is visible, but we decided to keep ours hidden for security purposes.

## Conclusion

This tutorial explained how to create a model class and display the locale data of the user using the Appwrite locale API.

We urge the reader to build on this project, and we will provide some references to help:

- [Appwrite Localization API](https://appwrite.io/docs/client/locale?sdk=flutter-default)
- [Appwrite Account API](https://appwrite.io/docs/client/account?sdk=flutter-default)

Thanks for reading, and happy coding 💻