Learn how to download and display an offline map An offline map is a map area and its data content downloaded from an offline-enabled web map for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more for a user-defined geographical area of a web map A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. Learn more .

display an offline map on demand

Offline maps An offline map is a map area and its data content downloaded from an offline-enabled web map for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more allow users to continue working when network connectivity is poor or lost. If a web map A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. Learn more 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 An offline map is a map area and its data content downloaded from an offline-enabled web map for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more for an area of interest from the web map A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. Learn more of the stormwater network within Naperville, IL, USA . You can then use this offline map without a network connection.

Prerequisites

Before starting this tutorial:

  1. You need an ArcGIS Location Platform or ArcGIS Online account.

  2. Your system meets the system requirements.

  3. You need an IDE for Flutter - we recommend VS Code.

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

To start the tutorial, complete the Display a map tutorial. This creates a map to display the Santa Monica Mountains in California using the topographic basemap from the ArcGIS Basemap Styles service The ArcGIS Basemap Styles service, also referred to as the Basemap Styles service, is a location service that provides basemap styles and data for the world. It returns styles as Mapbox styles and web maps, and data as vector tiles and/or map tiles. It supports all of the styles in the ArcGIS Basemap style and Open Basemap style family. An ArcGIS Location Platform or ArcGIS Online account is required to use the service. Learn more .

Open Flutter project

  1. Open the project you created by completing the Display a map tutorial.

  2. Continue with the following instructions to download and display an offline map for a user-defined geographical area of a web map.

Import additional library and package

