【Google Maps--DirectionsSDK Integration】

I checked some information on the Internet and found that there are still many articles about Google Maps SDK integration, but they are not systematic. Here are some systematic arrangements, which are mainly divided into the following sections, and I hope it will be helpful to you who are the initial Google Maps:

  1. 【Google Maps – Integration Preparation】
  2. [Google Maps – MapsSDK Integration]
  3. [Google Maps – DirectionsSDK Integration]
  4. [Google Maps – PlacesSDK Integration]

Let's start the text:

Due to well-known reasons, before integrating the Google Maps SDK, your PC and mobile terminals must first bypass the wall, otherwise you will not be able to operate some subsequent functions.

Google Maps – DirectionsSDK Integration

Before starting the text, let’s make an explanation here: When integrating the Directions function, you need to enable the billing function with your Google Maps developer account. To enable the billing function, you need to bind an international credit card. What! I don’t have an international credit card, only domestic ones will work, the answer is no. Immediately I felt 10,000 upset, integrating the domestic map, it is not so troublesome! But don’t worry everyone, for students who cannot enable the billing function, I will provide you with a solution later, let’s go!
screenshot:
insert image description here

route planning

Let’s not talk too much nonsense, let’s start with the renderings:
insert image description here
First of all, it’s clear that obtaining these route information is not like integrating domestic maps. Google Maps is instead an http get request. The link is as follows:

https://maps.googleapis.com/maps/api/directions/json?origin=Toronto&destination=Montreal&avoid=highways&mode=bicycling&key=your_api_kay

You can read the official documentation carefully for the meaning of passing parameters . Here I also post the key code:

 /**
     * 获取线路信息
     *
     * origin,destination :可是以下几种:位置ID,地址,字符串经纬度
     *
     * mode: driving  (默认)表示使用道路网络的标准行车路线。
     *       walking
     *       bicycling
     *       transit  通过公共交通路线(如果有)请求路线。如果将模式设置为transit,则可以选择指定departure_time或 arrival_time。
     *       如果未指定任何时间,则 departure_time默认为现在(即,出发时间默认为当前时间)。
     *       您还可以选择包含 transit_mode和和/或 transit_routing_preference。
     *
     * arrival_time:指定公交路线的理想到达时间
     * departure_time:指定所需的出发时间。
     *
     * waypoints:指定要在起点和终点之间的路径上包括的直通或中途停留位置的中间位置数组。航点通过将路线引导通过指定位置来更改路线
     * API支持以下行驶模式的航点:驾驶,步行和骑车;不中转。
     *
     * alternatives:如果设置为 true,则指定“方向”服务可以在响应中提供多个路线选择。
     * 请注意,提供路由选择可能会增加服务器的响应时间。这仅适用于没有中间航路点的请求。
     *
     * avoid: 表示计算出的路线应避开所指示的特征。highways 表示计算出的路线应避开高速公路。
     *
     * units:指定显示结果时要使用的单位制。有效值在下面的“单位系统”中指定 。
     *
     */
    private fun getLineInfo() {
    
    

        ViseHttp.GET("directions/json")
            .tag("tag1")
            .addParam("origin", strOrigin)
            .addParam("destination", strDestination)
            //.addParam("mode", "driving")

            .addParam(
                "waypoints",
                "$strWaypoints2"
            ) //航路点,最大允许数量 waypoints为25,加上起点和终点  $strWaypoints1|$strWaypoints2
            //.addParam("alternatives", "true") //如果设置为 true,这仅适用于没有中间航路点的请求。
            //.addParam("avoid", "tolls|highways|ferries")

            .addParam("key", Config.API_KAY)
            .request(object : ACallback<LineModule?>() {
    
    
                override fun onSuccess(mBean: LineModule?) {
    
    
                    //请求成功,AuthorModel为解析服务器返回数据的对象,可以是String,按需定义即可
                    dealWithData(mBean)
                }

                override fun onFail(errCode: Int, errMsg: String) {
    
    
                    //请求失败,errCode为错误码,errMsg为错误描述
                    Log.i(TAG, " errCode=${
      
      errCode} errMsg=$errMsg")
                }
            })
    }

