Build an app with one of the ArcGIS Maps SDKs for Native Apps that downloads and displays your offline map area.

Prerequisites

Steps

Set up offline app

In this step, choose the appropriate ArcGIS Maps SDK for your platform and set up your development environment.

  1. Install and setup the ArcGIS Maps SDK for .NET on your development machine. Make sure you fulfill the SDK's system requirements.

  2. Go to the Display a map tutorial and download the completed solution to get a starter code for this workflow.
    You do not need to create another API key credential.

  3. Open the .sln file in Visual Studio.

    The Visual Studio solution, project, and the namespace for all classes currently use the name DisplayAMap. Follow the steps below if you prefer the name to reflect the current tutorial. These steps are not required, your code will still work if you keep the original name.

  4. Update the name for the solution and the project.

    • In Visual Studio, in the Solution Explorer, right-click the solution name and choose Rename. Provide the new name for your solution.
    • In the Solution Explorer, right-click the project name and choose Rename. Provide the new name for your project.
  5. Rename the namespace used by classes in the project.

    • In the Solution Explorer, expand the project node.
    • Double-click MapViewModel.cs in the Solution Explorer to open the file.
    • In the MapViewModel class, double-click the namespace name (DisplayAMap) to select it, and then right-click and choose Rename....
    • Provide the new name for the namespace.
    • Click Apply in the Rename: DisplayAMap window that appears in the upper-right of the code window. This will rename the namespace throughout your project.
  6. Build the project.

    • Choose Build > Build solution (or press F6).

Set the access token

  1. Paste the access token you copied in the previous step into your code.

    App.xaml.cs
    Use dark colors for code blocksCopy
    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
        public partial class App : Application
        {
    
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);
                // Note: it is not best practice to store API keys in source code.
                // The API key is referenced here for the convenience of this example.
    
                Esri.ArcGISRuntime.ArcGISRuntimeEnvironment.ApiKey = "YOUR_ACCESS_TOKEN";
    
            }
        }
    }

Download and display the offline map

Load the web map from your portal and retrieve its offline map areas. Then, download and display it as an offline map in your app. The existing map from the downloaded solution will be replaced by the offline map.

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

  2. Add additional required using statements at the top of the class.

    MapViewModel.cs
    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
    
    using System;
    using System.Collections.Generic;
    using Esri.ArcGISRuntime.Portal;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    
    using System.Linq;
    using Esri.ArcGISRuntime.Mapping;
    using Esri.ArcGISRuntime.Tasks.Offline;
    
  3. Create an empty global variable _downloadLocation to store the path to the downloaded map area later.

    MapViewModel.cs
    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
            private string _downloadLocation;
    
            private Map? _map;
            public Map? Map
            {
                get { return _map; }
                set
                {
                    _map = value;
                    OnPropertyChanged();
                }
            }
    
  4. Modify the SetupMap function signature to private async returning a Task and change the method name to GetOffllinePreplannedMap. Also remove the Map initializer from the function.

    MapViewModel.cs
    Use dark colors for code blocksCopy
    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
            private async Task GetOfflinePreplannedMap()
            {
    
            }
    
  5. Remove the Map initializer from the SetupMap function. Because the map area will be downloaded from the web map, this is no longer needed.

    MapViewModel.cs
    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
            private async Task GetOfflinePreplannedMap()
            {
    
            }
    
  6. Inside MainWindow.xaml.cs, remove the viewpoint configuration.

    MainWindow.xaml.cs
    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
            public MainWindow()
            {
                InitializeComponent();
    
                MapPoint mapCenterPoint = new MapPoint(-118.805, 34.027, SpatialReferences.Wgs84);
                MainMapView.SetViewpoint(new Viewpoint(mapCenterPoint, 100000));
    
            }
    
  7. Get the web map item ID from your portal, for example 4c4c3a28388446a19278b3a17051730e.

  8. Create a Map from the web map using its item ID.

    MapViewModel.cs
    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
            private async Task GetOfflinePreplannedMap()
            {
    
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
            }
    
  9. Create an OfflineMapTask referencing the web map. This task object reads the offline properties of the web map and manages downloading an offline map from it.

    MapViewModel.cs
    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
            private async Task GetOfflinePreplannedMap()
            {
    
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
    
            }
    
  10. Use the OfflineMapTask to list any available ahead-of-time offline maps. In the ArcGIS Maps SDKs for Native Apps the ahead-of-time offline map areas are referred to as preplanned areas.

    MapViewModel.cs
    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
            private async Task GetOfflinePreplannedMap()
            {
    
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
    
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
            }
    
  11. Get a set of default DownloadPreplannedOfflineMapParameters. These parameters describe how the owner of the web map configured the offline map to be downloaded by default. You can modify the parameters to fine tune the downloaded offline map.

    MapViewModel.cs
    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
            private async Task GetOfflinePreplannedMap()
            {
    
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
    
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                }
    
            }
    
  12. Define a path to store the downloaded map area and store it in the global variable _downloadLocation.

    MapViewModel.cs
    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
            private async Task GetOfflinePreplannedMap()
            {
    
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
    
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                }
    
            }
    
  13. Use the parameters to create a DownloadPreplannedOfflineMapJob to download the offline map, specifying the download location.

    MapViewModel.cs
    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
            private async Task GetOfflinePreplannedMap()
            {
    
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
    
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
    
                }
    
            }
    
  14. Start the job and wait for it to complete, returning a Map that is ready for use.

    MapViewModel.cs
    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
            private async Task GetOfflinePreplannedMap()
            {
    
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
    
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
    
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
    
                }
    
            }
    
    Expand
  15. Click Debug > Start Debugging (or press F5 on the keyboard) to run the app.

Access the offline map

Create a function to load the previously downloaded offline map from its stored location, so it can be reused without redownloading.

  1. Inside MapViewModel.cs, create a private async function returning a Task called AccessMap().

    MapViewModel.cs
    Use dark colors for code blocksCopy
    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
            private async Task AccessMap()
            {
    
            }
    
  2. Inside the function, create a MobileMapPackage that references the path to the downloaded offline map area.

    MapViewModel.cs
    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
            private async Task AccessMap()
            {
    
                var mobileMapPackage = await MobileMapPackage.OpenAsync(_downloadLocation);
    
            }
    
  3. Load the mobile map package and read the Map from it.

    MapViewModel.cs
    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
            private async Task AccessMap()
            {
    
                var mobileMapPackage = await MobileMapPackage.OpenAsync(_downloadLocation);
    
                await mobileMapPackage.LoadAsync();
    
                this.Map = mobileMapPackage.Maps.First();
    
            }
    
  4. The function is now ready to be called to access a previously downloaded offline map area. You can trigger this function from a UI button click or by calling it directly from the constructor.

  5. Click Debug > Start Debugging (or press F5 on the keyboard) to run the app.

Congratulations!

You have completed the Create an offline app how-to. The application uses the ArcGIS Maps SDKs for Native Apps to display an offline map.

What's next?

This is just one way to build an offline application with ArcGIS. Depending on your needs, you can also:

  • Download map areas on demand.
  • Work in fully offline environments with mobile packages that support both 2D maps and 3D scenes.
  • Add editing, syncing, and advanced data workflows.

Explore the topics below to learn about other types of offline applications and data sources.

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.