A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developers.arcgis.com/kotlin/geocode-and-search/tutorials/search-for-an-address/ below:

Search for an address | ArcGIS Maps SDK for Kotlin

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.

Mapping and location services guide

For more background information about the topics in this tutorial, visit Geocode in the Mapping and location services guide. To learn more about the service, visit Geocoding service.

Prerequisites

Before starting this tutorial, you need the following:

  1. An ArcGIS Location Platform or ArcGIS Online account.

  2. A development and deployment environment that meets the system requirements.

  3. An IDE for Android development in Kotlin.

Note

It is recommended that you use the latest stable version Android Studio to create this tutorial app. The code described in the steps below, however, should work in any up-to-date Android IDE that supports Kotlin.

Set up authentication

To access the secure ArcGIS location services used in this tutorial, you must implement API key authentication or user authentication using an ArcGIS Location Platform or an ArcGIS Online account.

You can implement API key authentication or user authentication in this tutorial. Compare the differences below:

API key authentication

Learn more in API key authentication.

User authentication

Learn more in User authentication.

Security and authentication guide

To learn more about the different types of authentication, visit Types of authentication.

Create a new API key access token with privileges to access the secure resources used in this tutorial.

  1. Complete the Create an API key tutorial and create an API key with the following privilege(s):

  2. Copy and paste the API key access token into a safe location. It will be used in a later step.

Create new OAuth credentials to access the secure resources used in this tutorial.

  1. Complete the Create OAuth credentials for user authentication tutorial to obtain a Client ID and Redirect URL.

    A Client ID uniquely identifies your app on the authenticating server. If the server cannot find an app with the provided Client ID, it will not proceed with authentication.

    The Redirect URL (also referred to as a callback url) is used to identify a response from the authenticating server when the system returns control back to your app after an OAuth login. Since it does not necessarily represent a valid endpoint that a user could navigate to, the redirect URL can use a custom scheme, such as my-app://auth. It is important to make sure the redirect URL used in your app's code matches a redirect URL configured on the authenticating server.

  2. Copy and paste the Client ID and Redirect URL into a safe location. They will be used in a later step.

All users that access this application need account privileges to access the ArcGIS Basemap Styles service and the ArcGIS Geocoding service.

Develop or download

You have two options for completing this tutorial:

  1. Option 1: Develop the code or
  2. Option 2: Download the completed solution
Option 1: Develop the code Open an Android Studio project
  1. Open the project you created by completing the Display a map tutorial.

  2. Continue with the following instructions to add a search bar to the user interface and search for an address or place using the ArcGIS Geocoding service.

  3. Modify the old project for use in this new tutorial.

    1. On your file system, delete the .idea folder, if present, at the top level of your project.

    2. In the Android view, open app > res > values > strings.xml.

      In the <string name="app_name"> element, change the text content to Search for an address.

      strings.xml

      Use dark colors for code blocks

      1
      2
      3
      4
      5
      <resources>
      
          <string name="app_name">Search for an address</string>
      
      </resources>
    3. In the Android view, open Gradle Scripts > settings.gradle.kts.

      Change the value of rootProject.name to "Search for an address".

      settings.gradle.kts

      Expand

      Use dark colors for code blocks
      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
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
              maven { url = uri("https://esri.jfrog.io/artifactory/arcgis") }
          }
      }
      
      rootProject.name = "Search for an address"
      include(":app")
    4. Click File > Sync Project with Gradle files. Android Studio will recognize your changes and create a new .idea folder.

Set developer credentials

If you implemented API key authentication in the Display a map tutorial, the API key access token will only have the Basemaps privilege. The Search for an address tutorial requires the Geocoding privilege to search for an address using the LocatorTask. To create an API Key access token that has the Basemaps and Geocoding privileges, see the Set up authentication step and then follow the instructions below.

  1. In the Android view of Android Studio, open app > kotlin+java > com.example.app > MainActivity.

  2. In the onCreate() lifecycle method of the MainActivity class, set the ArcGISEnvironment.apiKey​ property by calling ApiKey.create(). Pass in your API key access token as a string and don't forget the double quotes. Do this before the setContent block.

    MainActivity.kt

    Use dark colors for code blocks

    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
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            ArcGISEnvironment.apiKey = ApiKey.create("YOUR_ACCESS_TOKEN")
    

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Use the Authenticator toolkit component to manage your OAuth credentials and pass it to the ArcGISEnvironment.

  1. Open the app > kotlin+java > com.example.app > MainActivity.kt file.

  2. Set your clientID and redirectURL values.

    MainActivity.kt

    Use dark colors for code blocks

    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
            authenticatorState.oAuthUserConfigurations = listOf(
                OAuthUserConfiguration(
    
                    portalUrl = "https://www.arcgis.com",
                    clientId = "YOUR_CLIENT_ID",
                    redirectUrl = "YOUR_REDIRECT_URL"
    
                )
            )
    

