Skip to content

Search

The search package provides all of the classes for search. Search is the most powerful set of classes and provides much flexibility for the developer. Following are some of the search features provided by the classes.

  • Onebox search - Location based semantic search finds POIs (points of interest) and addresses using free text or tagged query syntax. Advanced semantic knowledge and underlying search technology provide highly relevant search results by simply entering a free text query in a single text field (one-box). This is the foundation of Telenav search and great search flexibility.
  • Category filter search - Enables POI search by specific category. Telenav supports over 100 POI categories.
  • Brand filter search - Enables POI search by specific business brand name or chain name.
  • Corridor search - Enables POIs to be found within a specific corridor; also called "Search Along Route" to constrain search results to places near driver's route.
  • Polygon search - Constrains search results to any polygon shape.
  • Bounding box search - Constrains search results to a rectangular bounding box.
  • Reverse geocoding (RGC) - RGC service returns an address based on a coordinate (latitude/longitude) value.
  • Voice Search - Enables support for free text and structured text queries for voice search use cases.
  • Electric vehicle charge station search - Specialized search services for electric charge stations.
  • Anchor search - To specify search location if the search location is different from the current vehicle position.

Please see the API reference for the main classes related to Search.

Use the one box search method when search input is provided in the form of free search text and location is around a single point. At a minimum developer needs to provide query and point. Telenav one box search is semantic based free text query search. Many different entity types can be searched by providing a text query in the .setquery method. Search supports fuzzy matching capabilities such that the query does not need to exactly match desired search entity. The onebox text parser can identify the following entity types from the free form query text:

  • Address (full or partial)
  • Point of interest (exact or inexact match)
  • Category name (including synonyms)
  • Street (with or without street type)
  • City In addition to these entity types, additional query patterns can be supported such as querying street intersection, POI name in city, etc.

Fuzzy one box: Note that query does not need to be exact as semantic search will consider approximate names and ‘fuzzy match’ entities which are similarly named.

Key methods

Method Details
setLocation(double latitude, double longitude) A geopoint value of the user’s location using geographic coordinates of latitude and longitude separated by comma). For example, location=37.1245,-122.45678.
setQuery(String query) For one box search this value is free-text query. Query can support search for an address, point of interest (POI), street, or city. In addition, there are additional more complex search patterns which are supported. Query search patterns are localized so expected search patterns for supported locale are accepted.


Search API sample 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
entityClient.searchRequest()
    .setQuery("Pierce Rd")
    .setLocation(37.12419, -121.98828)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            List<Entity> resultEntities = response.getResults();
            if (resultEntities == null || resultEntities.isEmpty()) {
                LOG.info("No result found");
                return;
            }
            for (Entity entity : resultEntities) {
                if (entity.getType() == EntityType.ADDRESS) {
                    LOG.info("Found Address: " + entity.getAddress().getFormattedAddress());
                } else if (entity.getType() == EntityType.PLACE) {
                    LOG.info("Found Place: " + entity.getPlace().getName());
                }
            }
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Get unsuccessful response or throwable happened when executing the request.", t);
        }
    });
 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
entityClient.searchRequest()
    .setQuery("Pierce Rd")
    .setLocation(37.12419, -121.98828)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            val resultEntities = response.results
            if (resultEntities == null || resultEntities.isEmpty()) {
                Log.i("sdk", "No result found")
                return
            }
            for (entity in resultEntities) {
                if (entity.type == EntityType.ADDRESS) {
                    Log.i("sdk", "Found Address: ${entity.address.formattedAddress}")
                } else if (entity.type == EntityType.PLACE) {
                    Log.i("sdk", "Found Place: ${entity.place.name}")
                }
            }
        }

        override fun onFailure(t: Throwable) {
            Log.e("sdk", "Get unsuccessful response or throwable happened when executing the request.", t)
        }
    })

You can also call API synchronously using execute() method.

 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
EntitySearchResponse response = null;
try {
    response = entityClient.searchRequest()
        .setQuery("Pierce Rd")
        .setLocation(37.12419, -121.98828)
        .execute();
} catch (IOException e) {
    LOG.error("Error happened when doing search.", e);
    return;
} catch (EntityServiceException e) {
    ResponseCode code = e.getCode();
    LOG.error("Error happened when doing search. error code={}", code.getStatusCode(), e);
    return;
}

List<Entity> resultEntities = response.getResults();
if (resultEntities == null || resultEntities.isEmpty()) {
    LOG.info("No result found.");
    return;
}
for (Entity entity : resultEntities) {
    if (entity.getType() == EntityType.ADDRESS) {
        LOG.info("Found Address: " + entity.getAddress().getFormattedAddress());
    } else if (entity.getType() == EntityType.PLACE) {
        LOG.info("Found Place: " + entity.getPlace().getName());
    }
}
 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
var response: EntitySearchResponse?

