HERE Android SDK Developer's Guide

Offline Maps (MapLoader)

Even without an active data connection, applications developed with the HERE Android SDK let you browse, search and interact with maps. Classes involved with providing Offline Maps functionality include MapLoader, MapLoader.Listener, MapLoader.ResultCode and MapPackage.

An application can use MapLoader while it is performing another map operation. For example, an app can download map data while a user is panning a map.

Offline map functionality is invoked automatically, or you can also disable connectivity for the entire HERE SDK by using MapEngine.setOnline(false). Note that you can only set MapEngine.setOnline(true) when the device is online. If not, then the request is ignored.

MapLoader and MapLoader.Listener

Offline maps capabilities are enabled through the use of MapLoader and its associated objects. The MapLoader class provides a set of APIs that allow manipulation of the map data stored on the device. Operations include:

  • getMapPackages() - To retrieve the state of the map data on the device
  • installMapPackages(List<Integer> packageIdList) - To download and install new country or region data
  • uninstallMapPackages(List<Integer> packageIdList) - To uninstall and delete country or region data that is no longer desired
  • checkForMapDataUpdate() - To check whether a new map data version is available
  • performMapDataUpdate() - To perform a map data version update, if available
  • cancelCurrentOperation() - To cancel the running MapLoader operation

To use MapLoader, you must call MapLoader.getInstance() to retrieve a MapLoader object instance. Note that com.here.android.mpa.mapping.MapEngine must be successfully initialized before this method can be used.

MapLoader operations are performed asynchronously. Results of the various operations are returned by way of a MapLoader.Listener implementation that must be set to listen for notifications from the MapLoader as in the code snippet below:


MapLoader.Listener mapLoaderListener = new MapLoader.Listener() {
  public void onUninstallMapPackagesComplete(MapPackage rootMapPackage,
     MapLoader.ResultCode mapLoaderResultCode) {
  }
  public void onProgress(int progressPercentage) {
  }
  public void onPerformMapDataUpdateComplete(MapPackage rootMapPackage,
     MapLoader.ResultCode mapLoaderResultCode) {
  }
  public void onInstallationSize(long diskSize, long networkSize) {
  }
  public void onInstallMapPackagesComplete(MapPackage rootMapPackage,
      MapLoader.ResultCode mapLoaderResultCode) {
  }
  public void onGetMapPackagesComplete(MapPackage rootMapPackage,
      MapLoader.ResultCode mapLoaderResultCode) {
  }
  public void onCheckForUpdateComplete(boolean updateAvailable,
    String currentMapVersion,String newestMapVersion,
          MapLoader.ResultCode mapLoaderResultCode) {
  }
};

MapLoader mapLoader = MapLoader.getInstance();
mapLoader.addListener(mapLoaderListener);

Also, all operations of the MapLoader are mutually exclusive. For example, if method XYZ is called before the callback method ABC has returned a result, method XYZ returns false to indicate that the MapLoader is busy with another operation.

The MapPackage Class

The map data packages available for download are represented as a tree structure with the root map package representing the world map. The MapPackage class represents the model through which this tree structure is accessed. As shown in the preceding code snippet, many of the MapLoader.Listener callbacks returns the root MapPackage. The other MapPackage instances are accessed by recursing through the tree structure from the root.

The MapPackage state of a particular instance is not updated dynamically to reflect changes to map data on disk. Therefore if you retrieve MapPackage instance A, and then perform an installation operation (which returns MapPackage instance B through onInstallMapPackagesComplete()), MapPackage instance A does not reflect the updated map data state, but MapPackage instance B does. Therefore, always use the new MapPackage object returned by a given operation and update the representation in your application accordingly.

Note: The getSize() method returns the maximum install size of the map package, in kilobytes. If this is the first MapPackage to be installed, then the package takes up the same amount of memory storage as returned by this method. However, if other packages have already been installed, then the required disk space for this map package is considerably less than the value returned by getSize(), because common data between map packages does not need to be installed again. To get an accurate representation of the disk space that is used for a given installation operation, use the MapLoader.Listener.onInstallationSize(long, long) callback method.
Note: Map data packages may need to be reinstalled if the application crashes or is forced closed during MapLoader installation or uninstallation.

Incremental Map Data Updates

MapLoader exposes the ability to update the map data version to provide the user with the freshest map data available. The map data version applies not only to map data pre-installed using the MapLoader, but also to data that is retrieved dynamically by browing new areas.

Map data version is consistent for all map data across the entire system, whether the map data is downloaded or not. It is not possible to have some data from one map version and other data from another map version concurrent in the disk cache. Therefore, it is important to keep the map version of the system up to date. However, map version updating does not require re-downloading everything. Instead, only incremental changes need to be downloaded, making typical updates small and quick. Map version updating is exposed through the checkForMapDataUpdate() and performMapDataUpdate() methods.