As part of the offline workflow, you will need to store a downloaded map to your device. You will add the dart:io library to gain access to an API to deal with files and directories and the path_provider package to access local files on a device.

  1. In VS Code, double-click lib\main.dart to open the file.

  2. From the menu bar, select View > Terminal to open a new terminal.

  3. Add the path_provider package to the project as a dependency running the following command:

    flutter pub add path_provider
  4. Import path_provider and dart.io into main.dart.

    main.dart
    import 'dart:io';
    import 'package:path_provider/path_provider.dart';
    import 'package:flutter/material.dart';
    import 'package:arcgis_maps/arcgis_maps.dart';
    void main() {

Get the web map item ID

You can use ArcGIS tools Tools, also known as developer tools, are ArcGIS software applications such as portal and ArcGIS Pro that developers can use to prepare content and data for custom applications they are building. Learn more to create and view web maps A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. Learn more . Use the Map Viewer Map Viewer is a browser-based mapping tool that can view, create, and save web maps. It can also perform mapping, visualization, and spatial analysis operations. Learn more to identify the web map item ID An item ID is a unique identifier representing a single item stored, managed, and accessed in a portal, such as a web map, hosted layer, or file. Learn more . This item ID will be used later in the tutorial.

  1. Go to the Naperville water network in the Map Viewer Map Viewer is a browser-based mapping tool that can view, create, and save web maps. It can also perform mapping, visualization, and spatial analysis operations. Learn more in ArcGIS Online ArcGIS Online is a GIS mapping, analytics, data hosting, and content management software as a service (SaaS) product. It includes applications, tools, APIs, and location services for users and developers. It is subscription-based and requires an ArcGIS Online account. Learn more . This web map A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. Learn more displays stormwater network within Naperville, IL, USA .
  2. Make a note of the item ID An item ID is a unique identifier representing a single item stored, managed, and accessed in a portal, such as a web map, hosted layer, or file. Learn more at the end of the browser’s URL. The item ID should be:

    acc027394bc84c2fb04d1ed317aac674

Display the web map

You can display a web map A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. Learn more using the web map’s item ID An item ID is a unique identifier representing a single item stored, managed, and accessed in a portal, such as a web map, hosted layer, or file. Learn more . Create a map A map is a collection of layers that are displayed in 2D. It is typically composed of a basemap layer and data layers. Learn more from the web map portal item An item, also known as a content item, is a resource stored in a portal such as a web map, hosted layer, style, script tool, file, or notebook. Learn more , and display it in your app.

  1. Replace all the code contained in onMapViewReady() to instead create a portal item using the item ID from the ArcGIS Online web map.

    main.dart
    void onMapViewReady() {
    // Create an ArcGIS Online portal item using the item ID.
    final portalItem = PortalItem.withPortalAndItemId(
    portal: Portal.arcGISOnline(),
    itemId: 'acc027394bc84c2fb04d1ed317aac674',
    );
    }
  2. Define a final map variable and set its value to an instance of ArcGISMap using the PortalItem.

    main.dart > onMapViewReady()
    // Create an ArcGIS Online portal item using the item ID.
    final portalItem = PortalItem.withPortalAndItemId(
    portal: Portal.arcGISOnline(),
    itemId: 'acc027394bc84c2fb04d1ed317aac674',
    );
    // Define an ArcGIS map variable to hold on to the web map.
    final map = ArcGISMap.withItem(portalItem);
  3. Set the map to the ArcGISMapViewController‘s arcGISMap property.

    main.dart > onMapViewReady()
    // Define an ArcGIS map variable to hold on to the web map.
    final map = ArcGISMap.withItem(portalItem);
    // Set the map to the map view controller's ArcGIS map property.
    _mapViewController.arcGISMap = map;
  4. Make sure you have an Android emulator, iOS simulator or physical device configured and running.

  5. In VS Code, select Run > Run Without Debugging.

You should see a map of the stormwater network within Naperville, IL, USA. Pinch, drag, and double-tap the map view to explore the map. Leave the application running while you move into the next section to continue with the tutorial.

Specify an area of the web map to take offline

To specify an area of the web map A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. Learn more to take offline, you will use an Envelope that will be constructed using the EnvelopeBuilder. You will then display the area on the map using a Graphic.

  1. Create an envelope builder and set its spatial reference to match the web map.

    main.dart > onMapViewReady()
    // Set the map to the map view controller's ArcGIS map property.
    _mapViewController.arcGISMap = map;
    // Create an envelope builder.
    final envelopeBuilder = EnvelopeBuilder(
    // Set the spatial reference.
    spatialReference: SpatialReference.wgs84,
    );
  2. Use the envelope builder to define an area to take offline.

    main.dart > onMapViewReady()
    // Create an envelope builder.
    final envelopeBuilder = EnvelopeBuilder(
    // Set the spatial reference.
    spatialReference: SpatialReference.wgs84,
    );
    // Add the lower left (Xmin, Ymin) and upper right (Xmax, Ymax)
    // coordinates to define the area to take offline.
    envelopeBuilder.xMin = -88.1526;
    envelopeBuilder.xMax = -88.1490;
    envelopeBuilder.yMin = 41.7694;
    envelopeBuilder.yMax = 41.7714;
    // Retrieve the new geometry from the builder.
    final offlineArea = envelopeBuilder.toGeometry();
  3. Display a graphic of the area to take offline.

    Use SimpleLineSymbol and SimpleFillSymbol to display a new Graphic of the offlineArea with a red outline. Add the graphic to a new GraphicsOverlay and add the new overlay to the _mapViewController.graphicsOverlays property to display it in the map view.

    main.dart > onMapViewReady()
    // Retrieve the new geometry from the builder.
    final offlineArea = envelopeBuilder.toGeometry();
    // Define a red line symbol to act as the outline
    // for the area of interest.
    final lineSymbol = SimpleLineSymbol(
    style: SimpleLineSymbolStyle.solid,
    color: Colors.red,
    width: 2,
    );
    // Define a fill symbol that is transparent, setting the
    // outline to the line symbol.
    final fillSymbol = SimpleFillSymbol(
    style: SimpleFillSymbolStyle.solid,
    color: Colors.transparent,
    outline: lineSymbol,
    );
    // Create a graphic for the area of interest using the
    // built geometry and symbol.
    final offlineAreaGraphic = Graphic(
    geometry: offlineArea,
    symbol: fillSymbol,
    );
    // Create a new graphics overlay.
    final areaOverlay = GraphicsOverlay();
    // Add the graphic to the graphics overlay.
    areaOverlay.graphics.add(offlineAreaGraphic);
    // Add the graphics overlay to the map view controller.
    _mapViewController.graphicsOverlays.add(areaOverlay);
  4. Use Flutter’s hot restart to load your code changes and restart 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 An offline map is a map area and its data content downloaded from an offline-enabled web map for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more for an area of interest using an asynchronous task. When complete, it will provide the offline map for display in your map view A map view is a user interface that displays map layers and graphics in 2D. It controls the area (extent) of the map that is visible and supports user interactions such as pan and zoom. Learn more .

  1. Create an OfflineMapTask using the online map.

    main.dart > onMapViewReady()
    // Add the graphics overlay to the map view controller.
    _mapViewController.graphicsOverlays.add(areaOverlay);
    // Create an offline map task for the map.
    final offlineMapTask = OfflineMapTask.withOnlineMap(map);
  2. In onMapViewReady(), change the method signature to denote the method as asynchronous.

    main.dart
    void onMapViewReady() async {
  3. Get default parameters to generate and download the offline map An offline map is a map area and its data content downloaded from an offline-enabled web map for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more . Modify them to download a read-only offline map.

    main.dart > onMapViewReady()
    // Create an offline map task for the map.
    final offlineMapTask = OfflineMapTask.withOnlineMap(map);
    // Create parameters specifying the region to take offline
    // using the graphic's geometry. Set the update mode to
    // no updates to avoid the overhead of maintaining the
    // metadata required when synchronizing edits.
    final parameters = await offlineMapTask
    .createDefaultGenerateOfflineMapParameters(
    areaOfInterest: offlineArea,
    )
    ..updateMode = GenerateOfflineMapUpdateMode.noUpdates;
  4. Set a download location for the offline map An offline map is a map area and its data content downloaded from an offline-enabled web map for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more .

    main.dart > onMapViewReady()
    // Create parameters specifying the region to take offline
    // using the graphic's geometry. Set the update mode to
    // no updates to avoid the overhead of maintaining the
    // metadata required when synchronizing edits.
    final parameters = await offlineMapTask
    .createDefaultGenerateOfflineMapParameters(
    areaOfInterest: offlineArea,
    )
    ..updateMode = GenerateOfflineMapUpdateMode.noUpdates;
    // Prepare an empty directory to store the offline map.
    final documentsUri = (await getApplicationDocumentsDirectory()).uri;
    final downloadDirectoryUri = documentsUri.resolve('offline_map');
    // If the download directory already exists we delete.
    // If this is undesirable, use a unique identifier for the downloadDirectoryUri
    // such as appending a timestamp.
    if (Directory.fromUri(downloadDirectoryUri).existsSync()) {
    Directory.fromUri(downloadDirectoryUri).deleteSync(recursive: true);
    }
    Directory.fromUri(downloadDirectoryUri).createSync();
  5. Create a new GenerateOfflineMapJob using the parameters and downloadDirectoryUri.

    main.dart > onMapViewReady()
    // Prepare an empty directory to store the offline map.
    final documentsUri = (await getApplicationDocumentsDirectory()).uri;
    final downloadDirectoryUri = documentsUri.resolve('offline_map');
    // If the download directory already exists we delete.
    // If this is undesirable, use a unique identifier for the downloadDirectoryUri
    // such as appending a timestamp.
    if (Directory.fromUri(downloadDirectoryUri).existsSync()) {
    Directory.fromUri(downloadDirectoryUri).deleteSync(recursive: true);
    }
    Directory.fromUri(downloadDirectoryUri).createSync();
    // Create a job to generate the offline map passing in
    // the parameters and download directory.
    final generateOfflineMapJob = offlineMapTask.generateOfflineMap(
    parameters: parameters,
    downloadDirectoryUri: downloadDirectoryUri,
    );
  6. Add code to listen for when the generate offline map job completes or fails and to track the percent complete as the job runs. Add a try/catch block to handle exceptions.

    main.dart > onMapViewReady()
    // Create a job to generate the offline map passing in
    // the parameters and download directory.
    final generateOfflineMapJob = offlineMapTask.generateOfflineMap(
    parameters: parameters,
    downloadDirectoryUri: downloadDirectoryUri,
    );
    // Listen for status updates as the generate offline map
    // job runs.
    generateOfflineMapJob.onStatusChanged.listen((jobStatus) {
    try {
    // See next step.
    } on ArcGISException catch (e) {
    debugPrint('Error generating offline map: ${e.message}');
    }
    });
  7. If the job succeeds, set the arcgisMap property on the map view controller with the offline map result. If it fails, print out a message. If the job is running, print the percent complete.

    main.dart > onMapViewReady() > try{}
    // Listen for status updates as the generate offline map
    // job runs.
    generateOfflineMapJob.onStatusChanged.listen((jobStatus) {
    try {
    // If the job succeeds, show the offline map.
    if (generateOfflineMapJob.status == JobStatus.succeeded) {
    // Retrieve the offline map.
    final result = generateOfflineMapJob.result;
    if (result == null) return;
    // Set the map view controller's ArcGIS map to the offline map.
    _mapViewController.arcGISMap = result.offlineMap;
    debugPrint('Generate offline map: Complete');
    } else if (generateOfflineMapJob.status == JobStatus.failed) {
    // If the job fails, print out the error message.
    debugPrint(
    'Unable to generate a map for that area: ${generateOfflineMapJob.error?.message}',
    );
    } else {
    // Otherwise, get the progress and report it.
    final percentComplete = generateOfflineMapJob.progress;
    debugPrint('Percent complete: $percentComplete%');
    }
    } on ArcGISException catch (e) {
    debugPrint('Error generating offline map: ${e.message}');
    }
    });
  8. Start the generate offline map job.

    main.dart > onMapViewReady()
    } on ArcGISException catch (e) {
    debugPrint('Error generating offline map: ${e.message}');
    }
    });
    // Start the generate offline map job.
    generateOfflineMapJob.start();
    }
  9. Hot restart your 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 pinch, drag, and double-tab the map view to explore this offline map.

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

Option 2: Download the solution

  1. Click the Download solution link under Solution and unzip the file to a location on your machine.

  2. Open the project in VS code.

Set developer credentials in the solution

To allow your app users to access ArcGIS location services ArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. Learn more , use the developer credentials that you created in the Set up authentication step to authenticate requests for resources.

  1. In VS Code, open lib/main.dart.

  2. In the main() function, set the ArcGISEnvironment.apiKey value to your access token An access token is an authorization string that provides access to secure ArcGIS content, data, and services. Its capabilities are determined by the privileges it supports. It is obtained by implementing API key authentication, User authentication, or App authentication. Learn more .

    main.dart
    void main() {
    ArcGISEnvironment.apiKey = 'YOUR_ACCESS_TOKEN';
    runApp(const MainApp());
    }

    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.

Run the application

Follow these steps to run the application.

  1. In VS Code’s terminal, run:

    flutter pub upgrade
  2. Run:

    dart run arcgis_maps install
  3. Make sure you have an Android emulator, iOS simulator or physical device configured and running.

  4. In VS Code, select Run > Run Without Debugging.

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 pinch, drag, and double-tab the map view to explore this offline map.