response = try {
    entityClient.buildSearchRequest()
        .setQuery("Pierce Rd")
        .setLocation(37.12419, -121.98828)
        .execute()
} catch (e: IOException) {
    Log.e("sdk", "Error happened when doing search.", e)
    return
} catch (e: EntityServiceException) {
    val code: ResponseCode = e.getCode()
    Log.e("sdk", "Error happened when doing search. error code=${code.statusCode}", e)
    return
}

val resultEntities = response.results
if (resultEntities == null || resultEntities.isEmpty()) {
    Log.i("sdk", "No result found.")
    return
}
for (entity in resultEntities) {
    if (entity.type == EntityType.ADDRESS) {
        Log.i("sdk", "Found Address: ${entity.address.formattedAddress}")
    } else if (entity.type == EntityType.PLACE) {
        Log.i("sdk", "Found Place: ${entity.place.name}")
    }
}

Response example

 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
{
  "code": "SUCCESS",
  "reference_id": "2e3f55e3-df3e-44d4-8b88-b120630274b9",
  "search_metadata": {
    "counts": [
      {
        "type": "ADDRESS",
        "count": 3
      }
    ],
    "query_resolution": {
      "query_tags": [
        {
          "where": "Street=Pierce Rd"
        }
      ],
      "search_location": {
        "latitude": 37.12419,
        "longitude": -121.98828
      }
    }
  },
  "has_more": false,
  "results": [
    {
      "id": "Yz1Mb3MgR2F0b3M7Y3k9U2FudGEgQ3J1ejtjbz1VUztzZm49UGllcmNlIFJkO3o9OTUwMzM7cz1DQTt0PVNUUkVFVDtpZD1IM19OVF9iQ2RoUnBxUEF1UmhVMGxySGJrMDRBO2x0PTM3LjEyNjAyO2xuPS0xMjEuOTkwMzY7cmdjPWZhbHNlO3R0PVNUUkVFVDtpX2NvPVVTO2lfc2ZuPVBpZXJjZSBSZDsV6",
      "type": "ADDRESS",
      "address": {
        "address_type": "STREET",
        "formatted_address": "Pierce Rd, Los Gatos CA 95033, USA",
        "street": {
          "body": "pierce",
          "type": "road",
          "formatted_name": "Pierce Rd"
        },
        "city": "Los Gatos",
        "county": "Santa Cruz",
        "state": "CA",
        "country": "USA",
        "postal_code": "95033",
        "geo_coordinates": {
          "latitude": 37.12602,
          "longitude": -121.99036
        },
        "nav_coordinates": {
          "latitude": 37.12602,
          "longitude": -121.99036
        }
      },
      "distance": 274.0
    },
    ...
  ],
  "response_time": 58
}

The category filter search enables search by specific category around a specific location. To use category search the developer needs to provide a list of category ids and a geopoint for location.

Category filter search is often used when HMI interface includes buttons or category hierarchical interface allowing user to select desired POI category such as restaurant, fuel, or parking.

Telenav POI categories support a hierarchical model with parents and child nodes. A child node will only return POIs which belong to the category of that node. If a parent category calls in the service then all children within that parent will be returned in the service. Consider below example: Parent (2041) Restaurant (226) Steakhouse (267) Pizza (263) Mexican (261) .... Coffee and Bakery (890) Bagels and Donuts (230) Bakeries (231) Coffee (241)

In above category example, add category id 2041 to category filter will produce a results list including POIs with categories of all restaurants and coffee/bakery POIs. If category 226 added to category filter then result entities include POIs of categories restaurants of various styles and cuisine types. If category id 263 is added to category filter then only pizza POIs will be in the result entities list.

The list of supported categories and their ids can be retrieved using Discover Category API

To use this category filter search the developer must create a CategoryFilter object and add 1 or more category ids to this object. The CategoryFilter object must be applied to a SearchFilters object before the search is executed or called. A geopoint just be set to provide the location context for search.

Key methods

Method Details
setLocation(double latitude, double longitude) A geopoint value of the location from where brand search will be executed
setCategoryFilter(CategoryFilter filter) The category filter object.

Sample 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
CategoryFilter categoryFilter = CategoryFilter.builder()
    .setCategories(Arrays.asList("241"))
    .build();

SearchFilters searchFilters = SearchFilters.builder()
    .setCategoryFilter(categoryFilter)
    .build();

entityClient.searchRequest()
    .setLocation(37.12419, -121.98828)
    .setFilters(searchFilters)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            List<Entity> resultEntities = response.getResults();
            for (Entity entity : resultEntities) {
                if (entity.getType() == EntityType.PLACE) {
                    LOG.info("Found Places: {}", entity.getPlace().getName());
                }
            }

        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Get unsuccessful response or throwable happened when executing the request.", t);
        }
    });
 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
val categoryFilter = CategoryFilter.builder()
    .setCategories(listOf("241"))
    .build()

val searchFilters = SearchFilters.builder()
    .setCategoryFilter(categoryFilter)
    .build()

entityClient.searchRequest()
    .setLocation(37.12419, -121.98828)
    .setFilters(searchFilters)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            val resultEntities = response.results
            for (entity in resultEntities) {
                if (entity.type == EntityType.PLACE) {
                    Log.i("sdk", "Found Places: ${entity.place.name}")
                }
            }
        }

        override fun onFailure(t: Throwable) {
            Log.e("sdk", "Get unsuccessful response or throwable happened when executing the request.", t)
        }
    })

