ArcGIS Runtime SDK for Java

Take a map offline - on demand

The on-demand workflow allows your field workers to define an area of a map and control the map content to be taken offline. Your app can specify parameters and overrides to control the map's area of interest, max and min scale, filter features, include attachments, determine editing characteristics, and many other aspects of the map content. The aim of these parameters is to ensure that only essential map content is taken offline. Here are the steps for this on-demand workflow:

  1. Enable services for offline use
  2. Create an offline map task
  3. Create parameters to specify the map content
  4. Create a job to generate an offline map.
  5. Run the job

Enable services for offline use

The author of the web map must ensure that all services contained in the web map can be taken offline. The author can set these options when publishing, or later using any of the service management tools.

Raster and vector tiled services

You can allow tiled services data to be downloaded and used offline by following the instructions here:

Tiled and vector tiled services must have the exportTiles capability enabled.

Feature services

You can allow feature service data to be downloaded, edited, and changes synchronized by following the instructions here:

Feature services must be sync enabled.

The map author must confirm that ArcGIS Online can access these tiled and feature services.

Create an offline map task

Create an OfflineMapTask from either an online map or its portal item.

//Create a task from a map
offlineMapTask = new OfflineMapTask(map);

//or from an online map's portal item
offlineMapTask = new OfflineMapTask(portalItem);


We recommend that you examine the map's offline capabilities before you attempt to take the map offline to ensure that all layers and tables in the map can be taken offline. See Examine offline capabilities.

Create parameters to control the map content

When you take a map offline you want the map to contain all the content that is relevant to the field worker. However, be aware that the size of the map will directly affect the time it takes to generate the offline map and download it to your device. You can control the size of this map by limiting the map's area of interest to just the geographical area that the field worker needs. You can also manage many other aspects of the map to suit your workflow such as:

  • the map's max and min scale
  • whether basemaps are included in the map
  • whether to apply definition expression filters
  • whether to return all rows from a related table
  • whether to continue downloading the map if a single layer fails to be taken offline
  • including feature attachments
  • whether only the schema is provided for editable layers
  • update or replace map's metadata

If your use-case requires you to have more control over how individual layers and tables are downloaded, you can use the GenerateOfflineMapParameterOverrides to make those specific adjustments. Follow the steps outlined in Create generate offline map parameter overrides.

Create generate offline map parameters

When you take a map offline you can specify the map's area of interest to ensure that the smallest effective map is downloaded. Create the GenerateOfflineMapParameters by passing an area of interest to the createDefaultGenerateOfflineMapParametersAsync method on the OfflineMapTask. The area of interest can be either a polygon or an envelope geometry. The default parameters that are returned will match the advanced offline settings configured by the web map author.

Once you have obtained these parameters you can set any of their properties to control the offline map content.

// generate the default offline map parameters
ListenableFuture<GenerateOfflineMapParameters> parametersListenableFuture =