Best Practice: The OAuth credentials are stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Add import statements and some Compose variables
  1. Modify import statements to reference the packages and classes required for this tutorial.

    Theme.kt

    Use dark colors for code blocks

    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    @file:OptIn(ExperimentalMaterial3Api::class)
    
    package com.example.app.screens
    
    import android.content.Context
    import android.widget.Toast
    import androidx.compose.foundation.layout.Column
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.foundation.layout.fillMaxWidth
    import androidx.compose.foundation.layout.padding
    import androidx.compose.material.icons.Icons
    import androidx.compose.material.icons.filled.Search
    import androidx.compose.material3.ExperimentalMaterial3Api
    import androidx.compose.material3.Icon
    import androidx.compose.material3.Scaffold
    import androidx.compose.material3.SearchBar
    import androidx.compose.material3.SearchBarDefaults
    import androidx.compose.material3.Text
    import androidx.compose.material3.TopAppBar
    import androidx.compose.runtime.Composable
    import androidx.compose.runtime.getValue
    import androidx.compose.runtime.mutableStateOf
    import androidx.compose.runtime.remember
    import androidx.compose.runtime.rememberCoroutineScope
    import androidx.compose.runtime.setValue
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.platform.LocalContext
    import androidx.compose.ui.platform.LocalFocusManager
    import androidx.compose.ui.res.stringResource
    import com.arcgismaps.Color
    import com.arcgismaps.geometry.SpatialReference
    import com.arcgismaps.mapping.ArcGISMap
    import com.arcgismaps.mapping.BasemapStyle
    import com.arcgismaps.mapping.Viewpoint
    import com.arcgismaps.mapping.symbology.HorizontalAlignment
    import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol
    import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle
    import com.arcgismaps.mapping.symbology.TextSymbol
    import com.arcgismaps.mapping.symbology.VerticalAlignment
    import com.arcgismaps.mapping.view.Graphic
    import com.arcgismaps.mapping.view.GraphicsOverlay
    import com.arcgismaps.tasks.geocode.GeocodeParameters
    import com.arcgismaps.tasks.geocode.GeocodeResult
    import com.arcgismaps.tasks.geocode.LocatorTask
    import com.arcgismaps.toolkit.geoviewcompose.MapView
    import com.arcgismaps.toolkit.geoviewcompose.MapViewProxy
    import com.example.app.R
    import kotlinx.coroutines.CoroutineScope
    import kotlinx.coroutines.Job
    import kotlinx.coroutines.launch
    
  2. In the MainScreen composable, create Compose variables that will be passed to various functions in the MainScreen.kt file.

    These are remembered state variables and use either remember() or rememberCoroutineScope()

    Briefly, these variables are as follows:

    Theme.kt

    Use dark colors for code blocks

    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    @Composable
    fun MainScreen() {
    
        val context = LocalContext.current
        val coroutineScope = rememberCoroutineScope()
        // The focus manager is used to dismiss keyboard after search query submission.
        val focusManager = LocalFocusManager.current
        var queryText by remember { mutableStateOf("") }
        val currentJob = remember { mutableStateOf<Job?>(null) }
        val graphicsOverlay = remember { GraphicsOverlay() }
        val graphicsOverlays = remember { listOf(graphicsOverlay) }
        val mapViewProxy = remember { MapViewProxy() }
        val currentSpatialReference = remember { mutableStateOf<SpatialReference?>(null) }
    
        val map = remember {
            createMap()
        }
    
        Scaffold(
            topBar = { TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) }) }
        ) {
    
                MapView(
                    modifier = Modifier.fillMaxSize(),
                    arcGISMap = map,
    
                )
    
        }
    
    }
    
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.

  1. Define a top-level suspend function named searchAddress(). Declare the parameters shown below.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    suspend fun searchAddress(
        context: Context,
        coroutineScope: CoroutineScope,
        query: String,
        currentSpatialReference: SpatialReference?,
        graphicsOverlay: GraphicsOverlay,
        mapViewProxy: MapViewProxy
    ) {
    
    }
    
  2. Create a LocatorTask based on the Geocoding service.

    A locator task is used to find the location of an address (geocode) or to interpolate an address for a location (reverse geocode). An address includes any type of information that distinguishes a place. A locator involves finding matching locations for a given address. Reverse-geocoding is the opposite and finds the closest address for a given location.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    suspend fun searchAddress(
        context: Context,
        coroutineScope: CoroutineScope,
        query: String,
        currentSpatialReference: SpatialReference?,
        graphicsOverlay: GraphicsOverlay,
        mapViewProxy: MapViewProxy
    ) {
    
        val geocodeServerUri = "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer"
        val locatorTask = LocatorTask(geocodeServerUri)
    
    }
    
  3. Create a new GeocodeParameters and define some of its properties.

    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 GeocodeParameters. For a list of attributes returned with geocode results, see Geocoding service output in the ArcGIS services reference.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    suspend fun searchAddress(
        context: Context,
        coroutineScope: CoroutineScope,
        query: String,
        currentSpatialReference: SpatialReference?,
        graphicsOverlay: GraphicsOverlay,
        mapViewProxy: MapViewProxy
    ) {
    
        val geocodeServerUri = "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer"
        val locatorTask = LocatorTask(geocodeServerUri)
    
        // Create geocode parameters
        val geocodeParameters = GeocodeParameters().apply {
            resultAttributeNames.add("*")
            maxResults = 1
            outputSpatialReference = currentSpatialReference
        }
    
    }
    
  4. To find the location for the address that the user entered, call LocatorTask.geocode(), passing the query and geocodeParameters variables.

    In the .onSuccess block, call the handleGeocodeResults() function (which we will define in a later section). Pass parameters to handleGeocodeResults() as shown below.

    The geocode results are implemented as a list of GeocodeResult objects. In this tutorial, either one or zero results will be returned, as the maximum results parameter was set to 1.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    suspend fun searchAddress(
        context: Context,
        coroutineScope: CoroutineScope,
        query: String,
        currentSpatialReference: SpatialReference?,
        graphicsOverlay: GraphicsOverlay,
        mapViewProxy: MapViewProxy
    ) {
    
        val geocodeServerUri = "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer"
        val locatorTask = LocatorTask(geocodeServerUri)
    
        // Create geocode parameters
        val geocodeParameters = GeocodeParameters().apply {
            resultAttributeNames.add("*")
            maxResults = 1
            outputSpatialReference = currentSpatialReference
        }
    
        // Search for the address
        locatorTask.geocode(searchText = query, parameters = geocodeParameters)
            .onSuccess { geocodeResults: List<GeocodeResult> ->
                handleGeocodeResults(
                    context, coroutineScope, geocodeResults, graphicsOverlay, mapViewProxy
                )
            }.onFailure { error ->
                showMessage(context, "The locatorTask.geocode() call failed: ${error.message}")
            }
    
    }
    