Telenav brand filter search feature enables search for specific brands or chains. To use brand filter search the developer needs to build a list of brand ids and provide a geopoint for search anchor location. Using a brand search enables all POIs that belong to the brand to be part of entities results list even if the brand may have name variations. Telenav supports hundreds of popular consumer brands across categories such as food, coffee, hotels, restaurants, fuel, and other. Such brands include Starbucks, Chipotle, Subway, HIlton, Best Buy, Nordstrom, Chevron, and many others. Use brand search instead of onebox search when search intent is known to be for specific brand. As some brands have name variations using a brand filter search is recommended for this case.

To use this feature the developer must create a BrandFilter object and add 1 or more brand ids to this object. The BrandFilter object must be applied to a SearchFilters object before the search is executed or called.

Key methods

Method Details
setLocation(double latitude, double longitude) A geopoint value of the location from where brand search will be executed
setBrandFilter(BrandFilter filter) The brand filter object containing list of brand ids

Sample 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
BrandFilter brandFilter = BrandFilter.builder()
    // McDonald's
    .addBrand("99320621")
    .build();

SearchFilters searchFilters = SearchFilters.builder()
    .setBrandFilter(brandFilter)
    .build();

entityClient.searchRequest()
    .setLocation (37.12419, -121.98828)
    .setFilters(searchFilters)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            List<Entity> resultEntities = response.getResults();
            for (Entity entity : resultEntities) {
                if (entity.getType() == EntityType.PLACE) {
                    LOG.info("Found Places: " + entity.getPlace().getName());
                }
            }
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Brand search failed", t);
        }
    });
 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
val brandFilter = BrandFilter.builder()
    // McDonald's
    .addBrand("99320621")
    .build()

val searchFilters = SearchFilters.builder()
    .setBrandFilter(brandFilter)
    .build()

entityClient.searchRequest()
    .setLocation(37.12419, -121.98828)
    .setFilters(searchFilters)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            val resultEntities = response.results
            for (entity in resultEntities) {
                if (entity.type == EntityType.PLACE) {
                    Log.i("sdk", "Found Places: ${entity.place.name}")
                }
            }
        }

        override fun onFailure(t: Throwable) {
            Log.e("sdk", "Brand search failed", t)
        }
    })

Response example

  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
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
{
  "code": "SUCCESS",
  "reference_id": "92c30a35-8096-435d-8de2-f0a1e5672d17",
  "search_metadata": {
    "counts": [
      {
        "type": "PLACE",
        "count": 10
      }
    ],
    "query_resolution": {
      "search_location": {
        "latitude": 37.12419,
        "longitude": -121.98828
      }
    }
  },
  "has_more": false,
  "results": [
    {
      "id": "P-YP-cfjuAoaXnJiqkqK5UmGCxw",
      "type": "PLACE",
      "place": {
        "name": "Starbucks",
        "phone_numbers": [
          "18314409801"
        ],
        "categories": [
          {
            "id": "241",
            "name": "Coffee Houses"
          }
        ],
        "address": {
          "formatted_address": "5600 Scotts Valley Dr, Scotts Valley CA 95066, USA",
          "house_number": "5600",
          "street": {
            "body": "Scotts Valley Dr",
            "formatted_name": "Scotts Valley Dr"
          },
          "city": "Scotts Valley",
          "state": "CA",
          "country": "USA",
          "postal_code": "95066",
          "geo_coordinates": {
            "latitude": 37.06147,
            "longitude": -122.00706
          },
          "nav_coordinates": {
            "latitude": 37.06147,
            "longitude": -122.00706
          },
          "address_lines": [
            "5600 Scotts Valley Dr, Scotts Valley CA 95066"
          ]
        },
        "websites": [
          "https://www.starbucks.com"
        ],
        "brands": [
          {
            "brand_id": "5e36d154adf911e299336e1e7d26b4cc"
          }
        ]
      },
      "distance": 7164.0,
      "facets": {
        "open_hours": {
          "regular_open_hours": [
            {
              "day": 7,
              "open_time": [
                {
                  "from": "06:00:00",
                  "to": "18:00:00"
                }
              ]
            },
            {
              "day": 1,
              "open_time": [
                {
                  "from": "05:00:00",
                  "to": "18:00:00"
                }
              ]
            },
            {
              "day": 2,
              "open_time": [
                {
                  "from": "05:00:00",
                  "to": "18:00:00"
                }
              ]
            },
            {
              "day": 3,
              "open_time": [
                {
                  "from": "05:00:00",
                  "to": "18:00:00"
                }
              ]
            },
            {
              "day": 4,
              "open_time": [
                {
                  "from": "05:00:00",
                  "to": "18:00:00"
                }
              ]
            },
            {
              "day": 5,
              "open_time": [
                {
                  "from": "05:00:00",
                  "to": "18:00:00"
                }
              ]
            },
            {
              "day": 6,
              "open_time": [
                {
                  "from": "06:00:00",
                  "to": "18:00:00"
                }
              ]
            }
          ]
        },
        "price_info": {
          "price_level": 1
        },
        "rating": [
          {
            "source": "YELP",
            "average_rating": 3.5,
            "total_count": 50,
            "rating_type": "star",
            "url": "https://www.yelp.com/biz/starbucks-scotts-valley-2"
          }
        ]
      }
    },
    ...
  ],
  "response_time": 102
}