So what kind of data do we get? Here, I post the complete json data here for everyone to use. Students who are inconvenient to enable the billing function can completely copy the json data to their own projects, read the local json data, simulate the data request, and then parse and perform subsequent display processing. For the meaning of each return parameter, also refer to the official documentation .

JSON data:

{
    
    
   "geocoded_waypoints" : [
      {
    
    
         "geocoder_status" : "OK",
         "place_id" : "ChIJy-z5i18alTURP4V2gaGOgZY",
         "types" : [ "establishment", "point_of_interest", "transit_station" ]
      },
      {
    
    
         "geocoder_status" : "OK",
         "place_id" : "ChIJyXsMpF0alTURAOY_NJyY1U8",
         "types" : [ "establishment", "point_of_interest" ]
      }
   ],
   "routes" : [
      {
    
    
         "bounds" : {
    
    
            "northeast" : {
    
    
               "lat" : 36.7065579,
               "lng" : 119.1854509
            },
            "southwest" : {
    
    
               "lat" : 36.7023932,
               "lng" : 119.1759237
            }
         },
         "copyrights" : "Map data ©2020",
         "legs" : [
            {
    
    
               "distance" : {
    
    
                  "text" : "1.5 公里",
                  "value" : 1515
               },
               "duration" : {
    
    
                  "text" : "4分钟",
                  "value" : 241
               },
               "end_address" : "中国山东省潍坊市奎文区胜利东街华都鲁成大厦",
               "end_location" : {
    
    
                  "lat" : 36.7065579,
                  "lng" : 119.1772408
               },
               "start_address" : "中国潍坊市奎文区健康街潍县中路口",
               "start_location" : {
    
    
                  "lat" : 36.7045897,
                  "lng" : 119.1854509
               },
               "steps" : [
                  {
    
    
                     "distance" : {
    
    
                        "text" : "37 米",
                        "value" : 37
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 7
                     },
                     "end_location" : {
    
    
                        "lat" : 36.7047135,
                        "lng" : 119.1851888
                     },
                     "html_instructions" : "向\u003cb\u003e北\u003c/b\u003e行驶",
                     "polyline" : {
    
    
                        "points" : "uz__FalmvUMBSHDVBL"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.7045897,
                        "lng" : 119.1854509
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "52 米",
                        "value" : 52
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 15
                     },
                     "end_location" : {
    
    
                        "lat" : 36.70426399999999,
                        "lng" : 119.1853314
                     },
                     "html_instructions" : "向\u003cb\u003e左\u003c/b\u003e转,前往\u003cb\u003e804省道\u003c/b\u003e/\u003cwbr/\u003e\u003cb\u003e健康东街\u003c/b\u003e",
                     "maneuver" : "turn-left",
                     "polyline" : {
    
    
                        "points" : "m{__FmjmvUxA["
                     },
                     "start_location" : {
    
    
                        "lat" : 36.7047135,
                        "lng" : 119.1851888
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "0.8 公里",
                        "value" : 850
                     },
                     "duration" : {
    
    
                        "text" : "2分钟",
                        "value" : 127
                     },
                     "end_location" : {
    
    
                        "lat" : 36.7023932,
                        "lng" : 119.1760839
                     },
                     "html_instructions" : "向\u003cb\u003e右\u003c/b\u003e转,进入\u003cb\u003e804省道\u003c/b\u003e/\u003cwbr/\u003e\u003cb\u003e健康东街\u003c/b\u003e\u003cdiv style=\"font-size:0.9em\"\u003e继续沿健康东街前行\u003c/div\u003e",
                     "maneuver" : "turn-right",
                     "polyline" : {
    
    
                        "points" : "sx__FikmvULlAVtBHp@VtB@NTlBJv@fCzSn@lFf@`ERbBTfB"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.70426399999999,
                        "lng" : 119.1853314
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "0.5 公里",
                        "value" : 458
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 64
                     },
                     "end_location" : {
    
    
                        "lat" : 36.7065083,
                        "lng" : 119.1759237
                     },
                     "html_instructions" : "向\u003cb\u003e右\u003c/b\u003e转,进入\u003cb\u003e金马路\u003c/b\u003e",
                     "maneuver" : "turn-right",
                     "polyline" : {
    
    
                        "points" : "}l__FoqkvUoA@[@sHJ}ABoCBgABc@@}@@"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.7023932,
                        "lng" : 119.1760839
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "0.1 公里",
                        "value" : 118
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 28
                     },
                     "end_location" : {
    
    
                        "lat" : 36.7065579,
                        "lng" : 119.1772408
                     },
                     "html_instructions" : "向\u003cb\u003e右\u003c/b\u003e转,进入\u003cb\u003e胜利东街\u003c/b\u003e\u003cdiv style=\"font-size:0.9em\"\u003e目的地在左侧\u003c/div\u003e",
                     "maneuver" : "turn-right",
                     "polyline" : {
    
    
                        "points" : "uf`_FopkvUCgBEsC?K"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.7065083,
                        "lng" : 119.1759237
                     },
                     "travel_mode" : "DRIVING"
                  }
               ],
               "traffic_speed_entry" : [],
               "via_waypoint" : []
            }
         ],
         "overview_polyline" : {
    
    
            "points" : "uz__FalmvUa@LHd@xA[LlA`@fDz@jHrFnd@TfBoA@oILyIL}@@CgBE_D"
         },
         "summary" : "健康东街和金马路",
         "warnings" : [],
         "waypoint_order" : []
      },
      {
    
    
         "bounds" : {
    
    
            "northeast" : {
    
    
               "lat" : 36.7069392,
               "lng" : 119.1854509
            },
            "southwest" : {
    
    
               "lat" : 36.7039003,
               "lng" : 119.1764395
            }
         },
         "copyrights" : "Map data ©2020",
         "legs" : [
            {
    
    
               "distance" : {
    
    
                  "text" : "1.4 公里",
                  "value" : 1357
               },
               "duration" : {
    
    
                  "text" : "5分钟",
                  "value" : 279
               },
               "end_address" : "中国山东省潍坊市奎文区胜利东街华都鲁成大厦",
               "end_location" : {
    
    
                  "lat" : 36.7065579,
                  "lng" : 119.1772408
               },
               "start_address" : "中国潍坊市奎文区健康街潍县中路口",
               "start_location" : {
    
    
                  "lat" : 36.7045897,
                  "lng" : 119.1854509
               },
               "steps" : [
                  {
    
    
                     "distance" : {
    
    
                        "text" : "37 米",
                        "value" : 37
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 7
                     },
                     "end_location" : {
    
    
                        "lat" : 36.7047135,
                        "lng" : 119.1851888
                     },
                     "html_instructions" : "向\u003cb\u003e北\u003c/b\u003e行驶",
                     "polyline" : {
    
    
                        "points" : "uz__FalmvUMBSHDVBL"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.7045897,
                        "lng" : 119.1854509
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "52 米",
                        "value" : 52
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 15
                     },
                     "end_location" : {
    
    
                        "lat" : 36.70426399999999,
                        "lng" : 119.1853314
                     },
                     "html_instructions" : "向\u003cb\u003e左\u003c/b\u003e转,前往\u003cb\u003e804省道\u003c/b\u003e/\u003cwbr/\u003e\u003cb\u003e健康东街\u003c/b\u003e",
                     "maneuver" : "turn-left",
                     "polyline" : {
    
    
                        "points" : "m{__FmjmvUxA["
                     },
                     "start_location" : {
    
    
                        "lat" : 36.7047135,
                        "lng" : 119.1851888
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "0.2 公里",
                        "value" : 167
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 41
                     },
                     "end_location" : {
    
    
                        "lat" : 36.7039003,
                        "lng" : 119.1835148
                     },
                     "html_instructions" : "向\u003cb\u003e右\u003c/b\u003e转,进入\u003cb\u003e804省道\u003c/b\u003e/\u003cwbr/\u003e\u003cb\u003e健康东街\u003c/b\u003e",
                     "maneuver" : "turn-right",
                     "polyline" : {
    
    
                        "points" : "sx__FikmvULlAVtBHp@VtB"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.70426399999999,
                        "lng" : 119.1853314
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "0.3 公里",
                        "value" : 340
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 52
                     },
                     "end_location" : {
    
    
                        "lat" : 36.7069392,
                        "lng" : 119.1839711
                     },
                     "html_instructions" : "向\u003cb\u003e右\u003c/b\u003e转,进入\u003cb\u003e222省道\u003c/b\u003e/\u003cwbr/\u003e\u003cb\u003e潍县中路\u003c/b\u003e",
                     "maneuver" : "turn-right",
                     "polyline" : {
    
    
                        "points" : "kv__F}_mvUgBOYCoBQkBMSAwAMa@E_AIOAEA]C"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.7039003,
                        "lng" : 119.1835148
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "0.7 公里",
                        "value" : 672
                     },
                     "duration" : {
    
    
                        "text" : "2分钟",
                        "value" : 118
                     },
                     "end_location" : {
    
    
                        "lat" : 36.70669,
                        "lng" : 119.1764407
                     },
                     "html_instructions" : "向\u003cb\u003e左\u003c/b\u003e转,进入\u003cb\u003e胜利东街\u003c/b\u003e",
                     "maneuver" : "turn-left",
                     "polyline" : {
    
    
                        "points" : "ki`_FybmvU?PFrD@|AB|AFjGBpBDxDFbFD|DBdC"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.7069392,
                        "lng" : 119.1839711
                     },
                     "travel_mode" : "DRIVING"
                  },
                  {
    
    
                     "distance" : {
    
    
                        "text" : "89 米",
                        "value" : 89
                     },
                     "duration" : {
    
    
                        "text" : "1分钟",
                        "value" : 46
                     },
                     "end_location" : {
    
    
                        "lat" : 36.7065579,
                        "lng" : 119.1772408
                     },
                     "html_instructions" : "\u003cb\u003e调头\u003c/b\u003e\u003cdiv style=\"font-size:0.9em\"\u003e目的地在左侧\u003c/div\u003e",
                     "maneuver" : "uturn-left",
                     "polyline" : {
    
    
                        "points" : "yg`_FwskvU^?EsC?K"
                     },
                     "start_location" : {
    
    
                        "lat" : 36.70669,
                        "lng" : 119.1764407
                     },
                     "travel_mode" : "DRIVING"
                  }
               ],
               "traffic_speed_entry" : [],
               "via_waypoint" : []
            }
         ],
         "overview_polyline" : {
    
    
            "points" : "uz__FalmvUa@LHd@xA[LlA`@fDVtBgBOiCUyFc@sBQL`KXzWHbI^?EsC?K"
         },
         "summary" : "222省道/潍县中路和胜利东街",
         "warnings" : [],
         "waypoint_order" : []
      }
   ],
   "status" : "OK"
}

