MapQuest Maps Android SDK

Offline Maps

The MapQuest Maps SDK automatically caches about 50MB worth of styles and tiles locally, however if you need to download a specific region the latest SDK supports this with some limitations detailed below.

The MapQuest Maps SDK downloads tiles when any connection is available and because only individual highly-optimized tiles download there should be no large downloads incured just by opening the map in a region that's already downloaded unless the user is browsing a very large amount of tiles. When the SDK automatically updates offline map tiles, the offline region is not re-download from scratch. The offline tile update process is the same process as with regular map tiles: The map tile's only downloaded if there's a new version of that tile.

Downloading a region

Downloading a region requires first defining a region and some meta-data for user-visible names of the downloaded region. Then you pass this into the OfflineManager to download the region. When defining a region to download, keep in mind the following requirements:

  • The definition needs the device's screen density. It's best to get this from the activities resources.
  • The bounds used for the download must not go over the 6,000 tile limit.
// Set up the OfflineManager
offlineManager = OfflineManager.getInstance(SimpleOfflineMapActivity.this);

// Create a bounding box for the offline region
LatLngBounds latLngBounds = new LatLngBounds.Builder()
  .include(new LatLng(40.307155, -105.378504)) // Northeast
  .include(new LatLng(39.328620, -104.583757)) // Southwest
  .build();

// Define the offline region
OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(
  mapboxMap.getStyleUrl(),
  latLngBounds,
  10,
  20,
  MainActivity.this.getResources().getDisplayMetrics().density);


// Implementation that uses JSON to store Denver as the offline region name.
byte[] metadata;
try {
  JSONObject jsonObject = new JSONObject();
  jsonObject.put(JSON_FIELD_REGION_NAME, "Denver Metro Area");
  String json = jsonObject.toString();
  metadata = json.getBytes(JSON_CHARSET);
} catch (Exception exception) {
  Log.e(TAG, "Failed to encode metadata: " + exception.getMessage());
  metadata = null;
}

// Create the region asynchronously
offlineManager.createOfflineRegion(definition, metadata,
  new OfflineManager.CreateOfflineRegionCallback() {
    @Override
    public void onCreate(OfflineRegion offlineRegion) {
      offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);

      // Monitor the download progress using setObserver
      offlineRegion.setObserver(new OfflineRegion.OfflineRegionObserver() {
        @Override
        public void onStatusChanged(OfflineRegionStatus status) {

          // Calculate the download percentage
          double percentage = status.getRequiredResourceCount() >= 0
          ? (100.0 * status.getCompletedResourceCount() / status.getRequiredResourceCount()) :
          0.0;

          if (status.isComplete()) {
            // Download complete
            Log.d(TAG, "Region downloaded successfully.");
          } else if (status.isRequiredResourceCountPrecise()) {
            Log.d(TAG, percentage);
          }
        }

        @Override
        public void onError(OfflineRegionError error) {
          // If an error occurs, print to logcat
          Log.e(TAG, "onError reason: " + error.getReason());
          Log.e(TAG, "onError message: " + error.getMessage());
        }

        @Override
        public void mapboxTileCountLimitExceeded(long limit) {
          // Notify if offline region exceeds maximum tile count
          Log.e(TAG, "Maps SDK Tile count limit exceeded: " + limit);
        }
      });
    }

  @Override
  public void onError(String error) {
    Log.e(TAG, "Error: " + error);
  }
});

Managing Downloaded Regions

Once a region is downloaded, you will want to be able to list the downloaded regions including deleting regions. Deleting a region also cleans up the off-line database. The sample below shows how to list regions and delete the last one.

offlineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
        @Override
        public void onList(OfflineRegion[] offlineRegions) {
          if (offlineRegions.length > 0) {
            // delete the last item in the offlineRegions list
            offlineRegions[(offlineRegions.length - 1)].delete(new OfflineRegion.OfflineRegionDeleteCallback() {

              @Override
              public void onDelete() {
                Log.e(TAG, "Deleted region");
              }

              @Override
              public void onError(String error) {
                Log.e(TAG, "On Delete error: " + error);
              }
            });
          }
        }
    }

Offline Management Plugin

A user's device won't always have a strong enough internet connection to download and view map tiles. You might want to build an offline mode into your Android project to account for this situation. The Offline Plugin for Android is a convenient way to send information to the OfflineManager class class and use the manager in a background service to download map tiles for offline use. Once the offline download region is defined and initialized, the plugin handles everything else for you. Because the plugin uses a service, the downloading continues even if when your application is running in the background.

Limitations

An app can download multiple regions for offline use, but the total offline download is capped at a maximum tile count “ceiling” across all downloaded regions of about 6000 tiles. As an example, the Denver Metro Area is about 40-50 tiles.

The SDK places no limit on the number of offline regions that may be created. Our terms of service do not allow you or an end user to redistribute offline maps downloaded.