The corridor search features enables developer to apply a search buffer which is limited to an area which is within a buffer range of driver’s current route. This feature is also referred to as "Search Along Route". Either a place keyword query, category filter, or brand filter must also be supplied to indicate the search intent within the corridor. A prerequisite of building this filter is acquiring a route. The route is acquired from a separate service from search and is typically represented in the form of a polyline (list of coordinates). The developer needs to apply a buffer width (in meters) to the route.

A corridor filter search is a form of a geo-filter. A geo-filter limits search to the bounds of the provided geometry. In the case of corridor search the constraining geometry is the route (represented as a coordinate list) with a buffer applied to each side of the route. To build a corridor filter the developer creates a CorridorGeoFilter object and iteratively applies the .addPoint method for each coordinate point for the route. The CorridorGeoFilter object is applied to a SearchFilters object before search is executed or called.

Key methods

Method Details
setQuery(String query) Free form search text indicating search intent.
Note: brand or category filter can be used in place of query text
setGeoFilter(CorridorGeoFilter geoFilter) The corridor geofilter created above

Sample 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
CorridorGeoFilter geoFilter = CorridorGeoFilter.builder()
    .addPoint(37.763628, -122.47707)
    .addPoint(37.761720, -122.476960)
    .addPoint(37.761711, -122.475670)
    .addPoint(37.761796, -122.473792)
    .addPoint(37.761908, -122.471555)
    .addPoint(37.762061, -122.467285)
    // more points can be added as needed
    .build();

SearchFilters searchFilters = SearchFilters.builder()
    .setGeoFilter(geoFilter)
    .build();

entityClient.searchRequest()
    .setQuery("food")
    .setLocation(37.763662, -122.47700)
    .setFilters(searchFilters)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            List<Entity> resultEntities = response.getResults();
            for (Entity entity : resultEntities) {
                // ...
            }
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Corridor search failed", t);
        }
    });
 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
val geoFilter = CorridorGeoFilter.builder()
    .addPoint(37.763628, -122.47707)
    .addPoint(37.761720, -122.476960)
    .addPoint(37.761711, -122.475670)
    .addPoint(37.761796, -122.473792)
    .addPoint(37.761908, -122.471555)
    .addPoint(37.762061, -122.467285)
    // more points can be added as needed
    .build()

val searchFilters = SearchFilters.builder()
    .setGeoFilter(geoFilter)
    .build()

entityClient.searchRequest()
    .setQuery("food")
    .setLocation(37.763662, -122.47700)
    .setFilters(searchFilters)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            val resultEntities = response.results
            for (entity in resultEntities) {
                // ...
            }
        }

        override fun onFailure(t: Throwable) {
            Log.e("sdk", "Corridor search failed", t)
        }
    })

The polygon search feature enables search results to be constrained to within the spatial boundaries of the respective polygon. Either a query, category filter, or brand filter must also be supplied to indicate the search intent within the polygon. The polygon can represent any area although it is recommended that the polygon size is kept to a plausible search extent to reasonable fill the polygon area with entity search results. Although the polygon can represent any geographic area, a common usage for polygon search is limited results to the boundaries of a city or other administrative area.

A polygon filter search is a form of a geo-filter. A geo-filter limits search to the bounds of the provided geometry. In the case of polygon search the constraining geometry is the polygon geometry. To build a polygon filter the developer creates a Polygon object and iteratively applies the .addPoint method for each coordinate point for the polygon. A minimum of 3 points are required and the polygon object automatically closes itself by connecting the first and last point objects.

Key methods

Method Details
setQuery(String query) Free form search text indicating search intent
Note: category or brand filter can be used in place of query text
setGeoFilter(PolygonGeoFilter geoFilter) The polygon geofilter created above

Sample 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
Polygon polygon = Polygon.builder()
    .addPoint(37.12419, -121.98828)
    .addPoint(37.06723, -122.11108)
    .addPoint(36.95373, -122.07400)
    .addPoint(36.98445, -121.82475)
    .addPoint(37.11050, -121.85427)
    .build();

PolygonGeoFilter geoFilter = PolygonGeoFilter
    .builder(polygon)
    .build();

SearchFilters polygonSearchFilters = SearchFilters.builder()
    .setGeoFilter(geoFilter)
    .build();

entityClient.searchRequest()
    .setQuery("Tea")
    .setLocation(37.12419, -121.98828)
    .setFilters(polygonSearchFilters)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            List<Entity> resultEntities = response.getResults();
            for (Entity entity : resultEntities) {
                if (entity.getType() == EntityType.PLACE) {
                    LOG.info("Found Places: " + entity.getPlace().getName());
                }
            }
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Polygon search failed", t);
        }
    });
 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