Create two graphics

You will create a graphic that uses a text symbol to display the address as a string. You will create another graphic that uses a red square to indicate the location on the map.

  1. Define a top-level function named createTextGraphic() and declare a GeocodeResult parameter. For the text of the TextSymbol, use the GeocodeResult.label property. For the geometry of the Graphic, use the GeocodeResult.displayLocation property.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    fun createTextGraphic(geocodeResult: GeocodeResult): Graphic {
        val textSymbol = TextSymbol(
            text = geocodeResult.label,
            color = Color.black,
            size = 18f,
            horizontalAlignment = HorizontalAlignment.Center,
            verticalAlignment = VerticalAlignment.Bottom
        ).apply {
            offsetY = 8f
            haloColor = Color.white
            haloWidth = 2f
        }
        return Graphic(
            geometry = geocodeResult.displayLocation,
            symbol = textSymbol
        )
    }
    
  2. Define a top-level function named createMarkerGraphic() and declare a GeocodeResult parameter. For the geometry of the Graphic, use the GeocodeResult.label property. For the attributes of the Graphic, use the GeocodeResult.attributes property.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    fun createMarkerGraphic(geocodeResult: GeocodeResult): Graphic {
        val simpleMarkerSymbol = SimpleMarkerSymbol(
            style = SimpleMarkerSymbolStyle.Square,
            color = Color.red,
            size = 12.0f
        )
        return Graphic(
            geometry = geocodeResult.displayLocation,
            attributes = geocodeResult.attributes,
            symbol = simpleMarkerSymbol
        )
    }
    