The key code for parsing and processing:

private fun dealWithData(mBean: LineModule?) {
    
    
        val status = mBean!!.status
        if (status == "OK") {
    
    

            //包含一个数组,其中包含有关起点,目的地和航点的地理编码的详细信息。
            val geocodedWaypoints = mBean!!.geocoded_waypoints
            Log.i(TAG, "geocodedWaypoints.size=${
      
      geocodedWaypoints.size}")


            val routes = mBean!!.routes //路线 测试发现:第一条数据就是最优的线路
            if (routes != null && routes.size > 0) {
    
    
                Log.i(TAG, "routes.size=${
      
      routes.size}")

                var routesNumber = 0;

                routes.forEach {
    
    
                    routesNumber++;

                    //包含的视口边界框 overview_polyline。
                    val bounds = it.bounds

                    routesGlobalPreview(bounds);


                    //包含一个points 对象,该对象保存路线的编码折线表示。该折线是结果方向的近似(平滑)路径。
                    val overviewPolyline = it.overview_polyline

                    val points = overviewPolyline.points
                    Log.i(TAG, "points=$points")


                    // val mLatLngList: MutableList<LatLng> = decodePoly(points) as MutableList<LatLng>

                    val mLatLngList: MutableList<LatLng> = PolyUtil.decode(points)
                    Log.i(TAG, " mLatLngList.size=${
      
      mLatLngList.size}")

                    showLine(mLatLngList, routesNumber);


                    //包含一个数组,该数组包含有关给定路线内两个位置之间路线段的信息。对于指定的每个航点或目的地,将显示一条单独的航段。
                    // (没有航路点的路线将在legs阵列中仅包含一条腿。)每条腿由一系列组成steps。(请参见下面的“ 指导腿”。)
                    val legs = it.legs
                    Log.i(TAG, "legs.size=${
      
      legs.size}")
                    //总时间显示处理
                    calculateTotalTime(legs)


                    // 包含该路线的简短文字说明,适用于对路线进行命名和消除歧义。
                    val summary = it.summary


                    //包含显示这些方向时要显示的警告数组。您必须自己处理并显示这些警告。
                    val warnings = it.warnings


                    //包含要为此路线显示的版权文本。您必须自己处理和显示此信息。
                    val copyrights = it.copyrights


                    //包含一个数组,该数组指示计算出的路线中任何路标的顺序。如果请求是optimize:true在其waypoints参数内 传递的,则此路点可能会重新排序。
                    val waypointOrder = it.waypoint_order


                }
            } else {
    
    
                Log.i(TAG, " routes is null")
            }


        } else {
    
    
            if (status == "ZERO_RESULTS") {
    
    
                Log.i(TAG, " status 在起点和终点之间找不到路由")
            } else {
    
    
                Log.i(TAG, " status=${
      
      status}")
            }


        }
    }

