Android接入MapBox

作者:Angki
转载请注明


MapBox接入

MapBox的官方文档地址,插件地址。
大概的接入步骤(按照文档来就行):
  • 注册MapBox账号,创建私密访问令牌(为啥要创建呢,后面会说)。

  • 模块级的build.gradle文件添加:

    dependencies {
        implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.3.0'
    }
    
  • 添加私密令牌:

    在gradle.properties文件中添加
    MAPBOX_DOWNLOADS_TOKEN = 私密令牌
    
  • 项目级的build.gradle文件添加:

    maven {
            url 'https://api.mapbox.com/downloads/v2/releases/maven'
            authentication {
                basic(BasicAuthentication)
            }
            credentials {
                username = 'mapbox'
                // Use the secret token you stored in gradle.properties as the password
                password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: ""
            }
    }
    
  • 添加公共令牌:

    打开R.strings.xml文件
    添加 公共令牌
    
  • 在清单文件中配置权限:

    
    
  • 初始化Mapbox,建议在Application中:

    Mapbox.getInstance(this, resources.getString(R.string.mapbox_access_token))
    

MapBox的使用

  • 布局文件中添加MapBox

        
        
        mapbox:mapbox_cameraZoom表示初始化的缩放等级
    
  • 添加生命周期方法

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Activity_Main_Map.onCreate(savedInstanceState)
    }
    
    override fun onStart() {
        super.onStart()
        Activity_Main_Map.onStart()
    }
    
    override fun onResume() {
        super.onResume()
        Activity_Main_Map.onResume()
    }
    
    override fun onPause() {
        super.onPause()
        Activity_Main_Map.onPause()
    }
    
    override fun onStop() {
        super.onStop()
        Activity_Main_Map.onStop()
    }
    
    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        Activity_Main_Map.onSaveInstanceState(outState)
    }
    
    override fun onLowMemory() {
        super.onLowMemory()
        Activity_Main_Map.onLowMemory()
    }
    
    override fun onDestroy() {
        super.onDestroy()
        Activity_Main_Map.onDestroy()
    }
    
  • 设置地图相关设置,在Activity_Main_Map.onCreate(savedInstanceState)后加入:

        Activity_Main_Map.getMapAsync{ mapboxMap ->
            
            mapboxMap.setStyle(Style.OUTDOORS) { style ->
                //个性化设置
                val uiSettings = mapboxMap.uiSettings
                //设置罗盘
                uiSettings.setCompassMargins(0, AutoSizeUtils.mm2px(this, 120f), AutoSizeUtils.mm2px(this, 40f), 0)
                //设置本地化(需要添加本地化插件: implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-localization-v9:0.12.0')
                val localizationPlugin = LocalizationPlugin(Activity_Main_Map, mapboxMap, style)
                //将地图与设备语言匹配
                localizationPlugin.setMapLanguage(MapLocale.SIMPLIFIED_CHINESE)
                // 设置位置
                // 自定义位置的显示
                val customLocationComponentOptions = LocationComponentOptions.builder(this)
                    .trackingGesturesManagement(true)
                    .accuracyColor(ContextCompat.getColor(this, R.color.mapboxGreen))
                    .build()
    
                val locationComponentActivationOptions = LocationComponentActivationOptions
                    .builder(this, style)
                    .locationComponentOptions(customLocationComponentOptions)
                    .useDefaultLocationEngine(true)
                    .build()
    
                this.mLocationComponent = mapboxMap.locationComponent
    
                // Get an instance of the LocationComponent and then adjust its settings
                // 获取LocationComponent的实例,然后调整其设置
                this.mLocationComponent.apply {
                    // Activate the LocationComponent with options
                    // 使用选项激活LocationComponent
                    activateLocationComponent(locationComponentActivationOptions)
    
                    // Enable to make the LocationComponent visible
                    // 启用以使LocationComponent可见
                    isLocationComponentEnabled = true
    
                    // Set the LocationComponent's camera mode
                    // 设置LocationComponent的摄像头模式
                    cameraMode = CameraMode.TRACKING_COMPASS
    
                    // Set the LocationComponent's render mode
                    // 设置LocationComponent的渲染模式
                    renderMode = RenderMode.COMPASS
            }
        }
    

一些其他操作

  • 将地图源替换为天地图的源

    1.先创建天地图账号,获取token
    2.在assets文件中创建一个json文件:
        {
          "version": 8,
          "sources": {
            //矢量底图源
            "URL_VECTOR_2000": {
              "tiles": ["http://t0.tianditu.gov.cn/vec_w/wmts?tk=你的token&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles"],
              "type": "raster",
              "tileSize": 256
            },
            //矢量注记源
            "URL_VECTOR_ANNOTATION_CHINESE_2000": {
              "tiles": ["http://t0.tianditu.gov.cn/cva_w/DataServer?T=cva_w&X={x}&Y={y}&L={z}&tk=你的token"],
              "type": "raster",
              "tileSize": 256
            }
          },
          "layers": [
            {
              "id": "URL_VECTOR_2000",
              "type": "raster",
              "source": "URL_VECTOR_2000",
              "maxzoom": 22
            },
            {
              "id": "URL_VECTOR_ANNOTATION_CHINESE_2000",
              "type": "raster",
              "source": "URL_VECTOR_ANNOTATION_CHINESE_2000",
              "maxzoom": 22
            }
          ]
        }
    3.设置MapBox的Style:
        mMapBoxMap.setStyle(Style.Builder().fromUri("asset://Json文件"))
    
  • 创建一个Marker(标记点)

        //所有的标注,建筑等等都是添加到Layer里面
        mMapBoxMap.getStyle {
            if (it.getLayer("Home_Layer") != null) {
                return@getStyle
            }
            //添加icon
            it.addImage("marker_icon", BitmapFactory.decodeResource(resources, R.drawable.red_marker))
            //设置数据(GeoJson数据)
            it.addSource(getMarkerSource())
            //添加图层
            it.addLayer(SymbolLayer("Home_Layer", "Home")
                //设置属性
                .withProperties(
                    PropertyFactory.iconImage("marker_icon"),
                    //如果为true,则即使其他符号与图标碰撞也可以看到。(机翻,大概就这意思)
                    PropertyFactory.iconIgnorePlacement(true),
                    //如果为true,则即使该图标与其他先前绘制的符号发生冲突也将是可见的。(机翻,大概就这意思)
                    PropertyFactory.iconAllowOverlap(true)
                ))
        }
        
        /**
         * 指定坐标数据
         */
        fun getMarkerSource(): GeoJsonSource {
            val lat = 25.02365687211753
            val lng = 102.73601658370522
            //构建了一个点的数据
            return GeoJsonSource("Home", Feature.fromGeometry(Point.fromLngLat(lng, lat)))
        }
    
  • 设置点击事件(比如给Marker设置一个点击后移动到该Marker位置的事件)

        //设置点击事件
        mMapBoxMap.addOnMapClickListener(this)
        
        override fun onMapClick(point: LatLng): Boolean {
            return handleClickIcon(mMapBoxMap.projection.toScreenLocation(point))
        }
        
        /**
         * 处理点击事件
         * 大概逻辑就是,当点击地图某个点时,检索有没有符合的Feature,有的话处理返回false
         */
        private fun handleClickIcon(screenPoint: PointF): Boolean {
            val features: List = mMapBoxMap.queryRenderedFeatures(
                screenPoint,
                "Home_Layer"
            )
            return if (features.isNotEmpty()) {
                features[0].geometry()?.let {
                    if (it.type() == "Point") {
                        val point = it as Point
                        movePosition(LatLng(point.latitude(), point.longitude()), 18.0, 180.0, 30.0)
                    }
                }
                true
            } else {
                false
            }
        }
    

一些问题

  • 地图加载不出来咋办?

        //使用这个方法,地图加载失败的提示
        Activity_Main_Map.addOnDidFailLoadingMapListener {
            LogUtils.eTag("Angki", it)
        }
    
  • 经纬度不对?

    MapBox默认使用的WGS84坐标系,而国内使用的是GCJ-02。所以在把地图源替换为天地图源后坐标会偏移。可以使用MapBox提供的中国插件,把MapView替换为ChinaMapView。就是这个插件需要特殊的令牌,估计是要购买。
    
  • 总结下?

    MapBox官方文档齐全,但是就不要看国内的那个官方文档,太老了。然后地图的一些显示和效果也都有例子。建议把官方demo跑一下,就能知道可以做些什么。
    

你可能感兴趣的:(Android接入MapBox)