Display the result

The result obtained from the geocode operation can be displayed by adding the two graphics you just created to the map view's graphics overlay.

Tutorial

To learn more about graphics and graphics overlays, see the Add a point, line, and polygon tutorial.

  1. Define a suspend function named handleGeocodeResults(). Declare the parameters shown below.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    fun handleGeocodeResults(
        context: Context,
        coroutineScope: CoroutineScope,
        geocodeResults: List<GeocodeResult>,
        graphicsOverlay: GraphicsOverlay,
        mapViewProxy: MapViewProxy
    ) {
    
    }
    
  2. If the geocodeResults list is not empty, do the following: First, get the first GeocodeResult from the geocodeResults list. Next, call createTextGraphic() and createMarkerGraphic(), passing that geocode result to each. Last, add the two graphics to the GraphicsOverlay.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    fun handleGeocodeResults(
        context: Context,
        coroutineScope: CoroutineScope,
        geocodeResults: List<GeocodeResult>,
        graphicsOverlay: GraphicsOverlay,
        mapViewProxy: MapViewProxy
    ) {
    
        if (geocodeResults.isNotEmpty()) {
            val geocodeResult = geocodeResults[0]
            // Create a Text graphic to display the address text, and add it to the graphics overlay.
            val textGraphic = createTextGraphic(geocodeResult)
            // Create a red square marker graphic, and add it to the graphics overlay.
            val markerGraphic = createMarkerGraphic(geocodeResult)
            // Clear previous results and add graphics.
            graphicsOverlay.graphics.apply {
                clear()
                add(textGraphic)
                add(markerGraphic)
            }
    
    }
    
  3. Inside a coroutineScope.launch block, get the display location (which is a Point) from the geocode result and assign it to a variable named centerPoint. Then call MapViewProxy.setViewpointCenter(), which is defined in the ArcGIS Maps SDK for Kotlin Toolkit, and pass centerPoint.

    Last, add code to handle the case where the geocodeResults list is empty.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    fun handleGeocodeResults(
        context: Context,
        coroutineScope: CoroutineScope,
        geocodeResults: List<GeocodeResult>,
        graphicsOverlay: GraphicsOverlay,
        mapViewProxy: MapViewProxy
    ) {
    
        if (geocodeResults.isNotEmpty()) {
            val geocodeResult = geocodeResults[0]
            // Create a Text graphic to display the address text, and add it to the graphics overlay.
            val textGraphic = createTextGraphic(geocodeResult)
            // Create a red square marker graphic, and add it to the graphics overlay.
            val markerGraphic = createMarkerGraphic(geocodeResult)
            // Clear previous results and add graphics.
            graphicsOverlay.graphics.apply {
                clear()
                add(textGraphic)
                add(markerGraphic)
            }
    
            coroutineScope.launch {
                val centerPoint = geocodeResult.displayLocation
                    ?: return@launch showMessage(context, "The locatorTask.geocode() call failed")
    
                // Animate the map view to the center point.
                mapViewProxy.setViewpointCenter(centerPoint)
                    .onFailure { error ->
                        showMessage(context, "Failed to set Viewpoint center: ${error.message}")
                    }
    
            }
    
        } else {
            showMessage(context, "No address found for the given query")
        }
    
    }
    
Add a search bar and pass parameters to MapView

To search an address using the application, add a search bar that will accept an address as text input.

Next, modify the Scaffold so it contains a Column. Inside the Column, you will add a SearchBar, followed by MapView.

  1. Inside the Scaffold block, find the MapView from the Display a map tutorial and replace it with a call of Column. A Column allows you to display the search bar at the top of the screen and the map view directly below.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    @Composable
    fun MainScreen() {
    
        val context = LocalContext.current
        val coroutineScope = rememberCoroutineScope()
        // The focus manager is used to dismiss keyboard after search query submission.
        val focusManager = LocalFocusManager.current
        var queryText by remember { mutableStateOf("") }
        val currentJob = remember { mutableStateOf<Job?>(null) }
        val graphicsOverlay = remember { GraphicsOverlay() }
        val graphicsOverlays = remember { listOf(graphicsOverlay) }
        val mapViewProxy = remember { MapViewProxy() }
        val currentSpatialReference = remember { mutableStateOf<SpatialReference?>(null) }
    
        val map = remember {
            createMap()
        }
    
        Scaffold(
            topBar = { TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) }) }
        ) {
    
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(it)
            ) {
    
            }
    
        }
    
    }
    
  2. Call the SearchBar composable, passing the parameters shown below.

    Pass a lambda for the onSearch parameter. When the onSearch callback is invoked, the lambda should clear the focus from the search bar (thus dismissing the device keyboard), then cancel any previous search job, and start a new search job by calling searchAddress(). Note that the onSearch lambda provides a parameter with the value of the current input query, which you must pass to searchAddress().

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    @Composable
    fun MainScreen() {
    
        val context = LocalContext.current
        val coroutineScope = rememberCoroutineScope()
        // The focus manager is used to dismiss keyboard after search query submission.
        val focusManager = LocalFocusManager.current
        var queryText by remember { mutableStateOf("") }
        val currentJob = remember { mutableStateOf<Job?>(null) }
        val graphicsOverlay = remember { GraphicsOverlay() }
        val graphicsOverlays = remember { listOf(graphicsOverlay) }
        val mapViewProxy = remember { MapViewProxy() }
        val currentSpatialReference = remember { mutableStateOf<SpatialReference?>(null) }
    
        val map = remember {
            createMap()
        }
    
        Scaffold(
            topBar = { TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) }) }
        ) {
    
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(it)
            ) {
    
                SearchBar(
                    inputField = {
                        SearchBarDefaults.InputField(
                            query = queryText,
                            onQueryChange = { query ->
                                queryText = query
                            },
                            onSearch = { currentQuery ->
                                focusManager.clearFocus()
                                // Cancel any previous search job.
                                currentJob.value?.cancel()
                                // Start a new search job.
                                currentJob.value = coroutineScope.launch {
                                    searchAddress(
                                        context,
                                        coroutineScope,
                                        currentQuery,
                                        currentSpatialReference.value,
                                        graphicsOverlay,
                                        mapViewProxy
                                    )
                                }
                            },
                            expanded = false,
                            onExpandedChange = { },
                            enabled = true,
                            placeholder = { Text("Search for an address") },
                            leadingIcon = { Icon(Icons.Filled.Search, contentDescription = "Search") })
                    },
                    expanded = false,
                    onExpandedChange = {},
                    modifier = Modifier.fillMaxWidth(),
                ) {}
    
            }
    
        }
    
    }
    
  3. Add back the MapView, passing a Modifier and map.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
        Scaffold(
            topBar = { TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) }) }
        ) {
    
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(it)
            ) {
    
                SearchBar(
                    inputField = {
                        SearchBarDefaults.InputField(
                            query = queryText,
                            onQueryChange = { query ->
                                queryText = query
                            },
                            onSearch = { currentQuery ->
                                focusManager.clearFocus()
                                // Cancel any previous search job.
                                currentJob.value?.cancel()
                                // Start a new search job.
                                currentJob.value = coroutineScope.launch {
                                    searchAddress(
                                        context,
                                        coroutineScope,
                                        currentQuery,
                                        currentSpatialReference.value,
                                        graphicsOverlay,
                                        mapViewProxy
                                    )
                                }
                            },
                            expanded = false,
                            onExpandedChange = { },
                            enabled = true,
                            placeholder = { Text("Search for an address") },
                            leadingIcon = { Icon(Icons.Filled.Search, contentDescription = "Search") })
                    },
                    expanded = false,
                    onExpandedChange = {},
                    modifier = Modifier.fillMaxWidth(),
                ) {}
    
                MapView(
                    modifier = Modifier.fillMaxSize(),
                    arcGISMap = map,
    
                )
    
            }
    
        }
    
  4. Pass these additional parameters to MapView:

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
                MapView(
                    modifier = Modifier.fillMaxSize(),
                    arcGISMap = map,
    
                    graphicsOverlays = graphicsOverlays,
                    mapViewProxy = mapViewProxy,
                    onSpatialReferenceChanged = { spatialReference ->
                        currentSpatialReference.value = spatialReference
                    }
    
                )
    
  5. (Optional) The code in this tutorial calls a function to display messages to the user. One possible implementation of showMessage() is the following.

    MainScreen.kt

    Expand

    Use dark colors for code blocks
    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
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    fun showMessage(context: Context, message: String) {
        Toast.makeText(context, message, Toast.LENGTH_LONG).show()
    }
  6. Click Run > Run > app to run the app.

