The last version of arcgis for android is 10.2.9. It is said that the version will not be updated and maintained after that, but will jump directly to the 100 series, which is quite different from the previous version. But it also adds more functions and optimizes performance a lot. Specific differences are not repeated here, more than 100 versions will be able to feel.
This section mainly talks about the new version of the Internet map reference, mainly refers to the commonly used sky map, Google Map. In fact, loading Baidu and Golden Maps is the same principle, but because their map coordinate data are Mars coordinates, for professional GIS development, it can not be used.
1. Overload ImageTiled Layer. There are two main methods to implement.
One is the constructor: protected Image Tiled Layer (Tile Info tileInfo, Envelope full Extent)
One is tile download function: protected abstract byte[] getTile(TileKey var1)
2. According to our previous experience, the constructor is mainly the TileInfo parameter construction, which can be carried over.
Code directly
BaseMapLayer class
public class BaseMapLayer extends ImageTiledLayer { //Sky-Earth, Google Vector Map and Image Map Constants public static final int MAPLAYER_TIANDI_VECTOR = 1; public static final int MAPLAYER_TIANDI_IMAGE = 2; public static final int MAPLAYER_GOOGLE_VECTOR = 3; public static final int MAPLAYER_GOOGLE_IMAGE = 4; //Image map labeling constants public static final int MAPLAYER_TIANDI_IMAGE_LABEL = 5; public static final int MAPLAYER_TIANDI_VECTOR_LABEL = 6; private static double[] scales = new double[]{591657527.591555, 295828763.79577702, 147914381.89788899, 73957190.948944002, 36978595.474472001, 18489297.737236001, 9244648.8686180003, 4622324.4343090001, 2311162.217155, 1155581.108577, 577790.554289, 288895.277144, 144447.638572, 72223.819286, 36111.909643, 18055.954822, 9027.9774109999998, 4513.9887049999998, 2256.994353, 1128.4971760000001}; private static double[] resolutions = new double[]{156543.03392800014, 78271.516963999937, 39135.758482000092, 19567.879240999919, 9783.9396204999593, 4891.9698102499797, 2445.9849051249898, 1222.9924525624949, 611.49622628138, 305.748113140558, 152.874056570411, 76.4370282850732, 38.2185141425366, 19.1092570712683, 9.55462853563415, 4.7773142679493699, 2.3886571339746849, 1.1943285668550503, 0.59716428355981721, 0.29858214164761665}; private static Point origin = new Point(-20037508.342787, 20037508.342787, SpatialReference.create(3857)); int type = 0; protected BaseMapLayer(TileInfo tileInfo, Envelope fullExtent) { super(tileInfo, fullExtent); } protected BaseMapLayer(CoreImageTiledLayer coreTiledLayer, boolean addToCache) { super(coreTiledLayer, addToCache); } public static BaseMapLayer CreateBaseMapLayer(int type) { List<LevelOfDetail> levelOfDetails = MapTilesTool.getLevelOfDetails(); try { TileInfo tileInfo = new TileInfo(96, TileInfo.ImageFormat.MIXED, levelOfDetails , origin , SpatialReference.create(3857) , 256, 256); Envelope fullExtent = new Envelope(-22041257.773878, -32673939.6727517, 22041257.773878, 20851350.0432886, SpatialReference.create(3857)); BaseMapLayer layer = new BaseMapLayer(tileInfo, fullExtent); layer.type = type; return layer; } catch (Exception e) { e.printStackTrace(); } return null; } public static String getUrl(int type) { String[] subDomains = null; String urlPart = ""; String flag = ""; switch (type) { case MAPLAYER_TIANDI_VECTOR://Sky Map Vector Map subDomains = new String[]{"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"}; urlPart = ".tianditu.com/DataServer?T=vec_w"; flag = "l"; break; case MAPLAYER_TIANDI_IMAGE://Sky Map Image Map subDomains = new String[]{"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"}; urlPart = ".tianditu.com/DataServer?T=img_w"; flag = "l"; break; case MAPLAYER_GOOGLE_VECTOR://Google Vector Map subDomains = new String[]{"mt0", "mt1", "mt2", "mt3"}; urlPart = ".google.cn/vt/hl=zh-CN"; flag = "z"; break; case MAPLAYER_GOOGLE_IMAGE://Google Image Map subDomains = new String[]{"mt0", "mt1", "mt2", "mt3"}; urlPart = ".google.cn/vt/lyrs=s@105&hl=zh-CN"; flag = "z"; break; case MAPLAYER_TIANDI_IMAGE_LABEL://Sky Map Image Map Labeling subDomains = new String[]{"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"}; urlPart = ".tianditu.com/DataServer?T=cia_w"; flag = "l"; break; case MAPLAYER_TIANDI_VECTOR_LABEL://Vector Map Labeling of Sky Map subDomains = new String[]{"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"}; urlPart = ".tianditu.com/DataServer?T=cva_w"; flag = "l"; break; } if (subDomains != null) { String subDomain = subDomains[new Random().nextInt(100) % subDomains.length]; String url = "http://" + subDomain + urlPart + "&x=%d&" + "y=%d&" + flag + "=%d"; return url; } return null; } public static double getResolution(int level) { if (level < resolutions.length) return resolutions[level]; else return 1; } @Override protected byte[] getTile(TileKey tileKey) { byte[] iResult = null; String mapCache = CacheUtil.getMapCache() + "//"; mapCache += type + "//"; mapCache += tileKey.getLevel(); File f0 = new File(mapCache); if (!f0.exists()) { f0.mkdirs(); } String fileName = String.format("%d_%d.dat", tileKey.getColumn(), tileKey.getRow()); File f = new File(mapCache + "//" + fileName); if (f.exists()) { iResult = CacheUtil.ReadFile(f.getPath()); } if (iResult == null || iResult.length == 0) { try { boolean hasNetwork = MapTilesTool.isNetworkConnected(); if (!hasNetwork) return null; String baseUrl = getUrl(type); if (baseUrl == null) return new byte[0]; String url = String.format(baseUrl, tileKey.getColumn(), tileKey.getRow(), tileKey.getLevel()); iResult = downTile(url); if (iResult != null) CacheUtil.WriteFile(f.getPath(), iResult); } catch (Exception ex) { ex.printStackTrace(); } } return iResult; } private byte[] downTile(String iPath) { try { //Links to resources URL url = new URL(iPath); InputStream inputStream = url.openStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // Start reading data byte[] buffer = new byte[1024]; int len = 0;// Length of data read at a time while ((len = inputStream.read(buffer)) != -1) {// When len is - 1, it means there is no data. // append method adds data to sb object outputStream.write(buffer, 0, len); } inputStream.close(); // Output string return outputStream.toByteArray(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return new byte[0]; } }
MapTilesTool class
public class MapTilesTool { private static double[] scales = new double[]{591657527.591555, 295828763.79577702, 147914381.89788899, 73957190.948944002, 36978595.474472001, 18489297.737236001, 9244648.8686180003, 4622324.4343090001, 2311162.217155, 1155581.108577, 577790.554289, 288895.277144, 144447.638572, 72223.819286, 36111.909643, 18055.954822, 9027.9774109999998, 4513.9887049999998, 2256.994353, 1128.4971760000001}; private static double[] resolutions = new double[]{156543.03392800014, 78271.516963999937, 39135.758482000092, 19567.879240999919, 9783.9396204999593, 4891.9698102499797, 2445.9849051249898, 1222.9924525624949, 611.49622628138, 305.748113140558, 152.874056570411, 76.4370282850732, 38.2185141425366, 19.1092570712683, 9.55462853563415, 4.7773142679493699, 2.3886571339746849, 1.1943285668550503, 0.59716428355981721, 0.29858214164761665}; public static MapServerTileInfo PJson2MapServerInfo(MapServerPJson pJson) { if (pJson == null || pJson.getTileInfo() == null) { return null; } MapServerTileInfo tileInfo = new MapServerTileInfo(); tileInfo.dpi = pJson.getTileInfo().getDpi(); tileInfo.tileHeight = pJson.getTileInfo().getCols(); tileInfo.tileWidth = pJson.getTileInfo().getRows(); int wkid = pJson.getTileInfo().getSpatialReference().getWkid(); tileInfo.spatialReference = SpatialReference.create(wkid); tileInfo.origin = new Point(pJson.getTileInfo().getOrigin().getX() , pJson.getTileInfo().getOrigin().getY() , SpatialReference.create(wkid)); MapServerPJson.FullExtentBean fullExtentBean = pJson.getFullExtent(); tileInfo.fullExtent = new Envelope(fullExtentBean.getXmin(), fullExtentBean.getYmin(), fullExtentBean.getXmax(), fullExtentBean.getYmax(), SpatialReference.create(wkid)); int i = 0; List<LevelOfDetail> levelOfDetails = new ArrayList<>(); for (MapServerPJson.TileInfoBean.LodsBean lodsBean : pJson.getTileInfo().getLods()) { LevelOfDetail detail = new LevelOfDetail(i, lodsBean.getResolution(), lodsBean.getScale()); levelOfDetails.add(detail); i++; } tileInfo.levelOfDetails = levelOfDetails; tileInfo.minScale = pJson.getMinScale(); tileInfo.maxScale = pJson.getMaxScale(); return tileInfo; } public static List<LevelOfDetail> getLevelOfDetails() { List<LevelOfDetail> levelOfDetails = new ArrayList<>(); int level = 0; for (; level < scales.length; level++) { LevelOfDetail detail = new LevelOfDetail(level, resolutions[level], scales[level]); levelOfDetails.add(detail); } return levelOfDetails; } public static int getLevel(double scale) { int level = scales.length - 1; double minStep = Double.MAX_VALUE; for (int i = 0; i < scales.length; i++) { double sca = scales[i]; if (Math.abs(scale - sca) < minStep) { minStep = Math.abs(scale - sca); level = i; } } return level; } public static double getResolution(int level) { if (level < resolutions.length) return resolutions[level]; else return 1; } //Is there a network? public static boolean isNetworkConnected() { ConnectivityManager mConnectivityManager = (ConnectivityManager) NSCApplication.mContext .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); if (mNetworkInfo != null) { return mNetworkInfo.isAvailable(); } return false; } }
Load to map
final BaseMapLayer webTiledLayer = BaseMapLayer.CreateBaseMapLayer(OtherMapLayer.MAPLAYER_TIANDI_VECTOR); webTiledLayer.loadAsync(); webTiledLayer.addDoneLoadingListener(new Runnable() { @Override public void run() { if (webTiledLayer.getLoadStatus() == LoadStatus.LOADED) { ArcGISMap map = new ArcGISMap(new Basemap(webTiledLayer)); mMapView.setMap(map); mMapView.getGraphicsOverlays().add(overlay); } } });
The getTile in BaseMapLayer has implemented the downloading, loading and management of cache tiles.