I am having trouble trying to implement caching of map tiles to be used if the user doesn't have a network connection.
I have read through this sample code and attempted to implement it:
Export Tile Cache | ArcGIS for Developers
But there are a couple of problems I have encountered:
Ideally the functionality I am looking for is the arcgis map to maintain its own internal cache automatically. I could specify the maximum size of the cache and the arcgis map automatically caches map sections that have been downloaded, keeping sections in the cache that have been most recently viewed.
Does arcgis support this notion or do I need to manage a map cache manually such the sample code above? if so, how would you recommend going about this?
Solved! Go to Solution.
you can put a status listener on the TileLayer and listen for layer Initialized event when it becomes available from online. And before adding it to the mapView you can get the values of Full Extent and Min/Max scales. Then set these values on the MapView. To set the Extent use setMaxExtent() method.
tilelayer.setOnStatusChangedListener(new OnStatusChangedListener() { @Override public void onStatusChanged(Object source, STATUS status) { // TODO Auto-generated method stub if(source == tilelayer && status== STATUS.INITIALIZED){ mTileLayerExtent = tilelayer.getFullExtent(); mTileLayerMinScale = tilelayer.getMinScale(); mTileLayerMaxScale = tilelayer.getMaxScale(); } } });
mMapView.setMaxExtent(mTileLayerExtent); mMapView.setMinScale(mTileLayerMinScale); mMapView.setMaxScale(mTileLayerMaxScale);
Hi Mark,
Here are some answers to the problems that you have encountered,
1. The ExportTileCacheTask will the cache the area of the map specified by the Geometry areaOfInterest parameter in the ExportTileCacheParameters constructor.
ExportTileCacheParameters(boolean createAsTilePackage, int minLevelOfDetail, int maxLevelOfDetail, Geometry areaOfInterest, SpatialReference inSpatialRef)
The sample code is using the visible area of the map on screen as the extent to be downloaded. You can specify the envelope of the size you want around device's current location. Please make sure you are using our latest release 10.2.5 as we addressed a bug related areaOfInterest parameter.
2. For taking ArcGIS online basemaps offline please take a look at:
https://developers.arcgis.com/android/guide/create-an-offline-map.htm
In the "Include a Basemap" section it has a link to a group (http://links.esri.com/rtbasemaps) which list the services you need to use for taking a ArcGIS Online basemap offline.
These are hosted on http://tiledbasemaps.arcgis.com/ and password protected. You will need to be a part of an organization to be able to use them.
3. To get the current level of detail of the map, you can call getCurrentLevel() method on the ArcGISTiledMapServiceLayer instance,
int currentLOD = tiledlayer.getCurrentLevel();
We do not support the maintenance of downloaded tile cache's out of the box. That functionality is up to you to implement. One of that ArcGIS apps Collector implements this Go offline—Collector for ArcGIS | ArcGIS . You can figure out the size of the tile cache to be downloaded by using ExportTileCacheTasks estimateTileCacheSize() method,estimateTileCacheSize
public Future<Long> estimateTileCacheSize(final ExportTileCacheParameters params, final CallbackListener<Long> callback) {
and then proceed to download the tilecache. You can store the information such as the extent and LOD for the local tile cache on disk to figure out what areas you have covered locally in respect to the online map extent being viewed.
Hi Puneet,
Thanks for you reply.
I have managed to download & display a cached map tile in the map view now. But I have another question:
When I have the cached map loaded in the map view (with only level 16 cached), the map view can only pan an area slightly larger than the cached map area. So when the user reconnects to the network and I call reinitializeLayer(...) on the ArcGISTiledMapServiceLayer, the online layer loads but the map view is unable to pan any further than the area of the cached map.
How can I go about solving this issue? Would I have to set the map view extent so that it is able to pan for example the whole world?
Thanks,
Mark
Since you are downloading a local tile cache and adding it as the first layer to the MapView, the MapView is getting limited by the min / max scale on the localTiledLayer. You can try using the workflow illustrated in the sample and add the Online tiled layer as the first layer in the Mapview, and when you add the localTiledLayer, set the visibility of the online tiled layer to false. That way by switching the visibilities you can easily toggle between the two.
mMapView.getLayers()[0].setVisible(false);
mMapView.getLayers()[1].setVisible(true);
I do have the ArcGISTiledMapServiceLayer added first. Then the ArcGISLocalTiledLayer will be added if there is a network connection.
So the flow in the case of no network connection when the map activity is opened is:
The ArcGISTiledMapServiceLayer is created but fails to initialise due to no network connection
The ArcGISLocalTiledLayer is created with the last cached map tile
Then the user gains network connection and I call reinitializeLayer() on the ArcGISTiledMapServiceLayer
Is there a way to set the min / max scale that you mentioned to the whole world? Or is there a better way to do this?
you can put a status listener on the TileLayer and listen for layer Initialized event when it becomes available from online. And before adding it to the mapView you can get the values of Full Extent and Min/Max scales. Then set these values on the MapView. To set the Extent use setMaxExtent() method.
tilelayer.setOnStatusChangedListener(new OnStatusChangedListener() { @Override public void onStatusChanged(Object source, STATUS status) { // TODO Auto-generated method stub if(source == tilelayer && status== STATUS.INITIALIZED){ mTileLayerExtent = tilelayer.getFullExtent(); mTileLayerMinScale = tilelayer.getMinScale(); mTileLayerMaxScale = tilelayer.getMaxScale(); } } });
mMapView.setMaxExtent(mTileLayerExtent); mMapView.setMinScale(mTileLayerMinScale); mMapView.setMaxScale(mTileLayerMaxScale);
Thank you very much for your help. I was able to implement the simple cache as described above