Display an offline map (on-demand)

Learn how to download and display an offline map for a user-defined geographical area of a web map.

display an offline map custom

Offline maps allow users to continue working when network connectivity is poor or lost. If a web map is enabled for offline use, a user can request that ArcGIS generates an offline map for a specified geographic area of interest.

In this tutorial, you will download an offline map for an area of interest from the web map of the stormwater network within Naperville, IL, USA. You can then use this offline map without a network connection.

The following are required for this tutorial:

  1. An ArcGIS account to access API keys. If you don't have an account, sign up for free.
  2. Confirm that your system meets the system requirements.
  3. An IDE for Android development in Kotlin.

Steps

Open an Android Studio project

  1. To start this tutorial, complete the Display a web map tutorial. Or download and unzip the Display a web map solution in a new folder.

  2. Modify the old project for use in this new tutorial. Expand More info for instructions.

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

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

      In the <string name="app_name"> element, change the text content to Display an offline map (on-demand).

      strings.xml
      Use dark colors for code blocks
           
      Change line
      1
      2
      3
      4
      5
      <resources>
      
          <string name="app_name">Display an offline map (on-demand)</string>
      
      </resources>
    3. In the Android tool window, open Gradle Scripts > settings.gradle.

      Change the value of rootProject.name to "Display an offline map (on-demand)".

      settings.gradle
      Expand
      Use dark colors for code blocks
                              
      Change line
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      rootProject.name = "Display an offline map (on-demand)"
      
      include ':app'
    4. Click File > Sync Project with Gradle files. Android Studio will recognize your changes and create a new .idea folder.

  3. If you downloaded the Display a web map solution project, get your API key and set it in your app.

    An API Key enables access to services, web maps, and web scenes hosted in ArcGIS Online.

    1. 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.

    2. In Android Studio: in the Android tool window, open app > java > com.example.app > MainActivity.

    3. In the setApiKeyForApp() method, find the ArcGISRuntimeEnvironment.setApiKey("YOUR_API_KEY") call and paste your API key inside the quotes, replacing YOUR_API_KEY.

      MainActivity.kt
      Use dark colors for code blocks
                                                                                               
      Change line
      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
          override fun onDestroy() {
              mapView.dispose()
              super.onDestroy()
          }
      
          private fun setApiKeyForApp(){
              // 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")
      
          }
      

Add import statements and packagingOptions

  1. Replace app-specific import statements with the imports needed for this tutorial.

    MainActivity.kt
    Use dark colors for code blocks
    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 40 41 42 43 44 45 46 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
    Change lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange line
    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
    package com.example.app
    
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    
    import android.graphics.Color
    import android.view.View
    import android.widget.ProgressBar
    import android.widget.Toast
    
    import java.util.*
    
    import com.esri.arcgisruntime.ArcGISRuntimeEnvironment
    import com.esri.arcgisruntime.concurrent.Job
    import com.esri.arcgisruntime.geometry.Envelope
    import com.esri.arcgisruntime.geometry.SpatialReferences
    import com.esri.arcgisruntime.mapping.ArcGISMap
    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.portal.Portal
    import com.esri.arcgisruntime.portal.PortalItem
    import com.esri.arcgisruntime.symbology.SimpleFillSymbol
    import com.esri.arcgisruntime.symbology.SimpleLineSymbol
    import com.esri.arcgisruntime.tasks.offlinemap.GenerateOfflineMapParameters
    import com.esri.arcgisruntime.tasks.offlinemap.GenerateOfflineMapUpdateMode
    import com.esri.arcgisruntime.tasks.offlinemap.OfflineMapTask
    
    import com.example.app.databinding.ActivityMainBinding
    
    class MainActivity : AppCompatActivity() {
    
  2. In Android Studio, in the Android tool window, open Gradle Scripts > build.gradle (Module:Display_a_map_from_a_mobile_map_package.app). Make sure your file matches the one below. In particular, verify that you have the buildFeatures and packagingOptions blocks shown.

    build.gradle (Module:Display_a_map_from_a_mobile_map_package.app)
    Expand
    Use dark colors for code blocksCopy
    28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 29 30 31 32 33 34 35 36 37 38 39 40 40 40 40 40 40 40 40 40 40 40
    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
        kotlinOptions {
            jvmTarget = JavaVersion.VERSION_1_8.toString()
        }
    
        buildFeatures {
            viewBinding true
        }
        packagingOptions {
            exclude 'META-INF/DEPENDENCIES'
        }
    
    }
    
    Expand