val polygon = Polygon.builder()
    .addPoint(37.12419, -121.98828)
    .addPoint(37.06723, -122.11108)
    .addPoint(36.95373, -122.07400)
    .addPoint(36.98445, -121.82475)
    .addPoint(37.11050, -121.85427)
    .build()

val geoFilter = PolygonGeoFilter
    .builder(polygon)
    .build()

val polygonSearchFilters = SearchFilters.builder()
    .setGeoFilter(geoFilter)
    .build()

entityClient.searchRequest()
    .setQuery("Tea")
    .setLocation(37.12419, -121.98828)
    .setFilters(polygonSearchFilters)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            val resultEntities = response.results
            for (entity in resultEntities) {
                if (entity.type == EntityType.PLACE) {
                    Log.i("sdk", "Found Places: ${entity.place.name}")
                }
            }
        }

        override fun onFailure(t: Throwable) {
            Log.e("sdk", "Polygon search failed", t)
        }
    })

The bounding box search feature enables search results to be constrained within the spatial boundaries of the respective rectangle. Either a query, category filter, or brand filter must also be supplied to indicate the search intent within the rectangle. The rectangle can represent any area although it is recommended that the rectange size is kept to a plausible search extent so the search results can reasonably fill the rectangle area with entity search results. Although the rectangle can represent any geographic area, a common usage for rectangle search may be a user drawn search area or limiting results to a given map zoom level or map extent.

A bounding box search is a form of a geo-filter. A geo-filter limits search to the bounds of the provided geometry. In the case of bounding box search the constraining geometry is the rectangle geometry. To build a bounding box filter the developer creates a BBox object with two coordinates (bottomLeft, topRight).

Key methods

Method Details
setQuery(String query) Free form search text indicating search intent
Note: category or brand filter can be used in place of query text
setGeoFilter(BBoxGeoFilter geoFilter) The rectangle geofilter created above

Sample 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
BBox bBox = BBox
    .builder()
    .setBottomLeft(37.373974, -122.057767)
    .setTopRight(37.394161, -122.026524)
    .build();

BBoxGeoFilter geoFilter = BBoxGeoFilter
    .builder(bBox)
    .build();

SearchFilters geoSearchFilters = SearchFilters
    .builder()
    .setGeoFilter(geoFilter)
    .build();

entityClient.searchRequest()
    .setQuery("food")
    .setLocation(37.12419, -121.98828)
    .setFilters(geoSearchFilters)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            List<Entity> resultEntities = response.getResults();

            for (Entity entity : resultEntities) {
                if (entity.getType() == EntityType.PLACE) {
                    LOG.info("Found Places: {}", entity.getPlace().getName());
                }
            }

        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("BBOX search failed", t);
        }
    });
 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
val bBox = BBox
    .builder()
    .setBottomLeft(37.373974, -122.057767)
    .setTopRight(37.394161, -122.026524)
    .build()

val geoFilter = BBoxGeoFilter
    .builder(bBox)
    .build()

val geoSearchFilters = SearchFilters
    .builder()
    .setGeoFilter(geoFilter)
    .build()

entityClient.searchRequest()
    .setQuery("food")
    .setLocation(37.12419, -121.98828)
    .setFilters(geoSearchFilters)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            val resultEntities = response.results
            for (entity in resultEntities) {
                if (entity.type == EntityType.PLACE) {
                    Log.i("sdk", "Found Places: ${entity.place.name}")
                }
            }
        }

        override fun onFailure(t: Throwable) {
            Log.e("sdk", "BBOX search failed", t)
        }
    })

Reverse Geocoding

Reverse geocoding (rgc) provides methods to convert a geographic coordinate into a real world address. When using rgc the only entity type returned is an address. RGC is useful when application needs to display an address (or city) from a given location.

To instruct the search request to utilize reverse geocoding the search intent must be set for rgc and the location as a geopoint must be provided.

Key methods

Method Details
setIntent(Intent intent) Set to the enum REVERSE_GEOCODING to indicate reverse geocoding
setLocation(double latitude, double longitudet) The coordinates to indicate current vehicle position. For example, location=37.1245,-122.45678.
setAnchor(double latitude, double longitude) The coordinate used to RGC to equivalent address. If not set, the location will be treated as anchor. For example, location=37.1245,-122.45678.
setSearchOptions(SearchOptions options) Applies the search intent to search request

Sample 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
SearchOptions searchOptions = SearchOptions.builder()
    .setIntent(SearchOptions.Intent.REVERSE_GEOCODING)
    .build();

entityClient.searchRequest()
    .setLocation(37.12419, -121.98828)
    .setSearchOptions(searchOptions)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            List<Entity> resultEntities = response.getResults();
            for (Entity entity : resultEntities) {
                if (entity.getType() == EntityType.ADDRESS) {
                    LOG.info("Found Address: " + entity.getAddress().getFormattedAddress());
                }
            }
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("RGC failed", t);
        }
    });
 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
