Search for an address
Learn how to find an address or place with a search bar and the Geocoding service.

Geocoding is the process of converting address or place text into a location. The Geocoding service can search for an address or a place and perform reverse geocoding.
In this tutorial, you use a search bar in the user interface to access the Geocoding service and search for addresses and places.
To learn how to use the Geocoding service to reverse geocode, visit the Reverse geocode tutorial.
Prerequisites
The following are required for this tutorial:
- An ArcGIS account to access API keys. If you don't have an account, sign up for free.
- Confirm that your system meets the system requirements.
- An IDE for Android development in Kotlin.
Steps
Open an Android Studio project
To start this tutorial, complete the Display a map tutorial, or download and unzip the solution in a new folder.
Modify the old project for use in this new tutorial. Expand More info for instructions.
On your file system, delete the .idea folder, if present, at the top level of your project.
In the Android tool window, open app > res > values > strings.xml.
In the
<string name="app_name">
element, change the text content to Search for an address.strings.xmlChange line 1 2 2 3<resources> <string name="app_name">Search for an address</string> <string name="search_hint">Search for an address</string> </resources>
In the Android tool window, open Gradle Scripts > settings.gradle.
Change the value of
rootProject.name
to "Search for an address".settings.gradleChange line 1 2include ':app' rootProject.name = "Search for an address"
Click File > Sync Project with Gradle files. Android Studio will recognize your changes and create a new .idea folder.
If you downloaded the solution project, set your API key.
An API Key enables access to services, web maps, and web scenes hosted in ArcGIS Online.
Go to your developer dashboard to get your API key. For these tutorials, use your default API key. It is scoped to include all of the services demonstrated in the tutorials.
In Android Studio: in the Android tool window, open app > java > com.example.app > MainActivity.
In the
setupMap
function, set theapiKey
property on theArcGISRuntimeEnvironment
with your API key.MainActivity.ktChange line Change line Change line Change line 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 80 80/* * Copyright 2020 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.MapView import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle streets val map = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) // set the map to be displayed in the layout's MapView mapView.map = map // set the viewpoint, Viewpoint(latitude, longitude, scale) mapView.setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) } }
Add import statements and variable declarations
Add import statements and variable declarations to reference the packages and classes required for this tutorial.
In Android Studio, in the Android tool window, open app > java > com.example.app > MainActivity.
Add the following imports to the existing imports:
MainActivity.ktAdd line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
Declare graphics overlay and locator task and initialize map view
A graphics overlay is a container for graphics. A locator task converts an address to a point. You will create the properties graphicsOverlay
and locatorTask
for use later in later steps. Next you will initialize the mapView
.
In the
MainActivity
method, create a lazy property namedgraphicsOverlay
that references a newGraphicsOverlay
for storing geocode result graphics (address location and label).Since
graphicsOverlay
is a lazy property, aGraphicsOverlay
will not be created until the property is initialized, which occurs in thesetupMap()
method that you will modify shortly.MainActivity.ktAdd line. Add line. Add line. 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 54 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 52 51 50 49 48 47 46 45 45 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 28 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -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 -27/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
Create a property named
locatorTask
that references a newLocatorTask
for geocoding an address.MainActivity.ktAdd line. 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 54 53 52 51 50 49 48 47 47 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 30 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -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 -25/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
At the end of the
setupMap
method, initialize themapView
by calling the scope functionapply
and passing a lambda expression that does the following:- assigns the local variable
arcGISmap
to themap
property - creates a
Viewpoint
and pass it tosetViewpoint()
- adds
graphicsOverlay
to thegraphicsOverlays
collection.
Declared at the start of the
MainActivity
class, the lazy propertygraphicsOverlay
is initialized at its first access, which is in this lambda expression. The newGraphicsOverlay
is not created until now.MainActivity.ktAdd line. Add line. Add line. Add line. Add line. Add line. Add line. 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 82 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 84 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 29/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
- assigns the local variable
Add a UI for user input
To search an address using the application, add a UI element to prompt the user for text input.
In activity_main.xml, add a
SearchView
element. This widget will display a search text field at the top of the app window.activity_main.xmlAdd line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 2 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <SearchView android:id="@+id/searchView" android:layout_width="0dp" android:layout_height="0dp" android:queryHint="@string/search_hint" app:layout_constraintBottom_toTopOf="@+id/guideline" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.08" /> <com.esri.arcgisruntime.mapping.view.MapView android:id="@+id/mapView" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/guideline" /> </androidx.constraintlayout.widget.ConstraintLayout>
In MainActivity.kt, create a
setupSearchViewListener()
method to handle user activity by changing the current address in the search field and submitting the search. In the first line, get the boundsearchView
by callingactivityMainBinding.searchView
. Then callsetOnQueryTextListener()
and pass an anonymous class that implements theSearchView.OnQueryTextListener
interface.MainActivity.ktAdd line. 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 105 106 107 108 108 108 108 108 108 108 108 108 108 108 108 109 109 109 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 54/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
Implement the two methods of the
SearchView.OnQueryTextListener
interface:onQueryTextChange()
andonQueryTextSubmit()
.- Returning
false
specifies the standard Android behavior.
MainActivity.ktAdd line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 105 106 107 108 109 110 111 112 113 114 114 114 115 116 117 118 118 118 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 63/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
- Returning
Create a function to geocode an address
Geocoding is implemented with a locator, typically created by referencing a service such as the Geocoding service or, for offline geocoding, by referencing locator data contained in a mobile package. Geocoding parameters can be used to refine the results, such as setting a maximum number of results or requesting additional attributes in the results.
Create a method named
performGeocode()
.Create a new
GeocodeParameters
method and initialize it by calling the scope functionapply
and passing a lambda expression that does the following:- Adds the names of result attributes to the
resultAttributeNames
collection. These are the names of attributes to be returned. An asterisk (*
) indicates all attributes. - Sets
maxResults
to the maximum number of results to be returned.Results are ordered by score
, so that the first result has the best match score (ranging from 0 for no match to 100 for the best match). - Sets
outputSpatialReference
to the spatial reference for result locations.By default, the output spatial reference is defined by the geocode service. For optimal performance when displaying the geocode result, you can ensure that returned coordinates match those of the map view by providing the map view's spatial reference.
When geocoding an address, you can optionally provide
GeocodeParameters
to control certain aspects of the geocoding operation and specify the kinds of results to return from the locator task. Learn more about these parameters in the API documentation. For a list of attributes returned with geocode results, see Geocoding service output in the REST API documentation.MainActivity.ktAdd line. Add line. Add line. Add line. Add line. 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 122 121 121 121 121 121 121 121 121 122 123 124 125 126 127 128 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 130 130 129 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 101/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
- Adds the names of result attributes to the
To find the location for the provided address, call
geocodeAsync()
on thelocatorTask
, passing thequery
(the address to find) and thegeocodeParameters
. The call returns aListenableFuture
, which you should store in the read-only variablegeocodeResultFuture
.MainActivity.ktAdd line. 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 122 121 121 121 121 121 121 121 121 122 123 124 125 126 127 128 129 130 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 132 132 131 130 129 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 103/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
Call
addDoneListener
ongeocodeResultFuture
and specify a lambda expression to be executed when geocoding is complete. In the lambda, calldisplayResult(geocodeResult[0])
to display the first item in thegeocodeResult
list. This is the location of the address on the map.In this tutorial, the maximum results parameter was set to 1, so you pass the first and only item in the geocodeResult
list.MainActivity.ktAdd line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 122 121 121 121 121 121 121 121 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 146 145 144 143 142 141 140 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 119 118 117 117/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
In the
setupSearchViewListener()
method, callperformCode()
.MainActivity.ktAdd line. 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91 91/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbology.TextSymbol import com.esri.arcgisruntime.tasks.geocode.GeocodeParameters import com.esri.arcgisruntime.tasks.geocode.GeocodeResult import com.esri.arcgisruntime.tasks.geocode.LocatorTask import com.example.app.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val mapView: MapView by lazy { activityMainBinding.mapView } private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } private val locatorTask = LocatorTask("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(activityMainBinding.root) setupMap() setupSearchViewListener() } override fun onPause() { mapView.pause() super.onPause() } override fun onResume() { super.onResume() mapView.resume() } override fun onDestroy() { mapView.dispose() super.onDestroy() } // set up your map here. You will call this method from onCreate() private fun setupMap() { // set your API key // Note: it is not best practice to store API keys in source code. The API key is referenced // here for the convenience of this tutorial. ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") // create a map with the BasemapStyle topographic val arcGISmap = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC) mapView.apply { // set the map to be displayed in the layout's MapView map = arcGISmap // set the viewpoint, Viewpoint(latitude, longitude, scale) setViewpoint(Viewpoint(34.0270, -118.8050, 72000.0)) graphicsOverlays.add(graphicsOverlay) } } private fun setupSearchViewListener() { activityMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextChange(newText: String): Boolean { return false } override fun onQueryTextSubmit(query: String): Boolean { performGeocode(query) return false } }) } private fun performGeocode(query: String) { val geocodeParameters = GeocodeParameters().apply { resultAttributeNames.add("*") maxResults = 1 outputSpatialReference = mapView.spatialReference } val geocodeResultFuture = locatorTask.geocodeAsync(query, geocodeParameters) geocodeResultFuture.addDoneListener { try { val geocodeResult = geocodeResultFuture.get() if (geocodeResult.isNotEmpty()) { displayResult(geocodeResult[0]) } else { Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(MainActivity::class.simpleName, "Error getting result" + e.message) } } } private fun displayResult(geocodeResult: GeocodeResult) { // clear the overlay of any previous result graphicsOverlay.graphics.clear() // create a graphic to display the address text val textSymbol = TextSymbol( 18f, geocodeResult.label, Color.BLACK, TextSymbol.HorizontalAlignment.CENTER, TextSymbol.VerticalAlignment.BOTTOM ) val textGraphic = Graphic(geocodeResult.displayLocation, textSymbol) graphicsOverlay.graphics.add(textGraphic) // create a graphic to display the location as a red square val simpleMarkerSymbol = SimpleMarkerSymbol(SimpleMarkerSymbol.Style.SQUARE, Color.RED, 12.0f) val markerGraphic = Graphic(geocodeResult.displayLocation, geocodeResult.attributes, simpleMarkerSymbol) graphicsOverlay.graphics.add(markerGraphic) mapView.setViewpointCenterAsync(geocodeResult.displayLocation) } }
Display the result
The result obtained from the geocode operation can be displayed by adding two graphics to the map view's graphics overlay: one graphic that shows the address text and the other a red location marker.
Create a method named
displayResult()
and clear the graphics overlay of any previous result.MainActivity.ktAdd line. Add line. 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 150 151 152 153 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 155 155 155/* * Copyright 2021 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.app import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.SearchView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.esri.arcgisruntime.ArcGISRuntimeEnvironment import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.BasemapStyle import com.esri.arcgisruntime.mapping.Viewpoint import com.esri.arcgisruntime.mapping.view.Graphic import com.esri.arcgisruntime.mapping.view.GraphicsOverlay import com.esri.arcgisruntime.mapping.view.MapView import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol import com.esri.arcgisruntime.symbol