# Create an offline map

This API allows your users to continue working and interacting with their maps and data if network connectivity is poor or non-existent. You can provide this functionality by adopting one of two workflow patterns:

• The Services Pattern: If you want to build apps that allow your users to take a map offline from ArcGIS Online or ArcGIS Enterprise, use the Services Pattern. Taking a map offline involves downloading a web map as a mobile map package to a device. Users can interact with an offline map, edit operational data, and synchronize changes with the online services when connectivity is restored. All of these tasks are undertaken by the app that you build. The Services pattern supports two workflows: a preplanned workflow, where the map's author creates the offline map, and an on-demand workflow, where the field worker creates the map.
• The Desktop Pattern: In this pattern, you use ArcGIS Pro to author and create a mobile map package file. You then deliver that read-only file to individual devices.

Please see the Offline documentation for more details on these workflows. The main advantages of working directly with a map, and not the individual layers, is that ArcGIS Runtime can use a single common map definition to handle how a map is created on the device. If you do wish to take individual layers offline see the Create an offline layer topic.

## Services Pattern

The Services Pattern allows you to build apps that can download areas of ArcGIS Online or ArcGIS Enterprise web maps to your device. Each map is stored as a mobile map within an exploded mobile map package. Since the mobile map conforms to the web map specification, it is used by the API to reconstruct the map using basemap data, operational layers, symbology definitions, popup configurations, and other data that are stored within the mobile map package. This pattern allows your users to edit their operational data and synchronize it with the online service when connectivity is restored. There are two workflows available:

• The Preplanned workflow: where the map author defines a map area and generates the offline map ahead of time; so that your field workers can download the map and take into the field.
• The On-demand workflow: where the field worker defines the map area, generates the offline map content, and downloads the map to their device.

These are described more fully in the Offline topic.

When a web map is created to be taken offline, the author must ensure that all of the services used by the map have been enabled for offline use. If this is not done, your offline map may not contain all of the layers and tables that you expect.

### Enable services for offline use

The author of the web map must ensure that all of the services contained in the web map can be taken offline. You can set these options when publishing, or later on, 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:

#### Feature Services

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

The map author must confirm that ArcGIS Online can access these tiled and feature services. The services must have public access and be shared with everyone.

You can now adopt the Preplanned or On-Demand workflow and create the mobile map.

##### Note:

As of the 100.2 release, the Services Pattern supports taking the following services offline:

• Tiled and vector tiled services that have the exportTiles capability enabled.
• Feature services that have sync enabled.
• Feature collections that are read only and are stored along with the map information.

## Preplanned workflow

The Preplanned workflow allows an organization to prepare a mobile map in advance of a field worker entering the field. To do this the map owner must create a map area that defines a specific geographical area of work and then generate the individual data files that comprise the mobile map package. This mobile map package resides in ArcGIS Online until the field worker is ready to download it. Once the download job has completed the field worker can disconnect the device and work with the map offline. This workflow is discussed in detail in the following steps:

Here are the steps required for this workflow:

### Create preplanned map areas

The Preplanned workflow allows you to create a mobile map, in advance, so that it can be downloaded by the field worker when they need it. To do this you need to specify the area of interest, create a map area from a web map and generate the data packages for each of the services defined in the web map. Use the ArcGIS REST API to create a mobile map as follows:

1. To create a map area you must run the Create Map Area task providing a bookmark or geographical extent as the area of interest. Upon completion the task will generate a new portal item of type MapArea. This task requires that the web map is enabled for offline use and is only available to the owner of the web map and organization administrators.
2. To create the data defined by the map area you must run the Setup Map Area task providing the map area portal item ID. This will create a set of data files such as tile packages, vector tile packages and SQLite geodatabases. For good data management, we strongly recommend that you also provide a folder to organize these files. This task is only available to the map area portal item owner and organization administrators

##### Note:
The map's author can repeat these steps and create up to 16 individual map areas per web map.

The preplanned map areas and their related data are now ready to be downloaded to a device. This download phase is carried out by the Runtime app that you build.

As discussed above, each web map can provide one or more preplanned map areas. You may wish to build an app that allows the field worker to select and download a map area or you may wish to use the app logic to download a specific map area for the field worker. For either approach follow these steps:

1. Instantiate the offline map task by passing either a map (created from an web map) or a web map's portal item to the OfflineMapTask constructor.
2. Retrieve a list of the preplanned map areas from the web map.
3. Identify and select a map area.

// open map from a portal item
map = new ArcGISMap(portalItem);

// create an offline map task