val searchOptions = SearchOptions.builder()
    .setIntent(SearchOptions.Intent.REVERSE_GEOCODING)
    .build()

entityClient.searchRequest()
    .setLocation(37.12419, -121.98828)
    .setSearchOptions(searchOptions)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            val resultEntities = response.results
            for (entity in resultEntities) {
                if (entity.type == EntityType.ADDRESS) {
                    Log.i("sdk", "Found Address: ${entity.address.formattedAddress}")
                }
            }
        }

        override fun onFailure(t: Throwable) {
            Log.e("sdk", "RGC failed", t)
        }
    })

In addition, there is a special type of RGC that supports returning both Address and Place around the specified location, it's triggered by setting latitude,longitude as query parameter and SearchOptions.intent set as AROUND or keep as the default value.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
entityClient.searchRequest()
    .setLocation(37.92021,-122.31476)
    .setQuery("37.92021,-122.31476")
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));
        }

        @Override
        public void onFailure(Throwable throwable) {

        }
    });
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
entityClient.searchRequest()
    .setLocation(37.92021,-122.31476)
    .setQuery("37.92021,-122.31476")
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: response) {
            for (entity in response.results) {
                // log response in JSON format
                Log.i("sdk", EntityJsonConverter.toPrettyJson(response))
            }
        }

        override fun onFailure(t: Throwable) {

        }
    })

Search supports both free text and structured text queries for voice search use cases. Typically, a speech to text engine will accept voice input and convert into text; the converted text can be ‘parsed’ with tags assigned and sent as a query to search as structured (tagged) text or ‘unparsed’ and sent as a free text query. The Search API supports such structured text with tags and a speech to text engine can use these tags to build a structured query.

Query Tags

Tag Description
WHAT Tag used for POI name, chain name or category label.
WHERE Tag that indicates a full address or partial address including street and/or city.
CATEGORYID Id of the identified category.
ALT_WHAT Alternate homophonic WHAT
ALT_WHERE Alternate homophonic WHERE
;(semi colon) Tag separator
|| (double pipe) Homophonic group separator

("Alternate homophonic" words are alternate words for the same sound)

Query Syntax

query=tag1=v1;tag2=v2||tag3=v3;tag4=v4;...

  • Query Example
Voice Input Search Query
Find McDonald's WHAT=McDonald's
Find Restaurant CATEGORYID=226
Find Great America Parkway WHERE=Great America Parkway
Find Restaurant near Great America Parkway CATEGORYID=226;WHERE=Great America Parkway
Find McDonald's near Great America Parkway WHAT=McDonald’s;WHERE=Great America Parkway
Find McDonald's restaurant near Great America Parkway CATEGORYID=226;WHAT=McDonald's;WHERE=Great America Parkway
  • Query Examples (with homophones)
Voice Input NLU Candidates Search Query
Find McDonald's POI: McDonald's | Mac Donalds | MacDonald's WHAT=McDonald's||ALT_WHAT=Mac Donalds||ALT_WHAT= MacDonald's
Find Fischer Street Street: Fisher Street | Fischer Street | Ficher Street WHERE=Fisher Street||ALT_WHERE=Fischer Street||ALT_WHERE=Ficher Street
Find McDonald's near Fischer Street POI: McDonald's | Mac Donalds | MacDonald's
Street: Fischer Street
WHAT=McDonald's;WHERE=Fisher Street||ALT_WHAT=Mac Donalds;ALT_WHERE=Fisher Street||ALT_WHAT= MacDonald's;ALT_WHERE=Fisher Street
Find McDonalds near Fischer Street POI: McDonald's | Mac Donalds | MacDonald's
Street: Fisher Street | Fischer Street | Ficher Street

Note: if there are various combinations, preferably use only top 3 alternatives
WHAT=McDonald’s;WHERE=Fisher Street||ALT_WHAT= McDonald’s;ALT_WHERE= Fischer Street||ALT_WHAT= MacDonald’s;ALT_WHERE=Fisher Street

Sample 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
75
76
SearchOptions searchOptions = SearchOptions.builder()
    .setTrigger(SearchOptions.Trigger.VOICE)
    .build();

// Simple tag query
entityClient.searchRequest()
    .setQuery("WHAT=McDonald's")
    .setLocation(37.12419, -121.98828)
    .setSearchOptions(searchOptions)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            // handle success response
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Search request failed with exception", t);
        }
    });

// Using MultiboxQuery to build tag query
entityClient.searchRequest()
    .setQuery(MultiboxQuery.builder()
            .addTag(Tag.WHAT, "McDonald's")
            .addTag(Tag.CATEGORYID, "226")
            .build())
    .setLocation(37.12419, -121.98828)
    .setSearchOptions(searchOptions)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            // handle success response
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Search request failed with exception", t);
        }
    });

