Introduction
In this tutorial, you’ll learn how to build an application that determines a user’s location via the Geolocation
service. It returns a list of customer records that are within X miles of a given location. The list of customers will be stored in the Appery.io database. The records will contain a street address, not coordinates, so you’ll have to convert coordinates and street addresses using the geocoding API. This will be done via server code.
Before you begin
Tutorial level: intermediate.
Creating a new app
Create a new app in the Builder; from the Apps
page, click “Create new app”, select “jQuery Mobile App”, enter an app name and click “Create”. After the app builder opens, go to Pages > startScreen
.
We’re going to create a page, a database and a server code for the app.
Creating a page
The application has only one page.
2. Drag the Button
component to the page from PALETTE
. On the right, in the PROPERTIES
panel, change its Name
property to getCoordinatesButton and type in Text
property “Get my coordinates”.
3. Place the Grid
component on the page. It contains 2 rows and 2 cols.
4. Add two Label
components and two Input
components to the grid. Name the Input
components: latitudeInput and longitudeInput, clear their Text
values and type in their Placeholder
properties: Latitude and Longitude correspondingly. For the Labels
, define their Text
filelds: “Latitude” and “Longitude”.
5. Add the Label
and the Input
below the grid, change the input Name
property to radiusInput, clear the Text
value and type in Placeholder
property "Radius in miles".
6. Drag the Button
component to the page, change its Name
property to getCustomersButton and type in Text
property “Get customers within radius”.
7. Then, add the Collapsible set
component with three Labels
inside it to show customer information. Name them companyNameLabel, addressLabel, phoneLabel:
That’s all for the UI.
Now we’ll create a database to store users’ data.
Creating an app database
Let’s create a database that’ll store customers and their locations.
To start creating the app database, click on the “Database” button in the builder (upper right corner) or simply go to https://appery.io/database.
1. Create a new database; name it Geocoding
.
2. Once the database is loaded, create a new collection (custom) called customers
.
3. Add the following columns to the customers
collection (type should be String
):
- contactName
- companyName
- phoneNumber
- address
4. Click “+Row” to add records to the collection. Fill the database with some sample data. Note, that address
fields should contain real and valid addresses:
Creating a server code
Now, you need to create a server script that’ll get records from the database, geocode addresses (convert friendly location names to latitude and longitude values), and calculate whether a customer is located within the specified radius.
1. Click on the “Server Code” button in the builder (the upper right corner) or simply go to https://appery.io/servercode/.
2. Create a new script called Geocoding
.
3. Add the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
// Database Id var dbId = "your database id"; //Change this value to your database id var responseBody = {}; // Get request parameters var latitude = request.object().latitude; var longitude = request.object().longitude; var radius = request.object().radius; // The function that calculates the distance between two points function getDistance(lat1, lat2, lon1, lon2) { var R = 3959; // Earth radius in miles var dLat = (lat2 - lat1) * Math.PI / 180; var dLon = (lon2 - lon1) * Math.PI / 180; var lat1 = lat1 * Math.PI / 180; var lat2 = lat2 * Math.PI / 180; var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var d = R * c; return d; } try { // Check if all the necessary parameters are present and valid if (latitude && longitude && radius && !isNaN(latitude) && !isNaN(longitude) && !isNaN(radius)) { var results = []; var params = {}; // Sort the results by contact name params.sort = "contactName"; // Get all customers from the database var customers = Collection.query(dbId, "customers", params); for (var i = 0; i < customers.length; i++) { // Geocode customer's address with Google API var XHRResponse = XHR.send("GET", "https://maps.googleapis.com/maps/api/geocode/json", { "parameters": { "address": customers[i].address, "sensor": "false" } }); console.log(XHRResponse); if (XHRResponse.status == 200) { // Get coordinates from the response var lat = JSON.parse(XHRResponse.body).results[0].geometry.location.lat; var lng = JSON.parse(XHRResponse.body).results[0].geometry.location.lng; // If the customer's coordinates are within the radius, // add the customer record to the results array if (getDistance(lat, latitude, lng, longitude) <= radius) { results.push(customers[i]); } } } responseBody["results"] = results; response.success(responseBody, "application/json"); } else { response.error("Wrong parameters", 400); } } catch (e) { console.log(e); response.error("An error occured", 400); } |
Please replace your database id
with the ID of the database you’ve created. The code uses the Google Maps geocoding
API to turn addresses into coordinates. Note, that the code retrieves all the records from the database to geocode them. If your database contains a large number of records, this approach can be inefficient. In this case, we recommend storing the coordinates directly in the database.
To calculate the distance between two points, a special formula is used. You can read more about it here.
Creating services
The application uses two services.
The first is a Geolocation
service. It is a so-called “device” service. It retrieves the current coordinates of the user.
The second service calls the server script that’s been created. “GetCustomersWithinRange”.
Geolocation service
Click “Create Service” without specifying any parameters:
1. From the builder: CREATE NEW > Service
. Check Geolocation
and click “Create Service”. You can leave the default name:
2. Go to the startScreen
and switch to the DATA
tab. For datasource
, select Device
, and then select GeolocationService
. Click “Add“.
3. Then, on the DATA
tab, click “Mapping” for Success
event, and create the following mapping:
4. Click “Save and return”.
Server Code service
1. Choose CREATE NEW > Server Code Services
, choose Geocoding
from the list.
2. Click “Import selected services”, and then rename the service to GetCustomersWithinRange
.
3. In the Settings
tab of the newly-created service change Content Type
to json
. This is how the Settings
tab should look like:
4. Next, go to the Request
tab and add three parameters radius
, latitude
and longitude
under the Body
tab. Type mock values for the parameters (for example, 10 for radius
, 40.614865 for latitude
and -74.110191 for longitude
):
5. Switch to the Test
tab and click “Test”. After the test finishes successfully, click “Import as Response” to fill the Response
data:
6. Go to the startScreen
and switch to the DATA
tab. For datasource
, select Service
, and then select GetCustomersWithinRange
. Click “Add” and rename the service instance to getCustomersService
.
7. On the DATA
tab, click “Mapping” for Before send
, and create the following mapping:
8. Click “Save and return”.
9. Then, click “Mapping” for the Success
event, and create the following mapping:
10. In the Edit JS
sections of the labels, you can change the corresponding pieces of JavaScript:
- for
companyNameLabel
:
1return "Company: " + value; - for
addressLabel
:
1return "Address: " + value; - for
phoneLabel
:
1return "Phone:" + value;
11. Click “Save and return”.
Adding events
Invoking services
Now you need to define how the services will be invoked, and perform some error handling.
Open the DESIGN
tab of the page, open the EVENTS
panel and specify the following events:
getCoordinatesButton > Click > Invoke service > geolocationService
getCustomersButton > Click > Invoke service > getCustomersService
After adding an action, click “Save”. Thus, the services will be invoked when the corresponding buttons are clicked.
Now, the startScreen
DESIGN
tab events should look like:
Handling errors
Go to the DATA
tab again, open the EVENTS
panel, and specify the following error handlers:
geolocationService > Fail > Run JavaScript >
add the following script:
1alert("Failed to get coordinates");getCustomersService > Error > Run JavaScript >
add the following script:
1alert(jqXHR.responseText);
Now, the startScreen
DATA
tab events should look like:
The application is ready. You can test it by clicking “Test”, or by exporting it to test on devices.
It would be nice to display your location on a map, rather than just listing your coordinates. Try modifying this application by adding a Google Maps
component. You can review this tutorial for help: https://devcenter2.appery.io/tutorials/building-a-mobile-app-with-google-map-and-geolocation/.
Testing the app
If you click the “Get my coordinates” button, the application will determine your current location by using the Geolocation
service:
You can also enter any geographical coordinates manually, and you can also specify the radius (in miles) to display customers. After you click “Get customers within radius”, you’ll receive a list of records located within the specified radius: