最近公司有这个需求,需要能切换不同的地图,并且数据需要互通,如果引入每一个地图的SDK(例如百度地图SDK、高德地图SDK、谷歌地图等)的话apk包就太大了,而且操作数据及操作地图就会变得特别麻烦,所以找到了完全免费及开源的osmdroid。下面先看一下显示效果:
首先附上osmdroid的Github地址:https://github.com/osmdroid/osmdroid
第一步在app.gradle中添加上依赖:
implementation 'org.osmdroid:osmdroid-android:6.1.0'
第二步在布局中加载MapView:
<org.osmdroid.views.MapView android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" />
第三步在活动中对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<String> 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/