// Using MultiboxQuery to build homophonic group tag query
entityClient.searchRequest()
    .setQuery(MultiboxQuery.builder()
            .addTag(Tag.WHAT, "McDonald's")
            .addTag(Tag.CATEGORYID, "226")
            .newGroup()
            .addTag(Tag.ALT_WHAT, "Mac Donalds")
            .newGroup()
            .addTag(Tag.ALT_WHAT, "MacDonald's")
            .build())
    .setLocation(37.12419, -121.98828)
    .setSearchOptions(searchOptions)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            // handle success response
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Search request failed with exception", t);
        }
    });
 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
val searchOptions = SearchOptions.builder()
    .setTrigger(SearchOptions.Trigger.VOICE)
    .build()

// Simple tag query
entityClient.searchRequest()
    .setQuery("WHAT=McDonald's")
    .setLocation(37.12419, -121.98828)
    .setSearchOptions(searchOptions)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            // handle success response
        }

        override fun onFailure(t: Throwable) {
            LOG.e("Search request failed with exception", t);
        }
    })

// Using MultiboxQuery to build tag query
entityClient.searchRequest()
    .setQuery(MultiboxQuery.builder()
          .addTag(Tag.WHAT, "McDonald's")
          .addTag(Tag.CATEGORYID, "226")
          .build())
    .setLocation(37.12419, -121.98828)
    .setSearchOptions(searchOptions)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            // handle success response
        }

        override fun onFailure(t: Throwable) {
            LOG.e("Search request failed with exception", t);
        }
    })

// Using MultiboxQuery to build homophonic group tag query
entityClient.searchRequest()
    .setQuery(MultiboxQuery.builder()
          .addTag(Tag.WHAT, "McDonald's")
          .addTag(Tag.CATEGORYID, "226")
          .newGroup()
          .addTag(Tag.ALT_WHAT, "Mac Donalds")
          .newGroup()
          .addTag(Tag.ALT_WHAT, "MacDonald's")
          .build())
    .setLocation(37.12419, -121.98828)
    .setSearchOptions(searchOptions)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            // handle success response
        }

        override fun onFailure(t: Throwable) {
            LOG.e("Search request failed with exception", t);
        }
    })

There are specialized classes available specifically for electric charge station category. These classes enable filtering search by important characteristics for the electric vehicle driver. In addition there are classes which are associated with entity details of a charge station such as connector types, connector counts, power feed type, and charge network (brand).

To build these features the developer will use the EVFilter class.

Filter by Charge Network

This feature enables a driver to find EV charge stations for a specific charging network such as Chargepoint or EVgo. To filter charge station search by network use the .setChargerBrands method within EvFilter.Builder().The following table shows some common charge networks and their respective ids:

ID Charge Network
99100001 ChargePoint
99100002 Blink
99100003 eVgo
99100010 ElectrifyAmerica

Filter by Connector Type

This feature enables a driver to find EV charge stations by specific connector type such as J1772, CCS, etc. To filter charge stations by connector type use the .setConnectorTypes method within EvFilter.Builder(). The below table contains examples of commonly used connector types:

ID Connector Type
30001 J1772
30002 SAE Combo
30003 CHAdeMO
30004 Type 2
30005 Type 3
30006 Tesla
30007 NEMA
30008 NEMA 14-50
30009 Plug Type F

Filter by Charge Level

This feature enables a drive to find EV charge stations by specific power (charge) level such as Level 2 or DC Fast. To filter stations by charge level use the .setPowerFeedLevels method within EvFilter.Builder(). Currently supported power levels are:

ID Power Level
1 Level 1
2 Level 2
5 DC Fast
6 Ultra Fast

Filter for free chargers

This feature allows users to find EV charge stations that are free to use. When this filter is set to true only free connectors are returned, when set to false only paid connectors are returned, and when set to null all connectors are returned.

Filter by power

This feature enables a drive to find EV charge stations by specific power range in KW. To filter charge stations by power use the .setMinPower & .setMaxPower method within EvFilter.Builder().

Sample 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
entityClient.searchRequest()
    .setLocation(37.92021, -122.31476)
    .setQuery("ev station")
    .setFilters(SearchFilters.builder()
            .setEvFilter(EvFilter.builder()
                    .setChargerBrands(Arrays.asList("99100001"))
                    .setConnectorTypes(Arrays.asList("30001", "30002"))
                    .setPowerFeedLevels(Arrays.asList(1, 2))
                    .setFreeCharge(true)
                    .setMinPower(32.0)
                    .build())
            .build())
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));
        }

        @Override
        public void onFailure(Throwable throwable) {

        }
    });
 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
entityClient.searchRequest()
    .setLocation(37.92021, -122.31476)
    .setQuery("ev station")
    .setFilters(SearchFilters.builder()
            .setEvFilter(EvFilter.builder()
                    .setChargerBrands(Arrays.asList("99100001"))
                    .setConnectorTypes(Arrays.asList("30001", "30002"))
                    .setPowerFeedLevels(Arrays.asList(1, 2))
                    .setFreeCharge(true)
                    .setMinPower(32.0)
                    .build())
            .build())
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: response) {
            for (entity in response.results) {
                // log response in JSON format
                Log.i("sdk", EntityJsonConverter.toPrettyJson(response))
            }
        }

        override fun onFailure(t: Throwable) {

        }
    })

