날뛰는 코드

역지오코딩, 마커 찍은곳 위치 표시하기 (17/08/26) 본문

안드로이드/구글 맵

역지오코딩, 마커 찍은곳 위치 표시하기 (17/08/26)

미 냉 2017. 8. 26. 18:02

 

 

큰 맥락

 

1. 맵 클릭

2. 클릭한 위치정보(경되,위도)를 url주소로 합쳐서 googlemap geocoding보냄

3. Json 정보 받아옴

4. 필요한 정보 파싱

5. 파싱한 정보 받아서 마커찍을때 위치정보와 함께 이름과 snippet에 표시 

 


맵에서 클릭하는부분

// 맵 클릭 리스너
map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
// pickMark(latLng,"a","a");
String url = getUrl(latLng);
fetch_RgeoUrl fUrl = new fetch_RgeoUrl();
fUrl.execute(url,Double.toString(latLng.latitude),Double.toString(latLng.longitude));
Log.d("R_g",Double.toString(latLng.latitude)+" " +Double.toString(latLng.longitude));
}
});

일단 url 쓰려면 키값받아와서 해줘야한다.

https://developers.google.com/maps/documentation/geocoding/start?hl=ko#reverse

-키 가져오고

private String[] getUrl(LatLng place)
{
String[] url = {"",""};
String latlng_place = "latlng=" + place.latitude + "," + place.longitude;
Log.d("latlng",latlng_place);
url[0] = "https://maps.googleapis.com/maps/api/geocode/json?" + latlng_place + "&key=AIzaSyCm03LatWFr4wpLYSOnVqHZdjsNPc8hvi0";
// http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=AIzaSyCm03LatWFr4wpLYSOnVqHZdjsNPc8hvi0 - PC
return url;
}

형식에 따라 맞춰서 보낼 URL 위치정보를 합쳐준다.

 private String downloadUrl(String strUrl) throws IOException
{
String data = "";
InputStream iStream = null;
HttpsURLConnection urlConnection = null;
Log.d("Url",strUrl);
try{
URL url = new URL(strUrl);

// url 만들기
urlConnection = (HttpsURLConnection) url.openConnection();

// 연결
urlConnection.connect();

// 데이터 읽기
iStream = urlConnection.getInputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
// BufferedReader br = new BufferedReader(new InputStreamReader(iStream, StandardCharsets.UTF_8));

StringBuffer sb = new StringBuffer();

String line = "";
while((line = br.readLine()) != null)
{
sb.append(line);
}

data = sb.toString();
Log.d("downloadUrl", data.toString());
br.close();

}
catch (Exception e)
{
Log.d("Urlfail", "urldownloadfail");
}
finally
{
Log.d("Urlend", "end");
iStream.close();;
urlConnection.disconnect();
}
return data;
}

다운로드해서 데이터 얻어오는 부분

 

