Skip to content

Search

This section explains how to implement online, offline or hybrid (mixed) geocoding and search into your Android application.

Autocomplete, Geocoding and SearchPlaces

Applications developed with the Sygic Maps SDK can use geocoding to transform textual query into geographical information. With the SearchManager you can perform three basic actions : Geocoding, ReverseGeocoding and Autocomplete.

Note

If you use the online services, you might want to define to send a request once every 300ms or so, otherwise some requests might end up with an error TOO_MANY_REQUESTS.

The search has three types of search Sessions: (offline, online and hybrid): Offline - search using offline maps only Online - search using online search API only Hybrid - use both offline and online search

A Search session has a limited lifetime which follows this call graph

1) create the search session
2) do [0..N] autocomplete requests 
3) then either of:
    - do nothing
    - geocode with location ID
    - geocode with query
    - do [0..N] search places requests with continuation token
4) close the session

After finding the desired result in autocomplete, you can take its locationID and call Geocode() with it to get more precise information about the location. If you do not need to use autocomplete and have the full string that you want to search for, just use Geocode straight away.

When searching for places, you can create a new placeRequest and use your position, the categories that you want to search for and several other arguments.

For example, offline autocomplete search session with geocode operation may look like this:

val searchManager = SearchManagerProvider.getInstance().get()
val position = GeoCoordinates(51.510175, -0.122445)
val searchRequest = SearchRequest("London Eye", position)
val session = searchManager.newOfflineSession()

session.autocomplete(searchRequest, object : AutocompleteResultListener {
    override fun onAutocomplete(autocompleteResult: List<AutocompleteResult>) {
        // handle results
    }

    override fun onAutocompleteError(status: ResultStatus) {}
})
session.geocode(searchRequest, object : GeocodingResultsListener {
    override fun onGeocodingResults(geocodingResults: List<GeocodingResult>) {
        // handle results
    }

    override fun onGeocodingResultsError(status: ResultStatus) {}
})

...

// close session when you are done with handling results
searchManager.closeSession(session)
````

Or hybrid place search session:

=== "Kotlin"

````kotlin
val searchManager = SearchManagerProvider.getInstance().get()
val categories = listOf("SYTouristInformationOffice", "SYMuseum")
val placeRequest = PlaceRequest(position, categories, /*radius*/ 1000)
val session = searchManager.newHybridSession()

session.searchPlaces(placeRequest, object : PlacesListener {
    override fun onPlacesLoaded(places: List<Place>, continuationToken: String?) {
        // handle results
    }

    override fun onPlacesError(status: ResultStatus) {}
})

...

// close session when you are done with handling results
searchManager.closeSession(session)

Reverse geocoding

Reverse geocoding is the opposite process to geocoding, meaning you query by geographical location and receive textual address of the location. You can define a filter if you do not want to take walkways into account or pass it an emptySet.

ReverseGeocoderProvider.getInstance(object : CoreInitCallback<ReverseGeocoder> {
    override fun onInstance(reverseGeocoder: ReverseGeocoder) {
        reverseGeocoder.reverseGeocode(position, emptySet(), object : ReverseGeocoder.ReverseGeocodingResultListener {
            override fun onReverseGeocodingResult(result: List<ReverseGeocodingResult>) {
                // do not forget to filter out the walkways if you do not want them
            }

            override fun onReverseGeocodingResultError(code: ReverseGeocoder.ErrorCode) {}
        })
    }

    override fun onError(error: CoreInitException) {}
})

During the implementation you will probably stumble upon a task of navigating to a search result. Let's see a simple example of how this would be achieved. Please bear in mind that in this example we do it in a simple callback succession and it's probably not what would be desired to exist in a complete application.

val search: com.sygic.sdk.search.SearchManager = SearchManagerProvider.getInstance().get() // make sure that it's not the Android's Search Manager
val searchRequest = SearchRequest("champs-elysees 121", GeoCoordinates(48.2879167, 17.2636084))
val searchSession = search.newOnlineSession()
val router = RouterProvider.getInstance().get()

searchSession.autocomplete(searchRequest, object : AutocompleteResultListener {
  override fun onAutocomplete(autocompleteResult: List<AutocompleteResult>) {
    // here you can show the list of the results to the user
    // the results contain info such as distance to the result, its type, or which parts of the text were matched
    // let's suppose that the user chooses the first result (usually the most relevant one)
    // now let's take the locationID and use it for calling the geocode() function
    searchSession.geocode(GeocodeLocationRequest(autocompleteResult[0].locationId), object : GeocodingResultListener {
        override fun onGeocodingResult(geocodingResult: GeocodingResult) {
            // this is where you get detailed information about the result
            // you also get the GeoCoordinates of the object
            val routePlan = RoutePlan() // create a route plan
            routePlan.setStart(your-last-known-location) // set the start point
            routePlan.setDestination(geocodingResult.location) // set the destination point - using the GeocodingResult
            router.computeRoute(routePlan, object: Router.RouteComputeListener{}) // compute the route. more in the Routing section
        }

        override fun onGeocodingResultError(status: ResultStatus) {
          // handle the errors here
        }
    })
  }

  override fun onAutocompleteError(status: ResultStatus) {
    // handle the errors here
  }
})