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文件
    添加 <string name="mapbox_access_token">公共令牌</string>
    
  • 在清单文件中配置权限:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
  • 初始化Mapbox,建议在Application中:

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

MapBox的使用

  • 布局文件中添加MapBox

        <com.mapbox.mapboxsdk.maps.MapView
            android:id="@+id/Activity_Main_Map"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            mapbox:mapbox_cameraZoom="12"/>
        
        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<Feature> = 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跑一下,就能知道可以做些什么。
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354