Realize the navigation function

At the end of this article on Google Maps-MapsSDK Integration, we left these two questions:

  1. What should I do if I want to replace the blue dot icon in the screenshot with my own?
  2. After changing to your own icon, how to deal with the direction change of the blue dot?

So here is the answer.

replace blue dot

key code:

 private fun getDeviceLocation() {
    
    

        val selfPermission4 =
            ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        if (selfPermission4 != PackageManager.PERMISSION_GRANTED) {
    
    
            ActivityCompat.requestPermissions(
                this,
                arrayOf(
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_BACKGROUND_LOCATION
                ),
                12
            )
            return
        } else {
    
    
            Log.i(TAG, "getDeviceLocation: 已有权限")
        }

        //就可以去掉官方自带的定位按钮。
        mGoogleMap.isMyLocationEnabled = false
        
        mGoogleMap.uiSettings?.isMyLocationButtonEnabled = true

        //这行代码,就能发起定位请求
        val locationResult = fusedLocationProviderClient.lastLocation

        locationResult.addOnCompleteListener(this) {
    
     task ->
            if (task.isSuccessful) {
    
    
                // Set the map's camera position to the current location of the device.
                val lastKnownLocation = task.result
                if (lastKnownLocation != null) {
    
    
                    Log.i(TAG, "getDeviceLocation:  locationResult if")

                    val currentLocation =
                        LatLng(lastKnownLocation!!.latitude, lastKnownLocation!!.longitude)

                    mGoogleMap.animateCamera(
                        CameraUpdateFactory.newLatLngZoom(
                            currentLocation,
                            17.3f
                        )
                    )

                    if (isFirstLocation) {
    
    
                        val fbearin = lastKnownLocation.bearing //和道路一个方向
                        println("MainActivity.getDeviceLocation fbearin=" + fbearin)
                        //添加自定义定位蓝点
                        mPositionMarker = mGoogleMap!!.addMarker(
                            MarkerOptions()
                                .position(currentLocation)
                                .title("我的位置")
                                .rotation(fbearin)
                                .anchor(0.5f, 0.5f)
                                .icon(BitmapDescriptorFactory.fromResource(R.drawable.baseline_arrow_circle_up_red_900_24dp))
                        )
                    }
                    mPositionMarker!!.position = currentLocation;

                    //添加自定义蓝点范围
                    val circle: Circle = mGoogleMap!!.addCircle(
                        CircleOptions().apply {
    
    
                            center(currentLocation)
                            if (isFirstLocation) {
    
    
                                radius(100.00)
                                strokeWidth(3f)
                                strokeColor(
                                    ContextCompat.getColor(
                                        this@MainActivity,
                                        R.color.purple
                                    )
                                )
                                fillColor(
                                    ContextCompat.getColor(
                                        this@MainActivity,
                                        R.color.blue_100
                                    )
                                )
                                clickable(true)
                                strokePattern(getSelectedPattern(0))
                                isFirstLocation = false
                            }

                        })


                } else {
    
    
                    Log.i(TAG, "getDeviceLocation:  locationResult else")
                }
            } else {
    
    
                Log.e(TAG, "Exception: %s", task.exception)
            }
        }

        
    }

