rlqja1107 / LocationService

Based on Location Service, We would put a electronic kick-board option on Finding Way
0 stars 0 forks source link

GoogleApi를 이용한 Direction5 #2

Open rlqja1107 opened 4 years ago

rlqja1107 commented 4 years ago

GooleApi Direcion의 활용

설명

GoogleApi에서 Direction Api를 활용해 출발점과 목적지의 위도 경도를 알 때, 지도 위에 나타내는 과정

비용

월 $200지원
1000번당 5달러 ->최대 40,000회 사용가능

한계점

도보,자동차 경로는 안나오고 대중교통을 활용한 경로를 알려줌(mode가 transit으로만 가능)
대신, 미국 등의 나라에서는 도보, 자전거 경로 지원
따라서, 현위치에서 역, 정류장까지의 경로는 직선으로 나오는 한계점
-->보완점으로 정류장, 역까지의 경로는 NaverApi-Direction 활용할 예정

제공방식

Rest Api

코드

출발점과 목적지를 LatLng 객체로 매개변수로 받아 URL을 반환

  fun getDirectionUrl(origin: LatLng, dest: LatLng): String {
        return "https://maps.googleapis.com/maps/api/directions/json?origin=${origin.latitude},${origin.longitude}&destination=${dest.latitude},${dest.longitude}&mode=transit&departure_time=now&language=ko&key=YOUR_KEY"
    }

URL을 매개변수로 받아 지도 위에 PolyLine그리는 inner class Code