//get all of the preplanned map areas in the web map
try {
// get the list of areas
List<PreplannedMapArea> mapAreas = mapAreasFuture.get();

// loop through the map areas
for (PreplannedMapArea mapArea : mapAreas) {
// get the map area geometry so the is can used to display a graphic on the map
Geometry areaGeometry = mapArea.getAreaOfInterest();

// get the area title so it can be used in a UI component
String areaTitle = mapArea.getPortalItem().getTitle();

// UI code for showing map areas goes here:
});

}

} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
}

To download a preplanned map area, you need to run a job that will download the exploded mobile map package to the device. You create this job by passing the preplanned map area, PreplannedMapArea, and a destination directory on disk to the downloadPreplannedOfflineMapJob method on OfflineMapTask. For more details on how to work with jobs, see the Tasks and jobs topic.

When the DownloadPreplannedOfflineMapJob is finished, it will return an instance of DownloadPreplannedOfflineMapResult. If the hasErrors property is set to true then there was at least one table or layer that failed to be taken offline and indicates that a more detailed inspection of the results is needed.

If you want to use the offline map immediately, you can use the DownloadPreplannedOfflineMapResult.offlineMap.

// create an offline map task

// create the job

//start the job

// listen for job complete

// check for errors
// code here to examine errors:

} else {
// no errors so use the map straight away

}
});

If you want to open the map offline while in the field, load the exploded mobile map package stored in the downloadDirectory.

##### Note:

At ArcGIS Runtime SDK version 100.2, the Preplanned workflow is available in ArcGIS Online. This will become available in upcoming releases of ArcGIS Enterprise.

## On-demand workflow

The On-demand workflow allows a field worker to define the exact area of a map that they wish to take into the field. Although, the online map's author must create the web map and ensure that any services that are going to be taken offline have been enabled for offline use, the field worker actually controls area of interest, the max and min scale and many other parameters. Once the job to generate the map and download it to the device has completed the field worker can disconnect the device and work with the map offline. This workflow is discussed in detail in the following steps:

### Specify parameters

When you create an offline map, use the GenerateOfflineMapParameters class to control:

A set of default parameters ( createDefaultGenerateOfflineMapParametersAsync) is created using the method on OfflineMapTask. This method also loads the map's portal item, and copies its metadata to the itemInfo property, in preparation for copying it to an offline map.

// Create default parameters
final ListenableFuture<GenerateOfflineMapParameters> parametersFuture =
try {
GenerateOfflineMapParameters parameters = parametersFuture.get();

// Update the parameters if needed
// Limit maximum scale to 5000 but take all the scales above (use 0 as a MinScale)
parameters.setMaxScale(5000);

// only upload attachments from the client
// only include attachments with editable layers
parameters.setReturnLayerAttachmentOption(ReturnLayerAttachmentOption.EDITABLE_LAYERS);
// Request the table schema only (existing features won't be included)
parameters.setReturnSchemaOnlyForEditableLayers(true);

// Update the title to contain the region
parameters.getItemInfo().setTitle(parameters.getItemInfo().getTitle() + " (Central)");

// Override thumbnail with the new image based on the extent
final ListenableFuture<Image> exportImageFuture = mapView.exportImageAsync();
try {
Image exportImage = exportImageFuture.get();
// scale to thumbnail size
ImageView exportImageView = new ImageView(exportImage);
exportImageView.setFitWidth(200);
exportImageView.setFitHeight(133);
Image thumbnail = exportImageView.snapshot(null, null);
// convert to byte[]
BufferedImage thumbnailBuffered = SwingFXUtils.fromFXImage(thumbnail, null);
ByteArrayOutputStream thumbnailStream = new ByteArrayOutputStream();
ImageIO.write(thumbnailBuffered, "png", thumbnailStream);
byte[] thumbnailBytes = thumbnailStream.toByteArray();
thumbnailStream.close();

parameters.getItemInfo().setThumbnailData(thumbnailBytes);
} catch (Exception e) {
e.printStackTrace();
}
});

// ... add code below to:
//  - Create map's metadata properties
//  - Examine map's offline capabilities
//  - Open and use the offline map
} catch (Exception e) {
e.printStackTrace();
}
});

#### 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. Since the generation and download speed is directly proportional to the size of the map, 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.

##### Note:

We recommended that the area of interest is in the same spatial reference as the map to be taken offline. Without this, the layers may not be visible after the offline map is generated.

#### Scale range

Tiled layers comprise a number of 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.

##### Note:

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.

#### Inclusion of the map's basemap

In some workflows, you may want to exclude the basemap from the map and only take the operational layers offline. This provides a smaller file size, faster package generation, and a reduced download time. If you set the includeBasemap property to false, the OfflineMapTask will ignore all the layers included as part of the ArcGISMap's basemap.

If you exclude the basemap from your offline map, you will need to add a basemap into your map after it has been loaded. For example, if you have a workflow where you are sideloading a basemap to the device, there is no need to generate and download a basemap with every offline map. You can just add it as a basemap to your offline map.

