Geoqueries
Introduction
In this guide, you’ll learn how to perform GeoPoint
querying on Parse
in an Android
application.
This tutorial uses an app created in Android Studio Arctic Fox -2020.3.1 with compileSdk = 30
, minSdk = 23
and targetSdk = 30
At any time, you can access the complete Project via our GitHub repositories.
Goal
Perform Geoqueries using geopoints stored on Back4App and Android geolocation.
Here is a preview of what we are gonna achieve:

Prerequisites
To complete this tutorial, we need:
- Android Studio.
- An app created on Back4App.
- Note: Follow the New Parse App tutorial to learn how to create a Parse App on Back4App.
- An android app connected to Back4App.
- Note: Follow the Install Parse SDK tutorial to create an Android Studio Project connected to Back4App.
- A device (or virtual device) running Android 4.1 (Jelly Bean) or newer.
Let’s get started!
Before next steps, we need to connect
Back4App
to our application. You should save theappId
andclientKey
from theBack4App
tostring.xml
file and then initParse
in ourApp.java
orApp.kt
file.
Follow the New Parse App tutorial if you don’t know how to initParse
to your app.
Or you can download the projects we shared the github links above and edit only theappId
andclientKey
parts according to you.
Step 1 - Save some data on Back4App
In this step, we will create a Class with the JS Console and Javascript codes provided by
Parse
and we will create queries for this Class.
Let’s create a City
class, which will be the target of our queries in this guide. On Parse JS Console is possible to run JavaScript code directly, querying and updating your application database contents using the JS SDK commands. Run the code below from your JS Console and insert the data on Back4App.
Here is how the JS Console looks like in your dashboard:
Go ahead and create the City
class with the following example content:
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
// Add City objects and create table
// Note how GeoPoints are created, passing latitude and longitude as arguments
// Montevideo
City = new Parse.Object('City');
City.set('name', 'Montevideo - Uruguay');
City.set('location', new Parse.GeoPoint(-34.85553195363169, -56.207280375137955));
await City.save();
// Brasília
City = new Parse.Object('City');
City.set('name', 'Brasília - Brazil');
City.set('location', new Parse.GeoPoint(-15.79485821477289, -47.88391074690196));
await City.save();
// Bogotá
City = new Parse.Object('City');
City.set('name', 'Bogotá - Colombia');
City.set('location', new Parse.GeoPoint(4.69139880891712, -74.06936691331047));
await City.save();
// Mexico City
City = new Parse.Object('City');
City.set('name', 'Mexico City - Mexico');
City.set('location', new Parse.GeoPoint(19.400977162618933, -99.13311378164776));
await City.save();
// Washington, D.C.
City = new Parse.Object('City');
City.set('name', 'Washington, D.C. - USA');
City.set('location', new Parse.GeoPoint(38.930727220189944, -77.04626261880388));
await City.save();
// Ottawa
City = new Parse.Object('City');
City.set('name', 'Ottawa - Canada');
City.set('location', new Parse.GeoPoint(45.41102167733425, -75.695414598736));
await City.save();
console.log('Success!');
Step 2 - Query the data from Android app
Now that you have a populated class, we can now perform some GeoPoint queries in it. Let’s begin by ordering City
results by the nearest from Kingston in Jamaica (latitude 18.01808695059913 and longitude -76.79894232253473), using the ParseQuery.whereNear
method:
1
2
3
4
5
6
7
8
9
ParseQuery<ParseObject> query = new ParseQuery<>("City");
query.whereNear("location",new ParseGeoPoint(18.018086, -76.798942));
query.findInBackground((objects, e) -> {
if (e==null){
initData(objects);
} else {
Toast.makeText(MainActivity.this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
});
1
2
3
4
5
6
7
8
9
10
val query = ParseQuery<ParseObject>("City")
query.whereNear("location", ParseGeoPoint(18.018086, -76.798942))
query.findInBackground { objects: List<ParseObject>?, e: ParseException? ->
if (e == null) {
initData(objects!!)
} else {
Toast.makeText(this@MainActivity, e.localizedMessage, Toast.LENGTH_SHORT)
.show()
}
}
Let’s now query using the method ParseQuery.whereWithinKilometers
, which will retrieve all results whose GeoPoint field is located within the max distance. Kingston will be used once again as a reference and the distance limit will be 3000 km.
1
2
3
4
5
6
7
8
9
ParseQuery<ParseObject> query = new ParseQuery<>("City");
query.whereWithinKilometers("location",new ParseGeoPoint(18.018086, -76.798942),3000);
query.findInBackground((objects, e) -> {
if (e==null){
initData(objects);
} else {
Toast.makeText(MainActivity.this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
val query = ParseQuery<ParseObject>("City")
query.whereWithinKilometers(
"location",
ParseGeoPoint(18.018086, -76.798942),
3000.0
)
query.findInBackground { objects: List<ParseObject>?, e: ParseException? ->
if (e == null) {
initData(objects!!)
} else {
Toast.makeText(this@MainActivity, e.localizedMessage, Toast.LENGTH_SHORT)
.show()
}
}
Another useful query method is ParseQuery.whereWithinPolygon
, which will query results whose GeoPoint field value is within the specified polygon, composed of an array of GeoPoints (at least three). If the polygon path is open, it will be closed automatically by Parse connecting the last and first points.
For this example, you will be using a simple polygon that roughly contains the South American continent, composed of 5 distant GeoPoints in the ocean.
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
ParseQuery<ParseObject> query = new ParseQuery<>("City");
ParseGeoPoint geoPoint1 = new ParseGeoPoint(15.822238344514378, -72.42845934415942);
ParseGeoPoint geoPoint2 = new ParseGeoPoint(-0.7433770196268968, -97.44765968406668);
ParseGeoPoint geoPoint3 = new ParseGeoPoint(-59.997149373299166, -76.52969196322749);
ParseGeoPoint geoPoint4 = new ParseGeoPoint(-9.488786415007201, -18.346101586021952);
ParseGeoPoint geoPoint5 = new ParseGeoPoint(15.414859532811047, -60.00625459569375);
ParseGeoPoint geoPoint6 = new ParseGeoPoint(41.015137, 28.97953);
List<ParseGeoPoint> list = new ArrayList<>();
list.add(geoPoint1);
list.add(geoPoint2);
list.add(geoPoint3);
list.add(geoPoint4);
list.add(geoPoint5);
list.add(geoPoint6);
query.whereWithinPolygon("location",list);
query.findInBackground((objects, e) -> {
if (e==null){
initData(objects);
} else {
Toast.makeText(MainActivity.this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
val query = ParseQuery<ParseObject>("City")
val geoPoint1 = ParseGeoPoint(15.822238344514378, -72.42845934415942)
val geoPoint2 = ParseGeoPoint(-0.7433770196268968, -97.44765968406668)
val geoPoint3 = ParseGeoPoint(-59.997149373299166, -76.52969196322749)
val geoPoint4 = ParseGeoPoint(-9.488786415007201, -18.346101586021952)
val geoPoint5 = ParseGeoPoint(15.414859532811047, -60.00625459569375)
val geoPoint6 = ParseGeoPoint(41.015137, 28.97953)
val list: MutableList<ParseGeoPoint> =
ArrayList()
list.add(geoPoint1)
list.add(geoPoint2)
list.add(geoPoint3)
list.add(geoPoint4)
list.add(geoPoint5)
list.add(geoPoint6)
query.whereWithinPolygon("location", list)
query.findInBackground { objects: List<ParseObject>?, e: ParseException? ->
if (e == null) {
initData(objects!!)
} else {
Toast.makeText(this@MainActivity, e.localizedMessage, Toast.LENGTH_SHORT)
.show()
}
}
It’s done!
At the end of this guide, you learned how GeoPoint data queries work on Parse and how to perform them on Back4App from an Android app. In the next guide, you will check how to create and manage users in Parse.