MainActivity.map은 MainActivity에서 변수 map은 compaion object의 한 요소로 타입은 GoogleMap
lateinit var map: GoogleMap
AsyncTask를 상속받은 클래스의 instance가 execute()를 실행시 비동기 실행한다. RestApi 호출하는 경우, 무조건 비동기로 처리해야한다. AsyncTask말고 동기적으로 처리하고 싶으면 retrofit2를 활용하여 enque실행한다.
여기서는 Okhttp 라이브러리를 활용해 url을 호출함

 inner class GetDirection(var url: String) : AsyncTask<Void, Void, List<List<LatLng>>>() {
        override fun doInBackground(vararg p0: Void?): List<List<LatLng>> {
            val client = OkHttpClient()
            val request = Request.Builder().url(url).build()
            val response = client.newCall(request).execute()
            val data = response.body?.string()
            val result = ArrayList<List<LatLng>>()
            try {

                 val obj = Gson().fromJson(data,GoogleMapDTO::class.java)
                val path = ArrayList<LatLng>()
                var onlyFirst=0
                for (i in 0 until obj.routes[0].legs[0].steps.size) {
                    if(obj.routes[0].legs[0].steps[i].travel_mode=="WALKING"&&onlyFirst==0){
                        MainActivity.walkingTime=obj.routes[0].legs[0].steps[i].duration.text
                        onlyFirst++
                    }
                    path.addAll(decodePolyline(obj.routes[0].legs[0].steps[i].polyline.points))
                }

                result.add(path)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return result
        }

        override fun onPostExecute(result: List<List<LatLng>>?) {

            if (result != null) {
                val lineoption=PolylineOptions()
                for(i in result.indices){
                       lineoption.addAll(result[i])
                        .width(15f)
                        .color(Color.BLUE)
                        .geodesic(true)
                }
                MainActivity.polyline=MainActivity.map.addPolyline(lineoption)

            }
        }

    }

Rest Api Response로 Polyline이 주어지는데 이를 해독하여 지도 위에 나타내는 함수

inner class GetDirection를 보면 decodePolyline로 polyline의 point를 해독함

fun decodePolyline(encoded:String):List<LatLng>{
        val poly=ArrayList<LatLng>()
        var index=0
        var len=encoded.length
        var lat=0
        var lng=0
        while(index<len){
            var b:Int
            var shift=0
            var result=0
            do{
                b=encoded[index++].toInt() - 63
                result=result or (b and 0x1f shl shift)
                shift+=5
            }while(b>=0x20)
            val dlat=if(result and 1 !=0) (result shr 1).inv() else result shr 1
            lat+=dlat

            shift=0
            result=0
            do{
                b=encoded[index++].toInt() -63
                result=result or (b and 0x1f shl shift)
                shift+=5
            }while(b>=0x20)
            val dlng=if(result and 1 !=0) (result shr 1).inv() else result shr 1
            lng+=dlng
            val latLng=LatLng(lat.toDouble()/1E5,lng.toDouble()/1E5)
            poly.add(latLng)
        }
        return poly
    }

실행 코드

위 코드의 전체 class 이름이 Direcion_Finder

                var direction = Direction_Finder()
                var url = direction.getDirectionUrl(startLocation!!, endLocation!!)
                direction.GetDirection(url).execute()

Response Json 형태

"geocoded_waypoints" : [
          {
             "geocoder_status" : "OK",
             "place_id" : "ChIJFSvxtVijfDURN_aPuGcxtnk",
             "types" : [ "street_address" ]
I/System.out:       },
          {
             "geocoder_status" : "OK",
             "place_id" : "ChIJVZtRbqekfDURdfjvsMiiLmo",
             "types" : [ "street_address" ]
          }
       ],
       "routes" : [
          {
             "bounds" : {
                "northeast" : {
                   "lat" : 37.5590354,
I/System.out:                "lng" : 127.04103
                },
                "southwest" : {
                   "lat" : 37.557686,
                   "lng" : 127.03842
                }
             },
             "copyrights" : "Map data ©2020 SK telecom",
             "legs" : [
                {
                   "arrival_time" : {
                      "text" : "오후 12:06",
I/System.out:                   "time_zone" : "Asia/Seoul",
                      "value" : 1595300783
                   },
                   "departure_time" : {
                      "text" : "오후 12:02",
                      "time_zone" : "Asia/Seoul",
                      "value" : 1595300558
                   },
                   "distance" : {
                      "text" : "0.4 km",
                      "value" : 422
                   },
                   "duration" : {
I/System.out:                   "text" : "4분",
                      "value" : 225
                   },
                   "end_address" : "대한민국 서울특별시 성동구 행당동 21-4",
                   "end_location" : {
                      "lat" : 37.5590354,
                      "lng" : 127.0409726
                   },
                   "start_address" : "대한민국 서울특별시 성동구 행당1동 130-101",
                   "start_location" : {
                      "lat" : 37.5582625,
I/System.out:                   "lng" : 127.0389643
                   },
                   "steps" : [
                      {
                         "distance" : {
                            "text" : "48 m",
                            "value" : 48
                         },
                         "duration" : {
                            "text" : "1분",
                            "value" : 49
                         },
I/System.out:                      "end_location" : {
                            "lat" : 37.558229,
                            "lng" : 127.03842
                         },
                         "html_instructions" : "행당1동주민센터.성동소방서까지 도보",
                         "polyline" : {
                            "points" : "crfdFohkfWDjB"
                         },
                         "start_location" : {
                            "lat" : 37.5582625,
                            "lng" : 127.0389643
                         },
I/System.out:                      "steps" : [
                            {
                               "distance" : {
                                  "text" : "48 m",
                                  "value" : 48
                               },
                               "duration" : {
                                  "text" : "1분",
                                  "value" : 49
                               },
                               "end_location" : {
                                  "lat" : 37.558229,
                                  "lng" : 127.03842
                               },
I/System.out:                            "polyline" : {
                                  "points" : "crfdFohkfWDjB"
                               },
                               "start_location" : {
                                  "lat" : 37.5582625,
                                  "lng" : 127.0389643
                               },
                               "travel_mode" : "WALKING"
                            }
                         ],
                         "travel_mode" : "WALKING"
                      },
I/System.out:                   {
                         "distance" : {
                            "text" : "0.4 km",
                            "value" : 364
                         },
                         "duration" : {
                            "text" : "2분",
                            "value" : 135
                         },
                         "end_location" : {
                            "lat" : 37.558944,
                            "lng" : 127.041015
I/System.out:                      },
                         "html_instructions" : "버스 면목동행",
                         "polyline" : {
                            "points" : "}qfdFcekfWAA?AE??An@wBVm@\\qAJqA@eAGk@[i@o@MyAA[Co@I?B"
                         },
                         "start_location" : {
                            "lat" : 37.558229,
                            "lng" : 127.03842
                         },
                         "transit_details" : {
                            "arrival_stop" : {
                               "location" : {
                                  "lat" : 37.558944,
I/System.out:                               "lng" : 127.041015
                               },
                               "name" : "한양대앞.한양시장"
                            },
                            "arrival_time" : {
                               "text" : "오후 12:05",
                               "time_zone" : "Asia/Seoul",
                               "value" : 1595300742
                            },
                            "departure_stop" : {
                               "location" : {
                                  "lat" : 37.558229,
                                  "lng" : 127.03842
                               },
I/System.out:                            "name" : "행당1동주민센터.성동소방서"
                            },
                            "departure_time" : {
                               "text" : "오후 12:03",
                               "time_zone" : "Asia/Seoul",
                               "value" : 1595300607
                            },
                            "headsign" : "면목동",
                            "headway" : 600,
                            "line" : {
                               "agencies" : [
                                  {
I/System.out:                                  "name" : "서울특별시버스운송사업조합",
                                     "url" : "http://www.odsay.com/Bus/Seoul_Main.asp?CID=1000&LMenu=1"
                                  }
                               ],
                               "color" : "#0abb0c",
                               "name" : "서울 지선버스",
                               "short_name" : "2013",
                               "text_color" : "#ffffff",
                               "vehicle" : {
                                  "icon" : "//maps.gstatic.com/mapfiles/transit/iw2/6/bus2.png",
                                  "name" : "버스",
                                  "type" : "BUS"
                               }
I/System.out:                         },
                            "num_stops" : 1
                         },
                         "travel_mode" : "TRANSIT"
                      },
                      {
                         "distance" : {
                            "text" : "10 m",
                            "value" : 10
                         },
                         "duration" : {
I/System.out:                         "text" : "1분",
                            "value" : 11
                         },
                         "end_location" : {
                            "lat" : 37.5590354,
                            "lng" : 127.0409726
                         },
                         "html_instructions" : "대한민국 서울특별시 성동구 행당동 21-4까지 도보",
                         "polyline" : {
                            "points" : "kvfdFiukfWSF"
                         },
                         "start_location" : {
                            "lat" : 37.558944,
I/System.out:                         "lng" : 127.041015
I/System.out:                      },
                         "steps" : [
                            {
I/System.out:                            "distance" : {
                                  "text" : "10 m",
                                  "value" : 10
                               },
                               "duration" : {
                                  "text" : "1분",
                                  "value" : 11
                               },
                               "end_location" : {
                                  "lat" : 37.5590354,
                                  "lng" : 127.0409726
                               },
                               "polyline" : {
                                  "points" : "kvfdFiukfWSF"
I/System.out:                            },
                               "start_location" : {
                                  "lat" : 37.558944,
                                  "lng" : 127.041015
                               },
                               "travel_mode" : "WALKING"
                            }
                         ],
                         "travel_mode" : "WALKING"
                      }
                   ],
I/System.out:                "traffic_speed_entry" : [],
                   "via_waypoint" : []
                }
             ],
             "overview_polyline" : {
                "points" : "crfdFohkfWDjBAAEAn@yBVm@\\qAJqA@eAGk@[i@o@MyAAkAMSJ"
             },
             "summary" : "",
             "warnings" : [
                "도보 경로는 베타 서비스입니다. 주의 – 이 경로에는 인도 또는 보행 경로가 누락되었을 수도 있습니다."
             ],
             "waypoint_order" : []
          }
       ],
       "status" : "OK"
    }