• Android使用osmdroid加载在线地图,离线地图以及各种填坑姿势


    最近开发需要加载地图,包括离线瓦片和在线地图,因为百度和高德要掏钱并且不支持加载自己的瓦片,想着有没有开源的替代呢?发现了osmdroid这个开源库可以加载地图,但是关于开发资料中文少的可怜,有关博客都是互相抄,找不到有用的信息,于是我狠下心看了遍源码,然后开始了填坑之旅。

    首先加入依赖如下:

    implementation 'org.osmdroid:osmdroid-android:6.1.11'
    
    • 1

    然后,在xml里加入组件:

    <org.osmdroid.views.MapView
            android:id="@+id/map"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    • 1
    • 2
    • 3
    • 4

    最后,在activity中开始加载map

     		mapView?.maxZoomLevel = 23.0
            mapView?.minZoomLevel = 0.0
            mapView?.controller?.setZoom(12.0)
            //让瓦片适应不同像素密度:默认地图显示的字体小,图片像素高,可设置以下代码,使地图适应不同像素密度,更美观
            mapView?.isTilesScaledToDpi = true
            //设置缩放按钮可见
            val zoomController = mapView?.getZoomController()
            zoomController?.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
            mapView?.setMultiTouchControls(true) // 触控放大缩小
            mapView?.overlayManager?.tilesOverlay?.isEnabled = true
            mapView?.isSelected = true
            var dm = resources.displayMetrics
            //指南针
            var mCompassOverlay = CompassOverlay(
                this, InternalCompassOrientationProvider(this),
                mapView
            )
            mCompassOverlay.enableCompass()
            mapView?.getOverlays()?.add(mCompassOverlay)
            //比例尺配置
            var mScaleBarOverlay = ScaleBarOverlay(mapView)
            mScaleBarOverlay.setScaleBarOffset(dm.widthPixels / 2, 10)
            mapView?.getOverlays()?.add(mScaleBarOverlay)
            mapView?.overlays?.add(mScaleBarOverlay)
            //定位
            var mLocationOverlay = MyLocationNewOverlay(GpsMyLocationProvider(this), mapView)
            mapView?.overlays?.add(mLocationOverlay)
            mLocationOverlay.enableMyLocation()
            //地图移动到该点
            var startPoint = GeoPoint(GeoPoint(34.360284, 108.859602))
            mapView?.controller?.setCenter(startPoint)
    
            mapView?.setUseDataConnection(true)
            mapView?.setTileSource(tianDiTuCiaTileSource)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    其中,tianDiTuCiaTileSource是地图的在线资源,我用的是天地图,也可以换成别的,只要url配置正确就可以。如下:

     static  String  wz = "tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&tk=自己申请的token";
     	//影像地图 _W是墨卡托投影  _c是国家2000的坐标系
        public static OnlineTileSourceBase tianDiTuImgTileSource = new XYTileSource("Tian Di Tu Img", 1, 18, 256, "",
                new String[]{"https://t0." + wz,
                        "https://t1." + wz,
                        "https://t2." + wz,
                        "https://t3." + wz,
                        "https://t4." + wz,
                        "https://t5." + wz,
                        "https://t6." + wz,
                        "https://t7." + wz
                }) {
            @Override
            public String getTileURLString(final long pMapTileIndex) {
                Log.d("url", getBaseUrl() + "&TILEROW=" + MapTileIndex.getY(pMapTileIndex) + "&TILECOL=" + MapTileIndex.getX(pMapTileIndex)
                        + "&TILEMATRIX=" + MapTileIndex.getZoom(pMapTileIndex));
                return getBaseUrl() + "&TILEROW=" + MapTileIndex.getY(pMapTileIndex) + "&TILECOL=" + MapTileIndex.getX(pMapTileIndex)
                        + "&TILEMATRIX=" + MapTileIndex.getZoom(pMapTileIndex);
            }
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    把上面地址中的token换成自己申请的,就可以了

    至此,在线地图就加载出来了。

    接下来,我们来加载离线瓦片。

    离线瓦片的格式有很多种,osm也支持好多,这里我用的是.zip瓦片文件,解压开里面是一张一张的图片,然后osm地图会根据你缩放的大小和坐标,找到对应的图片进行显示。废话不多说,代码是最好的老师,代码下:

    fun mapViewOtherData(mapView: MapView, str: String) {
    		//str是离线瓦片.zip的路径,Android10以上,如果路径没有权限,下面会报错。所以我的做法是,先把zip复制到自己的包名下的私有目录,然后随便进行操作
            val strFilepath = str
            val exitFile = File(strFilepath)
    
            if (!exitFile.exists()) { //文件不存在,用默认网络的
    
            } else { //文件存在
                try {
                	//source 是zip解压后文件夹的名称,我zip文件名字和里面文件夹一样,所以代码这么写
                    val source = exitFile.name.substring(0, exitFile.name.lastIndexOf("."))
                    val archives = arrayOfNulls<IArchiveFile>(1)
                    archives[0] = ArchiveFileFactory.getArchiveFile(exitFile)
                    val customTiles = CustomTileSource(
                        source,
                        12,
                        23,
                        256,
                        ".png",
                    )
                    val providers = arrayOfNulls<MapTileModuleProviderBase>(1)
                    providers[0] = MapTileFileArchiveProvider(
                        SimpleRegisterReceiver(this),
                        customTiles,
                        archives
                    )
    
                    val tileProvider = MapTileProviderArray(
                        customTiles,
                        SimpleRegisterReceiver(this), providers
                    )
                    var tilesOverlay = TilesOverlay(tileProvider, this)
                    tilesOverlay.setLoadingBackgroundColor(Color.TRANSPARENT)
                    mapView.getOverlayManager()?.add(tilesOverlay)
                    return
                } catch (ex: Exception) {
                    ex.printStackTrace()
                }
                Toast.makeText(
                    this,
                    " did not have any files I can open!",
                    Toast.LENGTH_LONG
                ).show()
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    上面代码CustomTileSource是自定义的一个加载类,如下:

    public class CustomTileSource extends BitmapTileSourceBase {
        public CustomTileSource(String aName, int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels, String aImageFilenameEnding) {
            super(aName, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    至此,osm离线瓦片也加载出来了。

    osmdroid加载地图,确实很强大,官方的demo也有,但是demo里面没有加载zip的例子(吐槽一下,添加marker,画点线面的例子都有,就是没有zip),所以费了好大的功夫才把zip给加载出来。所以,记录一下。

    到现在,在线地图,离线地图瓦片都加载出来了,osmdroid的地图功能都实现了。

  • 相关阅读:
    【MyBatis笔记03】MyBatis实现CRUD增删改查功能
    MyBatis使⽤PageHelper(MySQL)
    Webpack5 Asset Module 使用小结
    多神经网络模型联合训练,全连接神经网络模型
    算法试题——每日一练
    不要高估迷信自己的毅力:交钱后坚持培训的比例不到1%
    机械臂速成小指南(十四):多项式插值轨迹规划
    cocos 2.4*版本的基础使用笔记分享(一)
    C# 如何设计一个好用的日志库?【架构篇】
    `算法题解` `AcWing` 1085. 不要62
  • 原文地址:https://blog.csdn.net/gemgaozhen/article/details/132498311