OpenStreetMap开发文档
in 地图 with 0 comment

OpenStreetMap开发文档

in 地图 with 0 comment

前言

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

0评论