// listen in for the completion
parametersListenableFuture.addDoneListener(()-> {
  // try to get the parameters
  try {
    GenerateOfflineMapParameters offlineMapParameters = parametersListenableFuture.get();

    // Update any of these parameters values, if needed

    // Update the ItemInfo parameter if you want to change any of the information from the Portal...
    String title = offlineMapParameters.getItemInfo().getTitle() + " (Central)";

  } catch (Exception e) {

The parameters are described as follows:

Area of interest

The size of an offline map directly affects the time it takes to generate the offline map and download it to a device. Therefore, you should limit the map's geographical area to just the area that you need. You can define this area by passing a Geometry object to the areaofInterest property. Both polygon and envelope geometries are supported.

Scale range

Tiled layers are comprised of many tiles at different levels of detail. For a particular area of interest, the amount of space, generation time, and download time will increase significantly with every increased level of detail. It's strongly recommended that you only download the levels of detail that are relevant for your app. You can control this by setting the minimum and maximum scale parameters (minScale and maxScale). If possible, choose a maximum scale that is not too “zoomed in”, as this will generate a large number of unnecessary tiles. Each service has a limit to the number of tiles which can be taken offline. It's recommended that you always set a scale range to avoid hitting this limit.


On-demand workflow will honor the scale range of a tiled layer as specified by the web map. This behavior helps to ensure that only tile data required by the offline map will be downloaded.

For example, if the web map contains a tiled layer which is set to a min scale of 1:1,000,000 and a max scale of 1:10,000, these values will be applied to the scale range requested by the user. If a user requests the data with a scale range of 1:900,000 to 1:5,000, the minimum range of 1:900,000 (min scale defined in the user's parameters) to 1:10,000 (max scale defined on the web map) will be downloaded. If the user's parameters request the default scale values of 1:0, then the range from the web map will be applied.

Include a map's basemap

The author of the web map can define whether the map:

  • the basemap defined by the web map

    This is the default situation and ensures that a tile package is downloaded as part of the mobile map package.

  • a tile package that is already on the device

    The tile package must be downloaded or side loaded onto the device and can be located using an actual file path on the device or a path that is relative to the mobile map package. You must ensure that the tile package covers the areas required by your map area. The benefits of this option are that the mobile map package file will be smaller, the download time may be faster, and you can use the tile package in many different maps and apps.

    To use the tile package on your device you must set the referenceBasemapDirectory to the directory which contains the tile package. We recommend that you confirm that the tile package file, referenceBasemapFilename, exists on the device before running the AGSGenerateOfflineMapJob. This job will add the tile package, as a basemap, to the offline map.


    If this tile package has a different spatial reference to your online map then the offline map will use the spatial of the tile package.

  • no basemap

    If only want to take the operational layers offline you can programmatically exclude the basemap. To do this set the includeBasemap property to false. In this case the GenerateOfflineMapJob will not download any layers included as part of the map's basemap. This task will not use the local tile package, even if you have specified one.

Apply feature layer definition expression filters

Whilst taking a map offline the GenerateOfflineMapJob will apply the feature layer's definition expression by default. Applying the definition expression may reduce the number of features taken offline for display and sync. If you do not want to apply the definition expression then set the boolean value of IsDefinitionExpressionFilterEnabled to be false.

Return all rows from a related table

If a map contains a layer or table that has a relationship with another table then you can choose to download all, or only the related rows from the destination table. The default is to download only the related rows. If you want to return all rows then you must set the value of the destinationTableRowFilter to be .

If the table is not the direct destination of a feature table, or it is a standalone table, or it is the source of a relationship then all rows are returned.

For more information, see Essentials of relating tables.

Continue downloading the map if a single layer or table fails

By default the GenerateOfflineMapJob will continue to take layers and tables offline even if a layer or table has failed. Whilst this ensures that the map is taken offline there can be missing data. When this job completes you should examine the job's result to identify if and why any layers have failed. At this point you can decide whether to continue working with the map.

If you want the job to stop immediately, if a layer or table fails to download, then set the ContinueOnErrors property to be false. In this case if a map is successfully taken offline it will contain all of its layers and tables.

The failure to take a layer or table offline may be due to an intermittent network connection, loss of the service or an unsupported layer type.

Inclusion of feature attachments

Some feature services can add attachments (pictures, videos, and other documents) to individual features. Since these files can be large, you should consider your app's offline workflow to determine whether the attachments are needed by the app, and whether attachments need to be synchronized with the service when the app is next online. These two behaviors work in conjunction with each other, and are defined using the returnLayerAttachmentOption and attachmentSyncDirection properties on the GenerateOfflineMapParameters class.

  • The return layer attachment property defines which layers should contain attachments in the offline map. The options are:
    • NONE- None of the layers will contain any attachments.
    • ALL_LAYERS - All layers will have their attachments included.
    • READ_ONLY_LAYERS - Layers without editing enabled will have attachments included.
    • EDITABLE_LAYERS - Layers with editing enabled will have attachments included.
  • The attachment sync direction defines how the attachments are synchronized with the service. The options are:
    • NONE - Attachments are not synchronized as part of the synchronization operation.
    • UPLOAD - Attachments are uploaded from the client to the service, but any changes on the service are not downloaded to the client.
    • BIDIRECTIONAL - Attachments are uploaded from client to the service, and changes on the service are pulled down to the client.

    Attachment sync direction was introduced with ArcGIS Server 10.4.

Here are some workflows that describe how these two parameters affect each other.

  • Workflow 1 - Download attachments for all layers in the map, allow the user to add or remove attachments from the layers, and then synchronize these changes between the service and the client when online. For example: multiple users collect data on the same area and they want to synchronize all the changes with the centralized services as well as sharing changes with other people in the field.
    • returnLayerAttachmentOption.ALL_LAYERS
    • attachmentSyncDirection.BIDIRECTIONAL
  • Workflow 2 - Download attachments for all read-only layers and update these layers when online. For example: users are offline and viewing a layer of buildings with photos that show how the buildings look. If there are any new photos added to the service, these will be downloaded to the client during synchronization when online.
    • returnLayerAttachmentOption.READ_ONLY_LAYERS
    • attachmentSyncDirection.BIDIRECTIONAL
  • Workflow 3 - Download attachments for editable layers only and upload them to the service when online. For example: users are offline and only need to view attachments for editable layers. If there are any read-only layers that provide context for the map, their attachments aren’t included to the local map. If users remove or add any new attachments, these changes can be synchronized to the service when online.
    • returnLayerAttachmentOption.EDITABLE_LAYERS
    • attachmentSyncDirection.BIDIRECTIONAL
  • Workflow 4 - Do not download any attachments but allow any new attachments to be uploaded to the service when online. For example: users are offline and collecting new attachments in the field but do not need to view existing attachments.
    • returnLayerAttachmentOption.NONE
    • attachmentSyncDirection.UPLOAD

Inclusion of features from editable feature layers

If users are collecting new information in the field where they do not need to access previously created features, you can create an offline map with empty editable feature layers. Do this by setting the GenerateOfflineMapParameters property returnSchemaOnlyForEditableLayers to true.

Update or replace map's metadata

You can access the online map's metadata from the itemInfo property. It includes portal item properties such as the title, description, short description, and thumbnail. This information is populated from the portal item that contains the map. You can override any of these metadata properties before you take the map offline. For example, if you are creating offline maps of different areas of interest on the same map, you may want to change the map's title to indicate which area it contains.

You can also create a new OfflineMapItemInfo object and manually set all the details.

// Create new item info
OfflineMapItemInfo itemInfo = new OfflineMapItemInfo();

// Set metadata on the itemInfo
itemInfo.setTitle("Water network (Central)");
itemInfo.getTags().add("Water network");
itemInfo.getTags().add("Data validation");



Instead of obtaining the default set of GenerateOfflineMapParameters you could construct them manually. The author of the web map can recommend how data is downloaded to offline devices, and subsequently synchronized, by adjusting the map's advanced offline settings. You can access these advanced settings from the map's OfflineSettings. They provide recommended options for:

  • working with feature attachments
  • synchronizing edits
  • downloading a basemap or using one which is already on the device

Once you are happy with the changes you have made to your parameters call the generateOfflineMap method on the OfflineMapTask to create a GenerateOfflineMapJob. Run job is used to generate an offline map using the specified parameters.

Create generate offline map parameter overrides

Managing the map content may be sufficient for your workflow but in some cases you may also want to control how individual layers or tables are taken offline, such as:

  • reducing the amount of data (e.g. tile data) for a given layer
  • altering the spatial extent of a given layer (for example to give coverage beyond the study area)
  • filtering features (e.g. with a where clause) to only take those which are relevant to your field work
  • taking features with null geometry (e.g. where the attributes are populated in the office but the geometry needs to be captured on site)
  • omitting individual layers
If you need this fine-grained control then you must generate the GenerateOfflineMapParameterOverrides object. This object gives you access to three dictionaries containing the generate geodatabase parameters, export tile cache parameters and export vector tile parameters. Adjust any of these parameters and create the GenerateOfflineMapJob using the overrides object. To control the individual layers and tables that you take offline follow these steps:

  1. Generate and modify the GenerateOfflineMapParameters as described in Create generate offline map parameters above.
  2. Generate the parameter overrides object (GenerateOfflineMapParameterOverrides) using the generateOfflineMapParameterOverrides method on the OfflineMapTask. Provide the GenerateOfflineMapParameters generated from the previous step.
  3. When the task completes, the GenerateOfflineMapParameterOverrides will be initialised, honouring the settings in the supplied GenerateOfflineMapParameters. GenerateOfflineMapParameterOverrides will presents three sets of data-source parameters as dictionary structures:
    • GenerateGeodatabaseParameters
    • ExportTileCacheParameters
    • ExportVectorTileCacheParameters
    You may inspect the dictionaries and modify them before they are passed onto the job to download the map. Each dictionary contains key, value pairs where the key is an OfflineMapParametersKey and the value is a data-source specific parameter (e.g. a GenerateGeodatabaseParameters).

    // generate the offline map parameter overrides
    ListenableFuture<GenerateOfflineMapParameterOverrides> overridesListener =
    // listen for the completion
    overridesListener.addDoneListener(()-> {
      // try to get them
      try {
        GenerateOfflineMapParameterOverrides overrides = overridesListener.get();
        Map<OfflineMapParametersKey, ExportTileCacheParameters> tileCacheParams =
        Map<OfflineMapParametersKey, ExportVectorTilesParameters> vectorTileParams =
        Map<OfflineMapParametersKey, GenerateGeodatabaseParameters> gdbParams =
      } catch (Exception e) {

  4. If, however, you just want to look up a specific set of parameters for a specific layer or table, you can construct the key from the layer or the table and obtain the parameters from the dictionary.

    //get the offline map parameter key for a feature layer
    OfflineMapParametersKey parametersKey = new OfflineMapParametersKey(featureLayer);
    //return the generate geodatabase parameters from the parameter overrides dictionaries
    Map<OfflineMapParametersKey, GenerateGeodatabaseParameters> gdbParametersMap = 
    GenerateGeodatabaseParameters gdbParameters = gdbParametersMap.get(parametersKey);

Once you are happy with your changes, you can obtain a GenerateOfflineMapJob by calling generateOfflineMap on the offline map task supplying both the parameters and the overrides.

Create a job to generate an offline map

To generate and download the offline map you must create a GenerateOfflineMapJob by providing the GenerateOfflineMapParameters to the generateOfflineMapJob method on OfflineMapTask. You must provide a directory on the device to store the offline map. If this download directory already exists it must be empty. If the directory doesn't exist, it will be created by the job.

// create the job
offlineMapJob = offlineMapTask.generateOfflineMap(offlineMapParameters, downloadDir);

If you want to control the individual layer and table content you also need to provide the GenerateOfflineMapParameterOverrides as well as the GenerateOfflineMapParameters to the generateOfflineMapJob method on OfflineMapTask

// create the job
offlineMapJob = offlineMapTask.generateOfflineMap(offlineMapParameters, downloadDir, overrides);

Note that the job will behave the same whether it was created using just the GenerateOfflineMapParameters or using the GenerateOfflineMapParameterOverrides along with the GenerateOfflineMapParameters.

See the Tasks and jobs topic for more details on how to work with jobs in general.

Run the job

To generate the offline map and download it to your device start the GenerateOfflineMapJob . Upon completion the job will return an instance of the GenerateOfflineMapResult. If at least one table or layer failed to be taken offline the hasErrors property will be true. In this case you should examine the layerErrors and tableErrors dictionaries to identify the problem.

Remember that if the job's ContinueOnErrors parameter has been set to false then the job will be terminated immediately if a single layer or table fails to be taken offline.

If you want to display the map immediately then use the GenerateOfflineMapResult.offlineMap.

//start the job

// listen for the job complete event
offlineMapJob.addJobDoneListener(() -> {
  // did the job succeed?
  if (offlineMapJob.getStatus() == Job.Status.SUCCEEDED) {
      GenerateOfflineMapResult offlineMapResult = offlineMapJob.getResult();

    // were there any errors?
    if (offlineMapResult.hasErrors()) {
      // get the layer errors
      Map<Layer, ArcGISRuntimeException> layerErrors = offlineMapResult.getLayerErrors();

      // get the table errors
      Map<FeatureTable, ArcGISRuntimeException> tableErrors = offlineMapResult.getTableErrors();

    } else {
      // get the offline map which can be used straight away
      ArcGISMap offlineMap = offlineMapResult.getOfflineMap();

  } else {
    // code here to deal with failure

If you want to open the map offline in the field then open the mobile map package stored in the downloadDirectory.

Open the offline map

Offline maps created by the on-demand workflow are stored in an unpacked mobile map package. When your app goes into the field you will need to open the map directly from the mobile map package directory stored on your device. To create the mobile map package object, pass the mobile map package directory path to the MobileMapPackage constructor.

// Create a MobileMapPackage from the offline map directory path
final MobileMapPackage offlineMapPackage = new MobileMapPackage(mMobileMapPackage);
offlineMapPackage.addDoneLoadingListener(new Runnable() {
  public void run() {
    // Get the title from the package metadata
    System.out.println("Title: " + offlineMapPackage.getItem().getTitle());

    // Get the map from the package and set it to the MapView

Upon loading the offline map, its metadata is accessible using the ArcGISMap.item property. In some situations, you may want to access the metadata from the mobile map package without loading the map itself. You can access this from the MobileMapPackage.item property.

See Display a map for more details on how to access and display maps stored in mobile map packages.

Examine offline capabilities

We do not recommend that you take a map offline unless all its layers and tables can be taken offline, because the map will not be as complete as originally designed. If you do take a map offline anyway, you should be aware of which layers or tables are missing from the offline map.

Obtain the OfflineMapCapabilites object by calling the getOfflineMapCapabilities method on the offline map task. The boolean value will indicate whether at least one layer or table cannot be taken offline. Examine the LayerCapabilities and TableCapabilities to determine which layer or table cannot be taken offline along with the reason why.

For example, if the target map is using an ArcGIS map image layer (ArcGISMapImageLayer), then an error will be returned stating that the layer type is not supported by the OfflineMapTask.

Although this step is optional, it's recommended that you examine these capabilities as this will avoid unnecessary work on the services side.

final ListenableFuture<OfflineMapCapabilities> offlineMapCapabilitiesFuture =
offlineMapCapabilitiesFuture.addDoneListener(() -> {
  try {
    OfflineMapCapabilities offlineMapCapabilities = offlineMapCapabilitiesFuture.get();
    if (offlineMapCapabilities.hasErrors()) {
      // Handle possible errors with layers
      for (java.util.MapEntry<Layer, OfflineCapability> layerCapability : offlineMapCapabilities
        .getLayerCapabilities().entrySet()) {
        if (!layerCapability.getValue().isSupportsOffline()) {
          System.err.print(layerCapability.getKey().getName() + " cannot be taken offline.");
          System.err.println("Error : " + layerCapability.getValue().getError().getMessage());

      // Handle possible errors with tables
      for (java.util.Map.Entry<FeatureTable, OfflineCapability> tableCapability : offlineMapCapabilities
        .getTableCapabilities().entrySet()) {
        if (!tableCapability.getValue().isSupportsOffline()) {
          System.err.println(tableCapability.getKey().getTableName() + " cannot be taken offline.");
          System.err.println("Error : " + tableCapability.getValue().getError().getMessage());
    } else {
      // All layers and tables can be taken offline!
      System.out.println("All layers are good to go!");
  } catch (Exception e) {


  • Advanced symbols are supported only if they are defined in the original service. Any overrides with advanced symbols will result in empty symbols in an offline map.
  • Area-of-interest geometries that cross the dateline are not currently supported.
  • If more than one feature layer in a map refers to the same feature service endpoint, only one feature layer will be taken offline. The other feature layers will raise an error.