You should see a search box above the map. Search for an address by entering an address and press the magnifying glass on the on the device keyboard. The result of the search should display on the map as a red square.

Tip

Try searching for the following locations:

Alternatively, you can download the tutorial solution, as follows.

Option 2: Download the solution
  1. Click the Download solution link in the right-hand side of this page.

  2. Unzip the file to a location on your machine.

  3. Run Android Studio.

  4. Go to File > Open.... Navigate to the solution folder and click Open.

    On Windows: If you are in the Welcome to Android Studio dialog, click Open and navigate to the solution folder. Then click Open.

Since the downloaded solution does not contain authentication credentials, you must add the developer credentials that you created in the Set up authentication section.

Set developer credentials in the solution

To allow your app users to access ArcGIS location services, use the developer credentials that you created in the Set up authentication step to authenticate requests for resources.

  1. In the Android view of Android Studio, open app > kotlin+java > com.example.app > MainActivity. Set the AuthenticationMode to .API_KEY.

    MainActivity.kt

    Expand

    Use dark colors for code blocks
    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
    class MainActivity : ComponentActivity() {
    
        private enum class AuthenticationMode { API_KEY, USER_AUTH }
    
        private val authenticationMode = AuthenticationMode.API_KEY
    
  2. Set the apiKey property with your API key access token.

    MainActivity.kt

    Expand

    Use dark colors for code blocks
    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
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            when (authenticationMode) {
                AuthenticationMode.API_KEY -> {
    
                    ArcGISEnvironment.apiKey = ApiKey.create("YOUR_ACCESS_TOKEN")
    
                }
    

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

  1. In the Android view of Android Studio, open app > kotlin+java > com.example.app > MainActivity. Set the AuthenticationMode to .USER_AUTH.

    MainActivity.kt

    Use dark colors for code blocks

    1
    2
    3
    4
    class MainActivity : ComponentActivity() {
        private enum class AuthenticationMode { API_KEY, USER_AUTH }
    
        private val authenticationMode = AuthenticationMode.USER_AUTH
  2. Set your clientID and redirectURL values. You must use the RedirectURL that you supplied for your app in the user authentication part of the Set up authentication step.

    MainActivity.kt

    Expand

    Use dark colors for code blocks
    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
                AuthenticationMode.USER_AUTH -> {
                    authenticatorState.oAuthUserConfigurations = listOf(
                        OAuthUserConfiguration(
                            portalUrl = "https://www.arcgis.com",
    
                            clientId = "YOUR_CLIENT_ID",
                            redirectUrl = "YOUR_REDIRECT_URL"
    
                        )
                    )
    
  3. Open app > manifests > AndroidManifest.xml.

  4. Set the android:scheme and android:host using the scheme and host from your RedirectURL.

    A redirectURL is composed of a scheme and a host component. The format for the redirect url is scheme://host. For example, if the redirect url is myscheme://myhost then the scheme is myscheme and the host is myhost.

    AndroidManifest.xml

    Expand

    Use dark colors for code blocks
    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
                    <data
                        android:scheme="your_redirect_url_scheme"
                        android:host="your_redirect_url_host" />
    

Best Practice: The OAuth credentials are stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Run the app

Click Run > Run > app to run the app.

You should see a search box above the map. Search for an address by entering an address and press the magnifying glass on the on the device keyboard. The result of the search should display on the map as a red square.

Tip

Try searching for the following locations:

What's next?

Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials:


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4