前言
OpenStreetMap社区是一个由地图制作爱好者组成的社区,这些爱好者提供并维护世界各地关于道路、小道、咖啡馆、铁路车站等各种各样的数据。
OpenStreetMap开源项目可以让程序开发更加灵活,图源更加丰富,例如可以使用谷歌地图,以解决国内无法使用谷歌服务的尴尬。
国内户外导航软件,例如:行者、户外帮和小狼信标都使用了OpenStreetMap。
Android版OpenStreetMap的github地址:osmdroid
5.2地图缓存的是瓦片,5.4之后地图缓存到数据库
一、环境配置
1、Gradle中添加依赖
compile 'org.osmdroid:osmdroid-android:5.2@aar'
2、权限配置
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
提示:编译版本为23或以上版本,要注意动态获取读写存储空间权限,否则地图可能不显示
二、基础MapView使用
1、使用内置地图源
(1)、在布局文件中添加MapView控件,在代码中找到控件并设置图源
<org.osmdroid.views.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
MapView mMapView= (MapView) findViewById(R.id.mapView);
mMapView.setTileSource(TileSourceFactory.CYCLEMAP);//(OCM等高)若不设置,则默认使用的是MAPNIK(OSM街道)
(2)、直接在代码中new MapView,然后设置图源,并将MapView添加到父布局中
MapView mMapView=new MapView(this);
mMapView.setTileSource(TileSourceFactory.MAPNIK);
2、设置其他地图源
(1)、谷歌图源
a、新建一个谷歌图源类,继承OnlineTileSourceBase
public class GoogleMapsTileSource extends OnlineTileSourceBase {
/**
* @param aName a human-friendly name for this tile source 自定图源义名字,会在手机外部存储中新建以该名字命名的文件夹,瓦片存储在其中
* @param aZoomMinLevel the minimum zoom level this tile source can provide 最小缩放级别
* @param aZoomMaxLevel the maximum zoom level this tile source can provide 最大缩放级别
* @param aTileSizePixels the tile size in pixels this tile source provides 瓦片质量 (256)
* @param aImageFilenameEnding the file name extension used when constructing the filename 瓦片格式(jpg[有损压缩率高、不透明]、png[无损、透明])
* @param aBaseUrl the base url(s) of the tile server used when constructing the url to download the tiles 下载瓦片的链接(前缀)
*/
public GoogleMapsTileSource(String aName, int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels, String aImageFilenameEnding, String[] aBaseUrl) {
super(aName, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding, aBaseUrl);
}
@Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + "&x=" + aTile.getX() + "&y=" + aTile.getY() + "&z=" + aTile.getZoomLevel();
}
}
b、new一个谷歌图源对象,并设置MapView图源
String str1 = "http://mt0.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&scale=2";
String str2 = "http://mt1.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&scale=2";
String str3 = "http://mt2.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&scale=2";
String str4 = "http://mt3.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&scale=2";
GoogleMapsTileSource googleMapsTileSource = new GoogleMapsTileSource("GoogleNormal", 2, 19, 256, ".png", new String[]{str1, str2, str3, str4});
mMapView.setTileSource(googleMapsTileSource);
(2)、必应等图源,使用方法类似于谷歌图源
参考文档:http://blog.csdn.net/youngkingyj/article/details/23365849
3、让瓦片适应不同像素密度
默认地图显示的字体小,图片像素高,可设置以下代码,使地图适应不同像素密度,更美观
mMapView.setTilesScaledToDpi(true);
4、添加指南针
CompassOverlay mCompassOverlay = new CompassOverlay(MainActivity.this, new InternalCompassOrientationProvider(MainActivity.this), mMapView);
mMapView.getOverlays().add(mCompassOverlay);
mCompassOverlay.enableCompass();
按此方法添加指南针之后,部分手机仍不显示指南针,原因未知
5、添加比例尺
ScaleBarOverlay mScaleBarOverlay = new ScaleBarOverlay(mMapView);
mMapView.getOverlays().add(mScaleBarOverlay);
添加上面代码后,比例尺显示在左上角,而且不美观,可以继续添加下面代码,使比例尺显示在左下角
mScaleBarOverlay.setAlignBottom(true);
mScaleBarOverlay.setLineWidth(1 * (getResources().getDisplayMetrics()).density);
mScaleBarOverlay.setMaxLength(0.85f);
6、设置地图中心
GeoPoint geopoint = new GeoPoint(39.986250, 116.400025);
MapController mMapController= (MapController) mMapView.getController();//获取MapView控制器
mMapController.setCenter(geopoint);//设置地图中心
7、其他设置
(1)、设置缩放界别
mMapController.setZoom(15);//设置缩放级别
(2)、设置缩放按钮可见
mMapView.setBuiltInZoomControls(true);//设置缩放按钮可见
(3)、设置多指触控可用
mMapView.setMultiTouchControls(true);//设置多指触控可用
(4)、关闭硬件加速
mMapView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);//关闭硬件加速(绘制轨迹时需要)
(5)、地图可旋转
RotationGestureOverlay mRotationGestureOverlay = new RotationGestureOverlay(this, mMapView);
mRotationGestureOverlay.setEnabled(true);
mMapView.getOverlays().add(mRotationGestureOverlay);
三、进阶使用
1、自定义瓦片缓存位置
默认会在外部存储中新建名为somdroid的文件夹,瓦片就存储在其中。
自定义缓存位置就是在外部存储中创建一个文件夹,然后设置为瓦片的缓存位置,放在MapView初始化之前
例如:
File dir = new File(Environment.getExternalStorageDirectory(), "AAA");//新建文件夹
if (dir.exists()) {
File nomedia = new File(dir.getAbsoluteFile() + "/.nomedia");
if (!nomedia.exists()) {
try {
nomedia.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
dir.mkdirs();
File file = dir.getAbsoluteFile();
try {
new File(file + "/.nomedia").createNewFile();
} catch (Exception ex) {
android.util.Log.e(IMapView.LOGTAG, "unable to create a nomedia file. downloaded tiles may be visible to the gallery.", ex);
}
}
OpenStreetMapTileProviderConstants.setCachePath(dir + "");//设置MapView的缓存路径
2、添加Marker
Marker marker = new Marker(mMapView);
marker.setIcon(getResources().getDrawable(R.mipmap.ic_launcher));//设置图标
marker.setPosition(geopoint);//设置位置
marker.setAnchor(0.5f, 0.5f);//设置偏移量
marker.setTitle("我是Titile");//设置标题
marker.setSubDescription("我是SubDescription");//设置说明
mMapView.getOverlays().add(marker);//添加marker到MapView
点击Marker之后会出现气泡,显示title和subDescription
3、连线
PathOverlay pathOverlay = new PathOverlay(Color.BLUE, 10, this);
pathOverlay.addPoint(new GeoPoint(39.986250, 116.400025));
pathOverlay.addPoint(new GeoPoint(39.886250, 116.300025));
mMapView.getOverlays().add(pathOverlay);
连线时务必关闭硬件加速,否则可能显示不出来连的线
4、离线地图下载
CacheManager cacheManager = new CacheManager(mMapView);//获取下载器
BoundingBoxE6 boundingBoxE6 = mMapView.getBoundingBox();//获取当前区域
int tileNum = cacheManager.possibleTilesInArea(boundingBoxE6, 8, 16);//计算当前区域8-16级的瓦片数量
cacheManager.downloadAreaAsync(this, boundingBoxE6, 8, 16, new CacheManager.CacheManagerCallback() {//下载
@Override
public void onTaskComplete() {
//下载完成后的回调
}
});
下载时会有进度框,若点击进度框以外的区域会取消下载,若想修改逻辑可参考CacheManager,自定义一个CacheManage
本文由 掘墓人 创作,采用 CC BY-NC-ND 4.0 DEED
,转载或翻译请注明出处。
最后编辑时间为: 2019年02月3日