本文主要介绍自定义扩展图层加载天地图并缓存(支持 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()
}
// 添加 arcgis-android-tianditu 依赖
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 版本及以后。
// 添加 arcgis-android-tianditu 依赖
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
最后的修改为什么把缓冲功能给删掉了?
缓存功能?为了适用天地图新的协议,2.0版本重写了关键代码;缓存功能还没有重写,可以参考以前的版本实现