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 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 (with developer account for Mac users).
- Either IOS Simulator, Android Studio, or Chrome web browser to run our application.
- Docker Installation (recommended), DigitalOcean droplet, or Gitpod.
- An Appwrite instance. Check out this article 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 and repository.
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).
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
).
Cloning the Flutter project
In this section, we will need to clone the repository 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 on how to clone a repository.
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.
IoS
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. 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
).
<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:
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:
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.
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:
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:
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.
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.
Here is the final result of how our code works:
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:
Thanks for reading, and happy coding 💻