#### Inclusion of feature attachments

Some feature services have the ability to 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 of the 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.
##### Note:

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

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

#### Inclusion of the map's metadata

You can access an 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. Get this metadata by creating the GenerateOfflineMapParameters using the createDefaultGenerateOfflineMapParameters method on the OfflineMapTask. 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 and manually set all the details.

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

// Create new thumbnail from the map
final ListenableFuture<Image> exportImageFuture = myMapView.exportImageAsync();
try {
Image mapImage = exportImageFuture.get();
// scale to thumbnail size
ImageView mapImageView = new ImageView(mapImage);
mapImageView.setFitWidth(200);
mapImageView.setFitHeight(133);
Image thumbnail = mapImageView.snapshot(null, null);
// convert to byte[]
BufferedImage thumbnailBuffered = SwingFXUtils.fromFXImage(thumbnail, null);
ByteArrayOutputStream thumbnailStream = new ByteArrayOutputStream();
ImageIO.write(thumbnailBuffered, "png", thumbnailStream);
byte[] thumbnailBytes = thumbnailStream.toByteArray();
thumbnailStream.close();

// Set values to the itemInfo
itemInfo.setThumbnailData(thumbnailBytes);
itemInfo.setTitle("Water network (Central)");
itemInfo.setSnippet(webmapItem.getSnippet()); // Copy from the source map
itemInfo.setDescription(webmapItem.getDescription()); // Copy from the source map
itemInfo.setAccessInformation(webmapItem.getAccessInformation()); // Copy from the source map

parameters.setItemInfo(itemInfo);
} catch (Exception e) {
e.printStackTrace();
}
});

##### Note:

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

### Examine offline capabilities

There are many things that determine whether a map or its layers and tables can be taken offline. Use the getOfflineMapCapabilitiesWithParameters method of the offline map task to explore this information. If there are layers or tables that cannot be taken offline you will get a 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. It's not recommended that you take a map offline unless all of its layers and tables can be taken offline, because the map will not be 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.

final ListenableFuture<OfflineMapCapabilities> offlineMapCapabilitiesFuture =
try {
OfflineMapCapabilities offlineMapCapabilities = offlineMapCapabilitiesFuture.get();
if (offlineMapCapabilities.hasErrors()) {
// Handle possible errors with layers
for (java.util.Map.Entry<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) {
e.printStackTrace();
}
});

You need to run a job to generate an offline map. You can create this job by passing the GenerateOfflineMapParameters and a destination path on disk to the generateOfflineMapJob method on OfflineMapTask. Running this job will create an offline map, using the specified parameters, to the path on disk. To see more details on how to work with jobs in general, see the Tasks and jobs topic.

When the GenerateOfflineMapJob is finished, it will return an instance of GenerateOfflineMapResult. If the hasErrors property is set to true then there was at least one table or layer that failed to be taken offline. This indicates whether a more detailed inspection of the results is needed.

If you want to use the offline map immediately, you can use the GenerateOfflineMapResult.offlineMap.