ps: Please take a look at the comments in the code, the comments have been said clearly.

blue dot direction

For the change of the direction of the blue dot, we have to rely on the sensor of the mobile device here. Set the direction of the blue dot by reading the data in the sensor.
Key code:
first get the sensor manager

 mSensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager;

Then implement the SensorEventListener interface

    /加速度传感器数据
    private val accelerometerReading = FloatArray(3)

    //地磁传感器数据
    private val magnetometerReading = FloatArray(3)

    //旋转矩阵,用来保存磁场和加速度的数据
    private val rotationMatrix = FloatArray(9)

    //方向数据
    private val orientationAngles = FloatArray(3)


    class MainActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListener {
    
    }

Then register to monitor

 override fun onResume() {
    
    
        super.onResume()
        //加速度传感器
        val accelerometer: Sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
        if (accelerometer != null) {
    
    
            mSensorManager.registerListener(
                this,
                accelerometer,
                SensorManager.SENSOR_DELAY_NORMAL,
                SensorManager.SENSOR_DELAY_UI
            )
        }
        //地磁传感器
        val magneticField: Sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
        if (magneticField != null) {
    
    
            mSensorManager.registerListener(
                this,
                magneticField,
                SensorManager.SENSOR_DELAY_NORMAL,
                SensorManager.SENSOR_DELAY_UI
            )
        }

    }

    override fun onPause() {
    
    
        super.onPause()
        mSensorManager.unregisterListener(this);
    }

