最近公司有这个需求,需要能切换不同的地图,并且数据需要互通,如果引入每一个地图的SDK(例如百度地图SDK、高德地图SDK、谷歌地图等)的话apk包就太大了,而且操作数据及操作地图就会变得特别麻烦,所以找到了完全免费及开源的osmdroid。下面先看一下显示效果:
首先附上osmdroid的Github地址:https://github.com/osmdroid/osmdroid
第一步在app.gradle中添加上依赖:
implementation 'org.osmdroid:osmdroid-android:6.1.0'
第二步在布局中加载MapView:
第三步在活动中对MapView进行初始化,再进行一些属性的配置,比如指南针的显示、比例尺的显示、小地图显示等等:
mMapView.setTileSource(Objects.requireNonNull(GoogleTileSource.getOnlineTileSourceBaseByName(mapSource)));
IMapController mapController = mMapView.getController();
mapController.setZoom(18.0);
GeoPoint startPoint = new GeoPoint(39.0853958, 117.0994426);
mapController.setCenter(startPoint);
this.mLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(this), mMapView);
this.mLocationOverlay.enableMyLocation();
//mMapView.getOverlays().add(this.mLocationOverlay);
this.mCompassOverlay = new CompassOverlay(this, new InternalCompassOrientationProvider(this), mMapView);
this.mCompassOverlay.enableCompass();
mMapView.getOverlays().add(this.mCompassOverlay);
//缩放按钮
mMapView.setBuiltInZoomControls(false);
mMapView.setMultiTouchControls(true);
//最大缩放比例
mMapView.setMaxZoomLevel(20.0);
上面代码中的mMapView为MapView,GooleTileSource为自定义的一个类,继承自TileSourceFactory,里面构造了谷歌地图以及高德地图的地图源,所以,mapView的setTileSource方法就是用来切换地图源的。下面放上GooleTileSource类的代码,可直接进行使用:
/**
* 谷歌、高德等瓦片地图
*
* @author jiang zhu on 2019/10/18
*/
public class GoogleTileSource extends TileSourceFactory {
//谷歌卫星混合
public static final OnlineTileSourceBase GoogleHybrid = new XYTileSource("Google-Hybrid",
0, 19, 512, ".png", new String[]{
"http://mt0.google.cn",
"http://mt1.google.cn",
"http://mt2.google.cn",
"http://mt3.google.cn",
}) {
@Override
public String getTileURLString(long pMapTileIndex) {
Log.d("url", getBaseUrl() + "/vt/lyrs=y&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex));
return getBaseUrl() + "/vt/lyrs=y&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);
}
};
//谷歌卫星
public static final OnlineTileSourceBase GoogleSat = new XYTileSource("Google-Sat",
0, 19, 512, ".png", new String[]{
"http://mt0.google.cn",
"http://mt1.google.cn",
"http://mt2.google.cn",
"http://mt3.google.cn",
}) {
@Override
public String getTileURLString(long pMapTileIndex) {
return getBaseUrl() + "/vt/lyrs=s&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);
}
};
//谷歌地图
public static final OnlineTileSourceBase GoogleRoads = new XYTileSource("Google-Roads",
0, 18, 512, ".png", new String[]{
"http://mt0.google.cn",
"http://mt1.google.cn",
"http://mt2.google.cn",
"http://mt3.google.cn",
}) {
@Override
public String getTileURLString(long pMapTileIndex) {
return getBaseUrl() + "/vt/lyrs=m&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);
}
};
//谷歌地形
public static final OnlineTileSourceBase GoogleTerrain = new XYTileSource("Google-Terrain",
0, 16, 512, ".png", new String[]{
"http://mt0.google.cn",
"http://mt1.google.cn",
"http://mt2.google.cn",
"http://mt3.google.cn",
}) {
@Override
public String getTileURLString(long pMapTileIndex) {
return getBaseUrl() + "/vt/lyrs=t&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);
}
};
//谷歌地形带标注
public static final OnlineTileSourceBase GoogleTerrainHybrid = new XYTileSource("Google-Terrain-Hybrid",
0, 16, 512, ".png", new String[]{
"http://mt0.google.cn",
"http://mt1.google.cn",
"http://mt2.google.cn",
"http://mt3.google.cn",
}) {
@Override
public String getTileURLString(long pMapTileIndex) {
return getBaseUrl() + "/vt/lyrs=p&scale=2&hl=zh-CN&gl=CN&src=app&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex);
}
};
//高德地图
public static final OnlineTileSourceBase AutoNaviVector = new XYTileSource("AutoNavi-Vector",
0, 20, 256, ".png", new String[]{
"https://wprd01.is.autonavi.com/appmaptile?",
"https://wprd02.is.autonavi.com/appmaptile?",
"https://wprd03.is.autonavi.com/appmaptile?",
"https://wprd04.is.autonavi.com/appmaptile?",
}) {
@Override
public String getTileURLString(long pMapTileIndex) {
return getBaseUrl() + "x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z="
+ MapTileIndex.getZoom(pMapTileIndex) + "&lang=zh_cn&size=1&scl=1&style=7<ype=7";
}
};
}
第四步来实现下离线地图的加载,写一个方法来判断当前是否有网络,若果有直接加载在线地图,否则加载离线地图:
/**
* 设置地图源
*/
private void setMapSources() {
if (NetworkUtils.isConnected()) {
mMapView.setTileSource(Objects.requireNonNull(GoogleTileSource.getOnlineTileSourceBaseByName(mapSource)));
}
} else {
ToastUtils.showShort("当前无网络,请选择离线地图包");
if (mMapView.getOverlays().size() <= 0) {
mapViewOffline();
}
}
}
其中的mapViewOffline方法为加载离线地图的方法,代码如下:
/**
* 加载离线地图
*/
public void mapViewOffline() {
String strFilepath = Environment.getExternalStorageDirectory().getPath() + "/osmdroid/jiang.sqlite";
File exitFile = new File(strFilepath);
String fileName = exitFile.getName();
if (!exitFile.exists()) {
mMapView.setTileSource(TileSourceFactory.MAPNIK);
} else {
fileName = fileName.substring(fileName.lastIndexOf(".") + 1);
if (ArchiveFileFactory.isFileExtensionRegistered(fileName)) {
try {
OfflineTileProvider tileProvider = new OfflineTileProvider(new SimpleRegisterReceiver(this), new File[]{exitFile});
mMapView.setTileProvider(tileProvider);
String source = "";
IArchiveFile[] archives = tileProvider.getArchives();
if (archives.length > 0) {
Set tileSources = archives[0].getTileSources();
if (!tileSources.isEmpty()) {
source = tileSources.iterator().next();
mMapView.setTileSource(FileBasedTileSource.getSource(source));
} else {
mMapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
}
} else
mMapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
Toast.makeText(this, "Using " + exitFile.getAbsolutePath() + " " + source, Toast.LENGTH_LONG).show();
mMapView.invalidate();
return;
} catch (Exception ex) {
ex.printStackTrace();
}
Toast.makeText(this, " did not have any files I can open! Try using MOBAC", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, " dir not found!", Toast.LENGTH_LONG).show();
}
}
}
其中的jiang.sqllite为离线地图资源包,大家可以在官方提供的网站自行下载:https://github.com/osmdroid/osmdroid/blob/master/OSMMapTilePackager/readme.md
先写这么多吧,里面的marker和PolyLine的添加和加载官方文档中都有详细描述:http://osmdroid.github.io/osmdroid/
如果有问题可进行留言,看到后会尽快进行答复。