// Create default parameters
// GenerateOfflineMapParameters parametersFuture
final ListenableFuture<GenerateOfflineMapParameters> parametersFuture =
try {
GenerateOfflineMapParameters generateOfflineMapParameters = parametersFuture.get();

// Create and start a job to generate the offline map
final GenerateOfflineMapJob generateOfflineJob =
generateOfflineJob.start();
GenerateOfflineMapResult result = generateOfflineJob.getResult();

if (!result.hasErrors()) {
MobileMapPackage mobileMapPackage = result.getMobileMapPackage();
// Job is finished and all content was generated
System.err.println("Map " + mobileMapPackage.getItem().getTitle() +
" saved to " + mobileMapPackage.getPath());

// Show offline map in a MapView
myMapView.setMap(result.getOfflineMap());
} else {
// Job is finished but some of the layers/tables had errors
if (result.getLayerErrors().size() > 0) {
for (java.util.Map.Entry<Layer, ArcGISRuntimeException> layerError : result.getLayerErrors().entrySet()) {
System.err.print("Error occurred when taking " + layerError.getKey().getName() + " offline.");
System.err.println("Error : " + layerError.getValue().getMessage());
}
}
if (result.getTableErrors().size() > 0) {
for (java.util.Map.Entry<FeatureTable, ArcGISRuntimeException> tableError : result.getTableErrors().entrySet()) {
System.err.print("Error occurred when taking " + tableError.getKey().getTableName() + " offline.");
System.err.println("Error : " + tableError.getValue().getMessage());
}
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
});

If you want to open a map offline in the field, open the exploded mobile map package stored in the downloadDirectory and access the map.

### Limitations

• 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 end point, only one feature layer will be taken offline. The other feature layers will raise an error.

## Desktop Pattern

The desktop pattern is based on mobile map packages created with ArcGIS Pro. A mobile map package (*.mmpk file) is a self-contained package that can contain one or more maps, their associated layers and data, and optionally networks and locators. Mobile map packages are used across the ArcGIS platform because they adhere to a common package definition.

If you'd like a ready-to-use and regularly updated locator (and network dataset) for your area of interest, you can license StreetMap Premium data in mobile map package format. For details, see Add StreetMap Premium data.

### Open a mobile map package

You can inspect the contents of a mobile map package by constructing the MobileMapPackage class from the path to the package. You must load the package to access the maps (which may contain networks for routing and locators for geocoding). Each map within the mobile map packages will also contain its own item metadata.

### Open a mobile map

Once you have determined which map to use, you can pass it to the map view to be displayed. This map is no different from a web map from ArcGIS Online or ArcGIS Enterprise. The map contains operational layers, a basemap, and optionally bookmarks and other data. For additional details on creating mobile map packages and using them in your app, see Create a map object from a mobile map package.

### Mobile map capabilities

Mobile map packages can contain the following layer types:

• Feature layers from feature classes - these are consolidated into a geodatabase for each workspace type and are accessed as geodatabase feature tables. These can include definition expressions.
• Vector tiled layers from vector tile caches - these are packaged as a vector tile package and are accessed as an ArcGIS vector tiled layer
• Basemaps created from multiple feature layers - all feature layers inside the ArcGIS Pro basemap layer collection get consolidated into a single mobile basemap layer. These compressed, high-performance vector layers maintain the full GIS data for your features yet allow you to use them as basemap layers.

##### Note:

At the 100.2 release, the Desktop Pattern supports taking the following services offline:

• Tiled image raster services that have the exportTiles capability enabled.
• Vector tiled services.
• Feature services.

### Limitations

Some data and map configurations from ArcGIS Pro are not fully supported inside mobile map packages. For example:

• Label placement - The ArcGIS Runtime label placement engine differs from that used in ArcGIS Pro. Therefore, label positions and visibility can appear different. The following label options in ArcGIS Pro are converted to label properties inside mobile map packages:
• Allow overrun options - an allow overrun true/false property.
• Label placement options, including place overlapping - deconfliction strategy property of none, static or dynamic as well as a label placement property which is used as the initial preferred location of the label. If dynamic deconfliction is being used, then the label will move clockwise from this position to find clear space.
• Duplicate labels and label largest part options - a multipart property of label per segment, label largest, or label per part.
• Line connection options - these result in a line connection property of none, minimize labels, or unambiguous labels.
• Label priority ranking.
• Remove duplicate options, including distance - a remove duplicate property of none, all, or features type, as well as a remove duplicate distance property.
• Repeat label options, including distance - a repeat label property of true or false as well as a repeat distance property.
• Stacking label options, including alignment - a stack label property of true or false as well as a stack alignment property of dynamic (assign the alignment depending upon the label's position with respect to its feature) or text symbol (follow the alignment specified in the text symbol).
• Analyzer restrictions - There are also various restrictions applied through analyzers when creating a mobile map package. Some of the more important items are listed below:
• In each map, all basemap layers must share the same workspace.
• Maps cannot be packaged with operational layers and basemap layers that reference the same workspace.
• The network dataset must be in a geodatabase of version 10 or greater.
• Network attributes cannot contain script evaluators.
• The spatial reference of the map must match the spatial reference of the vector tile layer.
• A layer's extent must intersect the map.
• Layer datasets cannot contain custom features or class extensions.
• Live traffic is not supported.
• The network should have length, time, and default cost attributes to be able to successfully generate directions.
• Network field names cannot be longer than 31 characters.
• Scenes - Adding scenes to mobile map packages is not supported.

## Open a map offline

Offline maps created by the Preplanned workflow, the On-demand workflow, or the Desktop pattern are stored within mobile map packages. When your app goes into the field you will need to open the map directly from the mobile map package stored on your device. To create the mobile map package object, you must pass the mobile map package path to the MobileMapPackage constructor.

For the Preplanned and On-demand workflows, the mobile map package is stored in an exploded format so the path is the mobile map package directory. For the Desktop patterns, the mobile map package is stored in an archived format so the path is the mobile map package file path (*.mmpk)

// create the mobile map package
MobileMapPackage mapPackage = new MobileMapPackage("path/to/file.mmpk");
// add done listener which will invoke when mobile map package has loaded
// check load status and that the mobile map package has maps
// add the map from the mobile map package to the MapView
mapView.setMap(mapPackage.getMaps().get(0));
} else {
// display error if fails to load
mapPackage.loadAsync();