The final interface implementation:

 var mPositionMarker: Marker? = null
    //var azimuth = 0f
    override fun onSensorChanged(event: SensorEvent?) {
    
    
        //判断sensor类型
        if (event!!.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
    
    
            System.arraycopy(
                event.values,
                0,
                accelerometerReading,
                0,
                accelerometerReading.size
            );
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
    
    
            System.arraycopy(
                event.values,
                0,
                magnetometerReading,
                0,
                magnetometerReading.size
            );
        }
        updateOrientationAngles();

    }
    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
    
    
    }

    fun updateOrientationAngles() {
    
    
        // 更新旋转矩阵.
        // 参数1:
        // 参数2 :将磁场数据转换进实际的重力坐标中,一般默认情况下可以设置为null
        // 参数3:加速度
        // 参数4:地磁
        SensorManager.getRotationMatrix(
            rotationMatrix,
            null,
            accelerometerReading,
            magnetometerReading
        )

        //根据旋转矩阵计算设备的方向
        //参数1:旋转数组
        //参数2:模拟方向传感器的数据
        SensorManager.getOrientation(rotationMatrix, orientationAngles)
        val sb = StringBuilder()
        if (orientationAngles.size >= 3) {
    
    
            sb.append("z轴:${
      
      orientationAngles[0]}\n")
            sb.append("x轴:${
      
      orientationAngles[1]}\n")
            sb.append("y轴:${
      
      orientationAngles[2]}\n")

            //Log.i(TAG, "updateOrientationAngles:sb=>> ${sb.toString()}")

            val azimuth = Math.toDegrees(orientationAngles[0].toDouble()).toFloat()
            if (mPositionMarker != null) {
    
    
                mPositionMarker!!.rotation = azimuth
            }

      
        }

    }

At this point, you can replace the blue dot and set the direction of the blue dot by obtaining the data from the device sensor. In combination with the function of real-time positioning, go to open the navigation.

Explanation: The space is limited, and only the key codes are posted in the article. Please click here for the complete project source code:

Project source address


Reference blog:

Official documentation:
https://developers.google.com/maps/documentation/directions/overview

Official demo:

Pick Coordinate System

[Google Maps – Extra Story android-maps-utils use]

Guess you like

Origin blog.csdn.net/da_caoyuan/article/details/109729433