Get the web map item ID

You can use ArcGIS tools to create and view web maps. Use the Map Viewer to identify the web map item ID. This item ID will be used later in the tutorial.

  1. Go to the Naperville water network in the Map Viewer in ArcGIS Online. This web map displays stormwater network within Naperville, IL, USA.
  2. Make a note of the item ID at the end of the browser's URL. The item ID should be acc027394bc84c2fb04d1ed317aac674

Define a ProgressBar and create read-only properties

  1. In the Project tool window, open app > res > layout > activity_main.xml. Add a <ProgressBar> element to define a progress bar.

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                      
    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.
    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
        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="50dp"
            android:layout_marginEnd="50dp"
            android:padding="20dp"
            android:indeterminate="false"
            android:visibility="gone"
            android:scaleY="3"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    Expand
  2. In the Project tool window, open app > java > com.example.app > MainActivity.kt. At the top of the MainActivity class, keep the read-only, lazy properties activityMainBinding and mapView that were defined in Display a web map tutorial. Add read-only, lazy properties progressBar and areaOverlay.

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.Add line.Add line.Add line.Add line.
    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
    class MainActivity : AppCompatActivity() {
    
        private val activityMainBinding by lazy {
            ActivityMainBinding.inflate(layoutInflater)
        }
    
        private val mapView: MapView by lazy {
            activityMainBinding.mapView
        }
    
        private val progressBar: ProgressBar by lazy {
            activityMainBinding.progressBar
        }
    
        private val areaOverlay: GraphicsOverlay by lazy {
            GraphicsOverlay()
        }
    
    Expand

Display the web map

You can display a web map using the web map's item ID. Create a map from the web map portal item, and display it in your app.

  1. In the Visual Studio > Solution Explorer, double-click MapViewModel.cs to open the file.

  2. In MainActivity.kt, delete the code inside setupMap().

    Create a Portal pointing to ArcGIS Online. Then create a PortalItem for the Naperville water network, using the portal and the web map's item ID. Finally, set the MapView.map property to a new ArcGISMap created using the PortalItem.

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Change lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange line
    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
        // set up your map here. You will call this method from onCreate()
        private fun setupMap() {
    
            // create a portal pointing to ArcGIS Online
            val portal = Portal("https://www.arcgis.com", false)
            // create a portal item for a specific web map id
    
            val webMapId = "acc027394bc84c2fb04d1ed317aac674"
    
            val mapItem = PortalItem(portal, webMapId)
            // create the map from the item
            val map = ArcGISMap(mapItem)
    
            // set the map to the map view
            mapView.map = map
    
        }
    
    Expand
  3. Add the areaOverlay to the map view's list of graphics overlays.

    The GraphicsOverlay referenced by areaOverlay has no graphics in it at the moment. You will add an area-of-interest graphic in the next section. To see where you defined the areaOverlay property, expand Show more lines in the code block below. The property is highlighted in blue.

    For more information about the list of graphics overlays in a map view, see GeoView.getGraphicsOverlays().

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Change lineChange line
    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
        // set up your map here. You will call this method from onCreate()
        private fun setupMap() {
    
            // create a portal pointing to ArcGIS Online
            val portal = Portal("https://www.arcgis.com", false)
            // create a portal item for a specific web map id
    
            val webMapId = "acc027394bc84c2fb04d1ed317aac674"
    
            val mapItem = PortalItem(portal, webMapId)
            // create the map from the item
            val map = ArcGISMap(mapItem)
    
            // set the map to the map view
            mapView.map = map
    
            // add a graphics overlay to the map view
            mapView.graphicsOverlays.add(areaOverlay)
    
        }
    
    Expand
  4. Click Run > Run > app to run the app.

You should see a map of the stormwater network within Naperville, IL, USA. Use the mouse to drag, scroll, and double-click the map view to explore the map.

Specify an area of the web map to take offline

You can specify an area of the web map to take offline using an Envelope. You can use a graphic to display the area on the map.

  1. Define a new function createAreaofInterestGraphic(). Create an Envelope to define the area of interest to take offline.

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.
    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
        private fun createAreaOfInterestGraphic(): Envelope {
    
            // define area of interest (envelope) to take offline.
            val offlineArea =
                Envelope(-88.1526, 41.7694, -88.1490, 41.7714, SpatialReferences.getWgs84())
    
        }
    
    Expand
  2. Display a graphic of the area to take offline.

    Use a SimpleLineSymbol and a SimpleFillSymbol to create a new Graphic of the offline area with a red outline. Add the graphic to the GraphicsOverlay referenced by areaOverlay.

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
    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
        private fun createAreaOfInterestGraphic(): Envelope {
    
            // define area of interest (envelope) to take offline.
            val offlineArea =
                Envelope(-88.1526, 41.7694, -88.1490, 41.7714, SpatialReferences.getWgs84())
    
            // create a graphic to display the area to take offline
            val lineSymbol = SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.RED, 2f)
            val fillSymbol =
                SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, Color.TRANSPARENT, lineSymbol)
            val offlineAreaGraphic = Graphic(offlineArea, fillSymbol)
    
            // create a graphics overlay and add the graphic
            areaOverlay.graphics.add(offlineAreaGraphic)
    
        }
    
    Expand
  3. Return the offline area itself. It will be used later when you create parameters for the job that generates and downloads an offline map.

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.
    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
        private fun createAreaOfInterestGraphic(): Envelope {
    
            // define area of interest (envelope) to take offline.
            val offlineArea =
                Envelope(-88.1526, 41.7694, -88.1490, 41.7714, SpatialReferences.getWgs84())
    
            // create a graphic to display the area to take offline
            val lineSymbol = SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.RED, 2f)
            val fillSymbol =
                SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, Color.TRANSPARENT, lineSymbol)
            val offlineAreaGraphic = Graphic(offlineArea, fillSymbol)
    
            // create a graphics overlay and add the graphic
            areaOverlay.graphics.add(offlineAreaGraphic)
    
            return offlineArea
    
        }
    
    Expand
  4. Click Run > Run > app to run the app.

