arcgis for android最后一版是10.2.9。据说之后不再更新维护该版本,直接跳跃到100系列,而100系列与之前的版本还是有较大差别。但也新增了更多功能,性能也优化很多。具体的差别此处不再赘述,多用用100版本就能感觉出来。
本节主要是讲讲新版本中互联网地图的引用,主要指常用的天地图、谷歌地图。其实加载百度、高德地图是一样的原理,但由于他们的地图坐标数据都是火星坐标,针对专业GIS开发时,就用不上了。
1、重载ImageTiledLayer。主要实现两个方法,
一个是构造函数:protected ImageTiledLayer(TileInfo tileInfo, Envelope fullExtent)
一个是瓦片下载函数:protected abstract byte[] getTile(TileKey var1)
2、根据我们之前的经验,构造函数主要是TileInfo参数构建,把之前的参数搬过来就可以了。
直接上代码
BaseMapLayer 类
public class BaseMapLayer extends ImageTiledLayer { //天地、谷歌矢量图和影像图常量 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; //影像地图标注常量 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://天地图矢量地图 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://天地图影像地图 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 矢量地图 subDomains = new String[]{"mt0", "mt1", "mt2", "mt3"}; urlPart = ".google.cn/vt/hl=zh-CN"; flag = "z"; break; case MAPLAYER_GOOGLE_IMAGE://Google 影像地图 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://天地图影像地图标注 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://天地图矢量地图标注 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 { //对资源链接 URL url = new URL(iPath); InputStream inputStream = url.openStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // 开始读取数据 byte[] buffer = new byte[1024]; int len = 0;// 每次读取到的数据的长度 while ((len = inputStream.read(buffer)) != -1) {// len值为-1时,表示没有数据了 // append方法往sb对象里面添加数据 outputStream.write(buffer, 0, len); } inputStream.close(); // 输出字符串 return outputStream.toByteArray(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return new byte[0]; } }
MapTilesTool 类
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; } //是否有网络 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; } }
加载到地图
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); } } });
BaseMapLayer 中的 getTile中已经实现了缓存瓦片的下载、加载和管理。