本文档主要介绍关于地图资源、载入瓦片、缓存、离线配置等。
osmdroid支持多种投影。osmdroid是基于Open Street Maps,使用的投影是EPSG:3857。
ZXY - osmdroid基于Open Street Maps,这个地图使用的是“Slippy Map Format”格式(一种常见的地图供应商采用的格式)。大多数的在线瓦片源使用的是Zoom/X/Y URL格式,其中x、y是基于地图划分成象限的整数坐标。这是osmdroid支持的原生格式。
ZYX - 一些像ESRI这样的公司提供的地图瓦片服务使用的是Zoom/Y/X格式,这种格式很容易转换为ZXY格式,从而很容易在osmdroid中使用。目前至少有一种地图源使用这种转换机制(详见USGS地图)。
TMS - 许多在线地图采用的规范,为Tile Map Service的缩写。ZXY和TMS之间很容易直接转换。转换后,x和y是相同的,只是zoom水平相反。
其他类型 - 许多其他在线地图服务采用的是地理经纬度。但很容易将这些地图服务提供的图像转化为OSM风格的ZXY坐标系统。
osmdroid使用瓦片提供者、瓦片源两个组件来显示地图图像。瓦片提供者用于确定如何加载瓦片(在线、离线、assets文件夹等)。瓦片源确定显示哪个瓦片集(Bing、Mapquest、Mapnik等)。默认的瓦片提供者会搜索发现瓦片源如Assets、离线(/sdcard/osmdroid下的zip/sqlite等)、已经下载的瓦片缓存(/sdcard/osmdroid/tiles)。osmdroid中一些瓦片提供者可以改变加载离线瓦片的路径。osmdroid BonusPack中有一些变更体使用一些MapForge等库在运行时利用OSM数据产生离线时可用的瓦片。
osmdroid的一个特点就是可以自定义瓦片供应链。这样,我们可以混合和匹配多种瓦片提供模块来创建特殊的瓦片检索策略。MapTileProviderBasic 瓦片提供者提供了一些列默认的提供者模块:文件缓存、存档提供者以及下载提供者。对于大部分使用者,这些功能足矣,当然你也可以建立自己的自定义瓦片供应链。
final Context context = getActivity();
final Context applicationContext = context.getApplicationContext();
final IRegisterReceiver registerReceiver = new SimpleRegisterReceiver(applicationContext);
// 创建自定义瓦片源
final ITileSource tileSource = new XYTileSource(
"Mapnik", ResourceProxy.string.mapnik, 1, 18, 256, ".png", "http://tile.openstreetmap.org/");
// 创建模块缓存文件提供者
final TileWriter tileWriter = new TileWriter();
final MapTileFilesystemProvider fileSystemProvider = new MapTileFilesystemProvider(
registerReceiver, tileSource);
// 利用本地缓存文件创建缓存文件模块瓦片提供者
GEMFFileArchive gemfFileArchive = GEMFFileArchive.getGEMFFileArchive(mGemfArchiveFilename); // Requires try/catch
MapTileFileArchiveProvider fileArchiveProvider = new MapTileFileArchiveProvider(
registerReceiver, tileSource, new IArchiveFile[] { gemfFileArchive });
// 创建通过网络下载的下载模块提供者
final NetworkAvailabliltyCheck networkAvailabliltyCheck = new NetworkAvailabliltyCheck(context);
final MapTileDownloader downloaderProvider = new MapTileDownloader(
tileSource, tileWriter, networkAvailablityCheck);
// 用自定义瓦片源和自定义瓦片提供者创建自定义瓦片供应数组
final MapTileProviderArray tileProviderArray = new MapTileProviderArray(
tileSource, registerReceiver, new MapTileModuleProviderBase[] {
fileSystemProvider, fileArchiveProvider, downloaderProvider });
//用自定义的瓦片供应数组创建mapview
mMapView = new MapView(context, 256, new DefaultResourceProxyImpl(context), tileProviderArray);
osmdroid绑定了一系列网上可用的瓦片源。其中一部分有使用限制、开发者账户、支付等,需要API keys或者附加信息才可以使用。下面的例子为您展示如何在运行时切换瓦片源。
设置为USGS卫星图(USGS satellite):
mMapView.setTileSource(TileSourceFactory.USGS_SAT);
设置为USGS Topo图(USGS Topo maps):
mMapView.setTileSource(TileSourceFactory.USGS_TOPO);
设置自定义地图服务/瓦片资源。本例中我们使用的是USGS地形图(USGS Topographic maps)。这个瓦源有一些不同,需要给予解释。许多OSM底图源使用类似于Zoom/X/Y.png的URL模式。USGS等一类的瓦片源采用的是Zoom/Y/X,显然需要采用一个不同的URL模式。
osmdroid版本 <= 4.3:
mMapView.setTileSource(new OnlineTileSourceBase("USGS Topo", ResourceProxy.string.custom, 0, 18, 256, "",
new String[] { "http://basemap.nationalmap.gov/ArcGIS/rest/services/USGSTopo/MapServer/tile/" }) {
@Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + aTile.getZoomLevel() + "/" + aTile.getY() + "/" + aTile.getX()
+ mImageFilenameEnding;
}
});
osmdroid版本 >= 5:
mMapView.setTileSource(new OnlineTileSourceBase("USGS Topo", 0, 18, 256, "",
new String[] { "http://basemap.nationalmap.gov/ArcGIS/rest/services/USGSTopo/MapServer/tile/" }) {
@Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + aTile.getZoomLevel() + "/" + aTile.getY() + "/" + aTile.getX()
+ mImageFilenameEnding;
}
});
许多设备支持 android:largeHeap=”true” 设置,这样你的app可以使用比“normal”状态更多的内存。一下代码允许你在内存中怎加瓦片缓存以满足你的需求。通常情况下会添加为充满全屏数目的瓦片数。
//获取覆盖层迭代器
Iterator<Overlay> iterator = mMapView.getOverlays().iterator();
while(iterator.hasNext()){
Overlay next = iterator.next();
//查询类型为瓦片类型的覆盖层
if (next instanceof TilesOverlay){
TilesOverlay x = (TilesOverlay)next;
//将缓存空间扩大为原来的二倍
x.setOvershootTileCache(x.getOvershootTileCache() * 2);
Toast.makeText(getActivity(), "Tiles overlay cache set to " + x.getOvershootTileCache(), Toast.LENGTH_LONG).show();
break;
}
}
主要用于下载的地图瓦片:
//this will set the disk cache size in MB to 1GB , 9GB trim size
OpenStreetMapTileProviderConstants.setCacheSizes(1000L, 900L);
osmdroid预配置了一些地图源。每个源的连接方式各不相同,你可以通过下文下文来查看。
更多的更新信息请查看TileSourceFactory。
需要的java依赖
代码示例:
final ITileSource tileSource = TileSourceFactory.MAPNIK;
mMapView.setTileSource(tileSource);
Note:V5.3 中更新
需要的java依赖
代码示例:
final ITileSource tileSource = new MapQuestTileSource(context);
mMapView.setTileSource(tileSource);
需要在你的Manifest文件中为MapBox添加连接key:
<meta-data android:name="MAPQUEST_MAPID" android:value="YOUR KEY" />
<meta-data android:name="MAPQUEST_ACCESS_TOKEN" android:value="YOUR TOKEN" />
Note:V5.3 中添加
需要的java依赖
示例代码:
final ITileSource tileSource = new HEREWeGoTileSource(context);
mMapView.setTileSource(tileSource);
需要在你的Manifest文件中添加连接key:
<meta-data android:name="HEREWEGO_MAPID" android:value="YOUR KEY" />
<meta-data android:name="HEREWEGO_APPID" android:value="YOUR TOKEN" />
<meta-data android:name="HEREWEGO_APPCODE" android:value="YOUR TOKEN" />
需要的java依赖
示例代码:
CloudmadeUtil.retrieveCloudmadeKey(context);
final ITileSource tileSource = TileSourceFactory.CLOUDMADESTANDARDTILES;
mMapView.setTileSource(tileSource);
需要在你的Manifest文件中添加连接key:
<meta-data android:name="CLOUDMADE_KEY" android:value="YOUR KEY" />
Note:在V5.3中更新
需要的java依赖
示例代码:
final MapBoxTileSource tileSource = new MapBoxTileSource();
//option 1, load your settings from the manifest
tileSource.retrieveAccessToken(context);
tileSource.retrieveMapBoxMapId(context);
//option 2, provide them programmatically
tileSource.setAccessToken(context);
tileSource.setMapBoxMapId(context);
mMapView.setTileSource(tileSource);
需要在你的Manifest文件中添加连接key:
<meta-data android:name="MAPBOX_MAPID" android:value="YOUR KEY" />
<meta-data android:name="MAPBOX_ACCESS_TOKEN" android:value="YOUR TOKEN" />
需要的java依赖
示例代码:
final ITileSource tileSource = TileSourceFactory.USGS_TOPO;
mMapView.setTileSource(tileSource);
需要的java依赖
示例代码:
//load from manifest
org.osmdroid.tileprovider.tilesource.bing.BingMapTileSource.retrieveBingKey(this);
//or load programmatically
org.osmdroid.tileprovider.tilesource.bing.BingMapTileSource.setBingKey("YOUR KEY");
org.osmdroid.tileprovider.tilesource.bing.BingMapTileSource bing=new org.osmdroid.tileprovider.tilesource.bing.BingMapTileSource(null);
mapView.setTileSource(bing);
需要在你的Manifest文件中添加连接key:
<meta-data android:name="BING_KEY" android:value="YOUR KEY" />
bing.setStyle(BingMapTileSource.IMAGERYSET_AERIALWITHLABELS);
bing.setStyle(BingMapTileSource.IMAGERYSET_ROAD);
bing.setStyle(BingMapTileSource.IMAGERYSET_AERIAL);
这里有两种选择,如果你想要对Google Maps使用与osmdroid相同的API,您可以看osmdroid-thirdparty项目和GoogleWrapperSample。如果你想要在你的app中使用Google的瓦片,下面的例子就是。注意,这是一个完全不同于Google的使用规则的,它从来没有被包含在osmdroid中。
需要的java依赖
示例代码:
public static final OnlineTileSourceBase GoogleHybrid = new XYTileSource("Google-Hybrid",
0, 19, 256, ".png", new String[] {
"http://mt0.google.com",
"http://mt1.google.com",
"http://mt2.google.com",
"http://mt3.google.com",
}) {
@Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + "/vt/lyrs=y&x=" + aTile.getX() + "&y=" +aTile.getY() + "&z=" + aTile.getZoomLevel();
}
};
public static final OnlineTileSourceBase GoogleSat = new XYTileSource("Google-Sat",
0, 19, 256, ".png", new String[] {
"http://mt0.google.com",
"http://mt1.google.com",
"http://mt2.google.com",
"http://mt3.google.com",
}) {
@Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + "/vt/lyrs=s&x=" + aTile.getX() + "&y=" +aTile.getY() + "&z=" + aTile.getZoomLevel();
}
};
public static final OnlineTileSourceBase GoogleRoads = new XYTileSource("Google-Roads",
0, 19, 256, ".png", new String[] {
"http://mt0.google.com",
"http://mt1.google.com",
"http://mt2.google.com",
"http://mt3.google.com",
}) {
@Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + "/vt/lyrs=m&x=" + aTile.getX() + "&y=" +aTile.getY() + "&z=" + aTile.getZoomLevel();
}
};
TileSourceFactory.addTileSource(GoogleSat);
TileSourceFactory.addTileSource(GoogleRoads);
TileSourceFactory.addTileSource(GoogleHybrid);
再者,Google Maps不是免费的。不要用osmdroid发布一个带有Google Maps作为瓦片源的应用。Google想要你是用他们自己的带有API keys的地图引擎。
WMS Maps的支持工作正在进行。你可以使用MOBAC连接WMS地图提供者,然后将瓦片转为离线地图资源。
Geopackage是一个定义了文件格式的、开放的标准,所以能够将其转换为osmdroid相适应的sqlite数据。这个任务可以在Android设备上执行,但是以前的经验告诉我们这个执行过程不是很好。
请看:https://github.com/osmdroid/osmdroid/wiki/Offline-Map-Tiles。