You should see a red outline on the stormwater network within Naperville, IL, USA. This indicates the area of the web map that you are going to take offline.

Download and display the offline map

You can generate and download an offline map for a specified area of interest using an asynchronous task. When complete, it will provide the offline map for display in your map view.

  1. Define a new function createOfflineMapTaskAndParameters(). Create an OfflineMapTask that references the online map.

    MainActivity.kt
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.
    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
        private fun createOfflineMapTaskAndParameters(map: ArcGISMap, offlineArea : Envelope) {
    
            // create an offline map task using the current map
            val offlineMapTask = OfflineMapTask(map)
    
        }
    
  2. Get default parameters to generate and download the offline map. Since the return value of createDefaultGenerateOfflineMapParametersAsync() is a listenable future, add a done listener, where you modify the default parameters to download a read-only offline map.

    This tutorial does not involve editing and updating the contents of the offline map. When an offline map is editable, metadata is stored in ArcGIS to track and synchronize edits. Setting the GenerateOfflineMapUpdateMode to NO_UPDATES avoids the overhead of maintaining this metadata in ArcGIS.

    MainActivity.kt
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
    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
        private fun createOfflineMapTaskAndParameters(map: ArcGISMap, offlineArea : Envelope) {
    
            // create an offline map task using the current map
            val offlineMapTask = OfflineMapTask(map)
    
            // create a default set of parameters for generating the offline map from the area of interest
            val parametersFuture =
                offlineMapTask.createDefaultGenerateOfflineMapParametersAsync(offlineArea)
            parametersFuture.addDoneListener {
                val parameters = parametersFuture.get().apply {
                    updateMode = GenerateOfflineMapUpdateMode.NO_UPDATES
                }
                downloadOfflineMap(offlineMapTask, parameters)
            }
    
        }
    
  3. Define a new function downloadOfflineMap(). Set a download location for the offline map.

    MainActivity.kt
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.
    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
        private fun downloadOfflineMap(offlineMapTask: OfflineMapTask, parameters: GenerateOfflineMapParameters) {
    
            // Build a folder path named with today's date/time in the "My Documents" folder.
            val downloadLocation =
                getExternalFilesDir(null)?.path + "OfflineMap_" + Calendar.getInstance().time
    
        }
    

    This tutorial code creates a new unique folder in your app's data folder, using the current date and time.

  4. Create a new GenerateOfflineMapJob using the parameters passed into the function and the downloadLocation.

    MainActivity.kt
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.Add line.
    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
        private fun downloadOfflineMap(offlineMapTask: OfflineMapTask, parameters: GenerateOfflineMapParameters) {
    
            // Build a folder path named with today's date/time in the "My Documents" folder.
            val downloadLocation =
                getExternalFilesDir(null)?.path + "OfflineMap_" + Calendar.getInstance().time
    
            val generateJob =
                offlineMapTask.generateOfflineMap(parameters, downloadLocation).apply {
    
                }
    
        }
    
  5. Add a progress changed listener for the generate offline map job.

    MainActivity.kt
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.
    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
        private fun downloadOfflineMap(offlineMapTask: OfflineMapTask, parameters: GenerateOfflineMapParameters) {
    
            // Build a folder path named with today's date/time in the "My Documents" folder.
            val downloadLocation =
                getExternalFilesDir(null)?.path + "OfflineMap_" + Calendar.getInstance().time
    
            val generateJob =
                offlineMapTask.generateOfflineMap(parameters, downloadLocation).apply {
    
                    addProgressChangedListener {
                        progressBar.progress = progress
                    }
    
                }
    
        }
    
  6. Add a job done listener for the generate offline map job.

    MainActivity.kt
    Use dark colors for code blocks
                                                                                                                                                                                                        
    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.
    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
        private fun downloadOfflineMap(offlineMapTask: OfflineMapTask, parameters: GenerateOfflineMapParameters) {
    
            // Build a folder path named with today's date/time in the "My Documents" folder.
            val downloadLocation =
                getExternalFilesDir(null)?.path + "OfflineMap_" + Calendar.getInstance().time
    
            val generateJob =
                offlineMapTask.generateOfflineMap(parameters, downloadLocation).apply {
    
                    addProgressChangedListener {
                        progressBar.progress = progress
                    }
    
                    addJobDoneListener {
                        // replace the current map with the result offline map when the job finishes
                        if (status == Job.Status.SUCCEEDED) {
                            progressBar.visibility = View.GONE
                            Toast.makeText(
                                this@MainActivity,
                                "Showing offline map.",
                                Toast.LENGTH_LONG
                            ).show()
                            val result = result
                            mapView.map = result.offlineMap
                            areaOverlay.graphics.clear()
                        }
                    }
    
                }
    
        }
    
  7. Start the generate offline map job, display a progress bar, and display a Toast saying that the job is starting.

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.
    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
                }
    
            generateJob.start()
            progressBar.visibility = View.VISIBLE
            Toast.makeText(this@MainActivity, "Starting generate offline map job.", Toast.LENGTH_LONG).show()
    
        }
    
    Expand
  8. In setupMap(), call the functions you defined to create the area of interest graphic and then create the offline map task. First, call createAreaofInterestGraphic() and then pass the result when you call createOfflineMapTaskAndParameters().

    MainActivity.kt
    Expand
    Use dark colors for code blocks
                                                                                                                                                                                                        
    Add line.Add line.Add line.
    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
            // set the map to the map view
            mapView.map = map
    
            // add a graphics overlay to the map view
            mapView.graphicsOverlays.add(areaOverlay)
    
            // create a graphic showing the area of interest
            val offlineArea = createAreaOfInterestGraphic()
            createOfflineMapTaskAndParameters(map, offlineArea)
    
        }
    
    Expand
  9. Click Run > Run > app to run the app.

You should see an offline map for the specified area of the stormwater network within Naperville, IL, USA. Remove your network connection and you will still be able to use the mouse to drag, scroll, and double-click the map view to explore this offline map.

What's next?

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