本文主要介绍自定义扩展图层加载天地图并缓存(支持 ArcGIS for Android 100 版本)
概述
国家地理信息公共服务平台 “ 天地图 ”(以下简称 “天地图” )是国家测绘地理信息局主导建设的网络化地理信息共享与服务门户,集成了来自国家、省、市(县)各级测绘地理信息部门,以及相关政府部门、企事业单位 、社会团体、公众的地理信息公共服务资源,向各类用户提供权威、标准、统一的在线地理信息综合服务。
“天地图”属于基础性、公益性服务平台,针对不同用途设计了多种数据版本和服务模式,用户可根据自身需求进行使用。
基本情况如下:
1、基于 OGC 的 WMTS 1.0.0 版本;
2、提供矢量地图、影像地图和地形图;
3、提供两种坐标系:国家2000大地坐标系和 Web Mercator 投影坐标系;
4、地图和标注数据分开,矢量地图和影像地图提供中英文标注,地形图仅提供中文标注。
天地图的坐标比较标准,是国家 2000 坐标,没有偏移,但是切片分辨率并不是标准的 WMTS 服务。
针对 ArcGIS for Android SDK 在 100 版本及以后发生了较大的变化,本文分为两部分介绍。
本文源码:https://github.com/wshunli/arcgis-android-tianditu
ArcGIS for Android 10.2.9 及以前
1、搭建 ArcGIS for Android 环境
这部分内容在前面有详细的介绍 https://www.wshunli.com/posts/29ec97b7.html
2、添加 arcgis-android-tianditu 依赖
arcgis-android-tianditu 已经发布至 jcenter ,确定项目已配置 jcenter 仓库即可。
repositories { jcenter() } dependencies { implementation 'com.wshunli.map:arcgis-android-tianditu:1.1.0' }
|
3、快速入门
MapView mMapView = (MapView) findViewById(R.id.map); TianDiTuLayer vec_c = new TianDiTuLayer(TianDiTuLayerTypes.TIANDITU_VECTOR_MERCATOR); mMapView.addLayer(vec_c);
|
这里支持对切片的缓存,指定缓存位置即可。
MapView mMapView = (MapView) findViewById(R.id.map); String cachePath = Environment.getExternalStorageDirectory().getAbsoluteFile() + "/TianDiTuCache"; TianDiTuLayer vec_c = new TianDiTuLayer(TianDiTuLayerTypes.TIANDITU_VECTOR_MERCATOR, cachePath); mMapView.addLayer(vec_c);
|
4、支持的图层类型
本文支持现有天地图所有图层,指定 TianDiTuLayerTypes 即可。
1、矢量、影像和地形切片图
| 图层类型 |
国家 2000 坐标 |
墨卡托投影 |
| 矢量图 |
TIANDITU_VECTOR_2000 |
TIANDITU_VECTOR_MERCATOR |
| 影像图 |
TIANDITU_IMAGE_2000 |
TIANDITU_IMAGE_MERCATOR |
| 地形图 |
TIANDITU_TERRAIN_2000 |
TIANDITU_TERRAIN_MERCATOR |
2.1、墨卡托投影及相关标注
| 图层类型 |
墨卡托投影 |
| 矢量图 |
TIANDITU_VECTOR_MERCATOR |
| 矢量中文标注 |
TIANDITU_VECTOR_ANNOTATION_CHINESE_MERCATOR |
| 矢量英文标注 |
TIANDITU_VECTOR_ANNOTATION_ENGLISH_MERCATOR |
| 影像图 |
TIANDITU_IMAGE_MERCATOR |
| 影像中文标注 |
TIANDITU_IMAGE_ANNOTATION_CHINESE_MERCATOR |
| 影像英文标注 |
TIANDITU_IMAGE_ANNOTATION_ENGLISH_MERCATOR |
| 地形图 |
TIANDITU_TERRAIN_MERCATOR |
| 地形中文标注 |
TIANDITU_TERRAIN_ANNOTATION_CHINESE_MERCATOR |
2.2、国家 2000 坐标及相关标注
| 图层类型 |
国家 2000 坐标 |
| 矢量图 |
TIANDITU_VECTOR_2000 |
| 矢量中文标注 |
TIANDITU_VECTOR_ANNOTATION_CHINESE_2000 |
| 矢量英文标注 |
TIANDITU_VECTOR_ANNOTATION_ENGLISH_2000 |
| 影像图 |
TIANDITU_IMAGE_2000 |
| 影像中文标注 |
TIANDITU_IMAGE_ANNOTATION_CHINESE_2000 |
| 影像英文标注 |
TIANDITU_IMAGE_ANNOTATION_ENGLISH_2000 |
| 地形图 |
TIANDITU_TERRAIN_2000 |
| 地形中文标注 |
TIANDITU_TERRAIN_ANNOTATION_CHINESE_2000 |
完整使用示例
package com.wshunli.map.tianditu.sample;
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import com.esri.android.map.MapView; import com.esri.android.map.event.OnZoomListener; import com.wshunli.map.tianditu.TianDiTuLayer; import com.wshunli.map.tianditu.TianDiTuLayerTypes;
public class MainActivity extends AppCompatActivity { public static String TDT_PATH = android.os.Environment.getExternalStorageDirectory() + "/TDTCacheDemo"; MapView mMapView; public TianDiTuLayer vec_c; public TianDiTuLayer cva_c; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
mMapView = (MapView) findViewById(R.id.map); vec_c = new TianDiTuLayer(TianDiTuLayerTypes.TIANDITU_VECTOR_2000, TDT_PATH); mMapView.addLayer(vec_c); cva_c = new TianDiTuLayer(TianDiTuLayerTypes.TIANDITU_VECTOR_ANNOTATION_CHINESE_2000, TDT_PATH); mMapView.addLayer(cva_c);
mMapView.setOnZoomListener(new OnZoomListener() { @Override public void preAction(float v, float v1, double v2) { } @Override public void postAction(float v, float v1, double v2) { cva_c.clearTiles(); } }); } }
|
5、源码分析,核心代码如下
protected byte[] getTile(int level, int col, int row) throws Exception { if (level > layerInfo.getMaxZoomLevel() || level < layerInfo.getMinZoomLevel()) return new byte[0]; byte[] bytes = null; if (cachePath != null) bytes = getOfflineCacheFile(cachePath, level, col, row); if (bytes == null) { String url = layerInfo.getUrl() + "?service=wmts&request=gettile&version=1.0.0&layer=" + layerInfo.getLayerName() + "&format=tiles&tilematrixset=" + layerInfo.getTileMatrixSet() + "&tilecol=" + col + "&tilerow=" + row + "&tilematrix=" + (level + 1); Map<String, String> map = null; bytes = com.esri.core.internal.io.handler.a.a(url, map); if (cachePath != null) AddOfflineCacheFile(cachePath, level, col, row, bytes); } return bytes; }
|
更多内容参考:README_zh_CN.10.X
ArcGIS for Android 100.0.0 及以后
1、搭建 ArcGIS for Android 环境
这部分内容在前面有详细的介绍 https://www.wshunli.com/posts/29ec97b7.html
2、添加 arcgis-android-tianditu 依赖
注意版本不同,arcgis-android-tianditu 2.0.0 以后对应 ArcGIS for Android 100 版本及以后。
dependencies { implementation 'com.wshunli.map:arcgis-android-tianditu:2.0.0' }
|
3、简单示例
MapView mMapView = findViewById(R.id.mapView); ArcGISMap map = new ArcGISMap(); TianDiTuLayer vec_c = new TianDiTuLayerBuilder() .setLayerType(TianDiTuLayerTypes.TIANDITU_VECTOR_MERCATOR) .build(); map.getBasemap().getBaseLayers().add(vec_c); mMapView.setMap(map);
|
缓存切片,指定缓存位置即可缓存切片。
MapView mMapView = findViewById(R.id.mapView); ArcGISMap map = new ArcGISMap(); String cachePath = Environment.getExternalStorageDirectory().getAbsoluteFile() + "/TianDiTu100Cache"; TianDiTuLayer vec_c = new TianDiTuLayerBuilder() .setLayerType(TianDiTuLayerTypes.TIANDITU_VECTOR_MERCATOR) .setCachePath(cachePath) .build(); map.getBasemap().getBaseLayers().add(vec_c); mMapView.setMap(map);
|
注意使用接口及调用方式不太一样。
4、支持的图层类型没有变参考前面内容。
5、源码分析
@Override protected byte[] getTile(TileKey tileKey) {
int level = tileKey.getLevel(); int col = tileKey.getColumn(); int row = tileKey.getRow(); if (level > layerInfo.getMaxZoomLevel() || level < layerInfo.getMinZoomLevel()) return new byte[0]; byte[] bytes = null; if (cachePath != null) bytes = getOfflineCacheFile(cachePath, level, col, row); if (bytes == null) { String url = layerInfo.getUrl() + "?service=wmts&request=gettile&version=1.0.0&layer=" + layerInfo.getLayerName() + "&format=tiles&tilematrixset=" + layerInfo.getTileMatrixSet() + "&tilecol=" + col + "&tilerow=" + row + "&tilematrix=" + (level);
try { HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection(); httpConnection.setRequestMethod("GET"); httpConnection.setConnectTimeout(5000); InputStream in = httpConnection.getInputStream(); bytes = getBytes(in); httpConnection.disconnect(); } catch (IOException e) { e.printStackTrace(); } if (cachePath != null) { AddOfflineCacheFile(cachePath, level, col, row, bytes); }
} return bytes; }
|
更多内容参考:README_zh_CN
最后欢迎 star 或者提交 PR 到本仓库。
https://github.com/wshunli/arcgis-android-tianditu
参考资料
1、ArcGIS读取天地图2.0 - ArcGIS产品与技术专栏 - 博客频道 - CSDN.NET
http://blog.csdn.net/arcgis_all/article/details/8848120
2、arcgis api for android 叠加天地图 - 阿华博台 - 博客频道 - CSDN.NET
http://blog.csdn.net/yu624774720hua/article/details/8755398
3、入门Android开发–ArcGis读取天地图,并实现一些简单功能。 - 从入门到忘记 - 博客频道 - CSDN.NET
http://blog.csdn.net/u013867301/article/details/51036200
4、arcgis for android 本地缓存 | 大光的博客
http://daguang.me/2013/08/01/arcgis-for-android-本地缓存/
5、Android开发,arcgis自定义layer-历史影像和地图缓存的实现 - 博客频道 - CSDN.NET
http://blog.csdn.net/Stanny_Bing/article/details/53736659