EV feature also supports two special search:

Exclusion filter: Specify the EV network to be excluded.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
entityClient.searchRequest()
    .setLocation(37.92021, -122.31476)
    .setQuery("ev station")
    .setFilters(SearchFilters.builder()
        .setEvFilter(EvFilter.builder()
            .setChargerBrands(Arrays.asList("99100001"), FilterType.EXCLUDE)
            .build())
        .build())
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));
        }

        @Override
        public void onFailure(Throwable throwable) {

        }
    });
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
entityClient.searchRequest()
    .setLocation(37.92021, -122.31476)
    .setQuery("ev station")
    .setFilters(SearchFilters.builder()
        .setEvFilter(EvFilter.builder()
            .setChargerBrands(Arrays.asList("99100001"), FilterType.EXCLUDE)
            .build())
        .build())
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: response) {
            for (entity in response.results) {
                // log response in JSON format
                Log.i("sdk", EntityJsonConverter.toPrettyJson(response))
            }
        }

        override fun onFailure(t: Throwable) {

        }
    })

Searching by OCPI location ID:

 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
entityClient.searchRequest()
    .setLocation(37.92021, -122.31476)
    .setQuery(MultiboxQuery.builder()
        .addTag(Tag.OCPI_LOCATION_ID, "USCPIL9813")
        .build())
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));
        }

        @Override
        public void onFailure(Throwable throwable) {

        }
    });

// or
entityClient.searchRequest()
    .setLocation(37.92021, -122.31476)
    .setQuery("OCPI_LOCATION_ID=USCPIL9813")
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));
        }

        @Override
        public void onFailure(Throwable throwable) {

        }
    });
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
entityClient.searchRequest()
    .setLocation(37.92021, -122.31476)
    .setQuery(MultiboxQuery.builder()
        .addTag(Tag.OCPI_LOCATION_ID, "USCPIL9813")
        .build())
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: response) {
            for (entity in response.results) {
                // log response in JSON format
                Log.i("sdk", EntityJsonConverter.toPrettyJson(response))
            }
        }

        override fun onFailure(t: Throwable) {

        }
    })

Usually the location used for current vehicle position (CVP) and search point is the same. When the vehicle position and the desired search location are not the same, the search location can be specified by setting parameter anchor.

  • If both location and anchor exist:
    • location will be used as current vehicle position to calculate driving distance and driving time.
    • anchor will be used as search location.
  • if only location exist:
    • location will be used as the current vehicle position and search position.

Key methods

Method Details
setLocation(double latitude, double longitude) A geopoint value of the user’s location using geographic coordinates of latitude and longitude separated by comma). For example, location=37.1245,-122.45678.
setAnchor(double latitude, double longitude) A geopoint value of the search location using geographic coordinates of latitude and longitude separated by comma). For example, location=37.1245,-122.45678.
setQuery(String query) Free form search text indicating search intent.
Note: brand or category filter can be used in place of query text.


Sample 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
entityClient.searchRequest()
    .setQuery("Fast Food")
    .setLocation(37.12419, -121.98828)
    .setAnchor(37.32587,-121.86442)
    .asyncCall(new Callback<EntitySearchResponse>() {

        @Override
        public void onSuccess(EntitySearchResponse response) {
            // log response in JSON format
            LOG.info(EntityJsonConverter.toPrettyJson(response));

            List<Entity> resultEntities = response.getResults();
            if (resultEntities == null || resultEntities.isEmpty()) {
                LOG.info("No result found");
                return;
            }
            for (Entity entity : resultEntities) {
                if (entity.getType() == EntityType.ADDRESS) {
                    LOG.info("Found Address: " + entity.getAddress().getFormattedAddress());
                } else if (entity.getType() == EntityType.PLACE) {
                    LOG.info("Found Place: " + entity.getPlace().getName());
                }
            }
        }

        @Override
        public void onFailure(Throwable t) {
            LOG.error("Get unsuccessful response or throwable happened when executing the request.", t);
        }
    });
 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
entityClient.searchRequest()
    .setQuery("Fast Food")
    .setLocation(37.12419, -121.98828)
    .setAnchor(37.32587,-121.86442)
    .asyncCall(object : Callback<EntitySearchResponse> {

        override fun onSuccess(response: EntitySearchResponse) {
            // log response in JSON format
            Log.i("sdk", EntityJsonConverter.toPrettyJson(response))

            val resultEntities = response.results
            if (resultEntities == null || resultEntities.isEmpty()) {
                Log.i("sdk", "No result found")
                return
            }
            for (entity in resultEntities) {
                if (entity.type == EntityType.ADDRESS) {
                    Log.i("sdk", "Found Address: ${entity.address.formattedAddress}")
                } else if (entity.type == EntityType.PLACE) {
                    Log.i("sdk", "Found Place: ${entity.place.name}")
                }
            }
        }

        override fun onFailure(t: Throwable) {
            Log.e("sdk", "Get unsuccessful response or throwable happened when executing the request.", t)
        }
    })