private class fetch_RgeoUrl extends AsyncTask<String, String, String[]>
{
protected String[] doInBackground(String... URLnLL)
{
String[] data={"","",""};
try {
data[0] = downloadUrl(URLnLL[0]);
data[1] = URLnLL[1];
data[2] = URLnLL[2];
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;

}
protected void onPostExecute(String[] result){
super.onPostExecute(result);
JSONObject jObject;
List<String> Rgeo;
try {
jObject= new JSONObject(result[0]);
DataParser parser = new DataParser();
LatLng LL = new LatLng(Double.parseDouble(result[1]),Double.parseDouble(result[2]));
Rgeo = parser.R_geocoding(jObject);
pickMark(LL,Rgeo.get(0),Rgeo.get(1));


} catch (JSONException e) {
e.printStackTrace();
}
}
}// fetchRgeoUrl

 

여기서 downloadUrl 사용 해 그 데이터 이용

그 데이터 내용 (엄청 길게나오는데 잘랐다)

{ "results" : [ { "address_components" : [ { "long_name" : "17-3", "short_name" : "17-3", "types" : [ "political", "premise" ] }, { "long_name" : "태평로2가", "short_name" : "태평로2가", "types" : [ "political", "sublocality", "sublocality_level_2" ] }, { "long_name" : "중구", "short_name" : "중구", "types" : [ "political", "sublocality", "sublocality_level_1" ] }, { "long_name" : "서울특별시", "short_name" : "서울특별시", "types" : [ "locality", "political" ] }, { "long_name" : "대한민국", "short_name" : "KR", "types" : [ "country", "political" ] }, { "long_name" : "100-102", "short_name" : "100-102", "types" : [ "postal_code" ] } ], "formatted_address" : "대한민국 서울특별시 중구 태평로2가 17-3", "geometry" : { "location" : { "lat" : 37.5652985, "lng" : 126.9777222 }, "location_type" : "ROOFTOP", "viewport" : { "northeast" : { "lat" : 37.56664748029149, "lng" : 126.9790711802915 }, "southwest" : { "lat" : 37.56394951970849, "lng" : 126.9763732197085 } } }, "place_id" : "ChIJM0bp8vKifDURLcoKflUoqRU", "types" : [ "political", "premise" ] }, { "address_components" : [ { "long_name" : "세종대로", "short_name" : "세종대로", "types" : [ "political", "sublocality", "sublocality_level_4" ] }, { "long_name" : "중구", "short_name" : "중구", "types" : [ "political", "sublocality", "sublocality_level_1" ] }, { "long_name" : "서울특별시", "short_name" : "서울특별시", "types" : [ "locality", "political" ] }, { "long_name" : "서울특별시", "short_name" : "서울특별시", "types" : [ "administrative_area_level_1", "political" ] }, { "long_name" : "대한민국", "short_name" : "KR", "types" : [ "country", "political" ] } ], "formatted_address" : "대한민국 서울특별시 중구 세종대로", "geometry" : { "bounds" : { "northeast" : { "lat" : 37.5689066, "lng" : 126.9782699 }, "southwest" : { "lat" : 37.5568778, "lng" : 126.9724008 } }, "location" : { "lat" : 37.5624945, "lng" : 126.9752957 }, "location_type" : "APPROXIMATE", "viewport" : { "northeast" : { "lat" : 37.5689066, "lng" : 126.9782699 }, "southwest" : { "lat" : 37.5568778, "lng" : 126.9724008 } } }, "place_id" : "ChIJXwA5qoyifDUREyhKPjwY4Ek", "types" : [ "political", "sublocality", "sublocality_level_4" ] },

....................................... (후략)

 

이런식으로 나오는데 엄청 길게 나온다.

실험 해보니 맨 처음의 "formatted_address" : "대한민국 서울특별시 중구 태평로2가 17-3" 이 부분이 괜찮게 나온다.

이거를 snippet 부분에 넣고

위의 두 long name을 합쳐서 이름에 넣게 

파싱해 와서 리턴해보장

public List<String> R_geocoding(JSONObject jObject)
{
List<String> f_a= new ArrayList<>();
JSONArray jResults;
JSONArray jAddress;
try {
jResults = jObject.getJSONArray("results");
jAddress = ((JSONObject)jResults.get(0)).getJSONArray("address_components");
f_a.add(((JSONObject)(jAddress.get(0))).get("long_name").toString()+" " +((JSONObject)(jAddress.get(1))).get("long_name").toString());
f_a.add(((JSONObject)jResults.get(0)).get("formatted_address").toString());
Log.d("R_g", f_a.get(0) );

} catch (JSONException e) {
e.printStackTrace();
Log.d("R_g","R_g error");
}
return f_a;

이 파싱함수를 써서 리턴값을 받아온다.

 

private class fetch_RgeoUrl extends AsyncTask<String, String, String[]>
{
protected String[] doInBackground(String... URLnLL)
{
String[] data={"","",""};
try {
data[0] = downloadUrl(URLnLL[0]);
data[1] = URLnLL[1];
data[2] = URLnLL[2];
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;

}
protected void onPostExecute(String[] result){
super.onPostExecute(result);
JSONObject jObject;
List<String> Rgeo;
try {
jObject= new JSONObject(result[0]);
DataParser parser = new DataParser();
LatLng LL = new LatLng(Double.parseDouble(result[1]),Double.parseDouble(result[2]));
Rgeo = parser.R_geocoding(jObject);
pickMark(LL,Rgeo.get(0),Rgeo.get(1));


} catch (JSONException e) {
e.printStackTrace();
}
}
}// fetchRgeoUrl

받아온 주소값과 경도위도를 맵을 클릭 할때 받아온걸 넘겨줘 찍었다.

 

 

 

 private void pickMark(final LatLng LL,String name, String address)
{
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(LL);
// markerOptions.title(String.format(Locale.KOREA,"%.3f",LL.latitude)+","+String.format(Locale.KOREA,"%.3f",LL.longitude));
markerOptions.title(name);
markerOptions.snippet(address.substring(0,40));
// markerOptions.snippet(address);
markerOptions.draggable(true);

//색 다르게
if(MarkerPoints.size()==0)
{
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}
else if (MarkerPoints.size() == 1) {
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
}
else if(MarkerPoints.size()>1)
{
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));

}
map.addMarker(markerOptions).setDraggable(true);
map.addMarker(markerOptions).showInfoWindow();
MarkerPoints.add(LL);
} // pickMark

마커 찍는부분

주소는 길어서 40까지 잘랏다.

 

역지오코딩 해서 맵 클릭해서 나온 위치정보를 넘겨주려면 전역변수쓰던가

뭐 다르게 리턴하는게 있는거 같은데 그냥 위도경도를 같이 넘겨줘서 좀이상하게됬다.

나중에 최적화 해보자

 

 

 결과.

 


 음근데 뭔가 대중교통 결과 받아오는게 좀 이상해졌네

우리나라는 구글디렉션으로 하면안되겠다..

 

 

전체 코드

https://github.com/littlecold2/googlemap_test

Comments