Google Maps Geolocation API를 이용한 현재위치 검색

Google Maps Geolocation API는 WPS(Wi-Fi Positioning System) 방식을 이용하여 측위한 현재 위치 정보를 Web Service 방식으로 제공하는 API입니다. 본 글에서는 Google Maps Geolocation API에 대해서 간단히 소개하고 Android OS에서 구현한 결과를 소개합니다.

 

1. 위치측위기술의 개방

위치기반서비스(LBS, Location Baesed Service)는 위치측위가 가능한 스마트폰의 보급 확산과 위치측위 플랫폼 개방으로 빠르게 발전하면서 패러다임의 변화를 가져왔습니다. 위치측위 기술지원을 기반으로 소셜네트워크서비스(SNS, Social Network Service),증강현실(AR, Augmented Really), 모바일 게임, 모바일 광고 등 다양한 서비스들과 연계한 위치기반서비스가 가능하게 되었고, 위치정보를 활용한 긴급구조 등 사회 안전망으로서도 그 활용성은 더욱 등재되고 있습니다.

 

2. 스마트폰의 위치 측위 기술 (iOS, Android)

iOS와 Android에서는 GPS 위성 신호, Wi-Fi AP, 이동통신사 기지국(Cell-ID)의 위치측위 방법을 지원하며 OS 단에서 API를 통하여 위치정보를 제공받도록 하고 있습니다. 그 중에서 Wi-Fi AP정보로 위치정보를 검색하는 WPS(Wi-Fi Positioning System)를 iOS에서 기본적으로 탑재하면서 일반인들에게 인식되기 시작했습니다. iOS 제품 중 iPod Touch와 같은 GPS나 이동통신사의 위치기반서비스의 이용이 불가능하더라도 위치정보를 제공 받을 수 있게 되었습니다. 이러한 위치측위 방식은 GPS 위성신호를 이용한 위치측위로 해결할 수 없는 도심과 실내 측위에 대해서 WLAN(Wi-Fi)기반 측위의 사용이 가능하게 하고 있고 Skyhook과 같은 사업자에 의해서 WLAN AP의 DB화가 이루어짐으로써 현재 스마트폰에서 WLAN 기술은 위치측위에서도 중요한 요소가 되고 있습니다.

 

3. Wi-Fi Positioning System(WPS)

wps_archi
GPS 위성신호와 이동통신사 기지국을 통한 위치 획득이 어려운 환경에서 사용하는 측위기술로 도심 중심으로 폭넓게 분포되어 운영중인 Wi-Fi AP의 정보를 활용하여 실내 외에서 비교적 정확한 위치를 제공받을 수 있습니다. Wi-Fi AP의 위치정보를 활용하기 위해서는 Wi-Fi AP 정보의 수집 및 분석, 수집 및 분석된 Wi-Fi AP의 정보를 Database에 저장, 사용자 디바이스 주변의 가장 가까운 Wi-Fi AP 정보 수집, 사용자 디바이스 주변의 수집된 Wi-Fi 정보와 Database내의 정보를 비교하여 위치 추정 총 4단계를 통해 정확성 있는 위치정보를 제공받을 수 있습니다.

 

4. Google Maps Geolocation API

wps_archi_google
Google Maps Geolocation API는 Google 서비스의 사용자뿐만 아니라 누구나 사용할 수 있는 위치기반 서비스입니다. Google Maps Geolocation API는 WPS 위치측위 방법을 지원하는 서비스로 사용자가 확인할 수 있는 Wi-Fi AP와 기지국(Cell-ID)의 정보를 기반으로 해서 위치정보를 제공합니다. 실내와 같이 GPS 위성신호를 통한 위치 획득이 어려운 비교적 정확한 위치를 제공합니다.

Geolocation API는 HTTPS 프로토콜의 POST방식으로 통신하며 URL은 아래와 같습니다.

https://www.googleapis.com/geolocation/v1/geolocate?key=API_KEY

Geolocation API를 사용하기 위해서는 API_KEY가 필요합니다. API_KEY는 Google Developers Console에서 발급받은 Server Key이다. API_KEY를 발급받는 절차는 Google Maps Geolocation API Documentation의 “Finding your API key” 항목을 통해 쉽게 발급받을 수 있습니다.

 

Geolocation API의 요청 파라미터 정보는 JSON형식으로 다음과 같이 작성할 수 있습니다.

{“homeMobileCountryCode” : 450, // Mobile Country Code (MCC)로 대한민국은 “450”“homeMobileNetworkCode” : 05,  // Mobile Network Code (MNC)로 SKT-05, KT-08, LGU-06“radioType” : “wcdma”,      // 장비의 통신 타입으로 gsm, cdma, wcdma 지원“carrier” : “SKTelecom”,      // 장비의 통신 서비스를 제공하는 통신사 명

“cellTowers” : [

// 현재 장비가 확인할 수 있는 Cell Tower 정보

],

“wifiAccessPoints” : [

// 현재 장비가 확인할 수 있는 Wi-Fi AP 정보

]

}

각 속성들은 모두 필수가 아닌 선택적이며 설정할 수 있으며 되도록 많은 속성을 설정 할수록 비교적 더 정확한 위치정보를 반환받을 수 있습니다. “cellTowers”“wifiAccessPoints”는 장비가 현재 확인할 수 있는 기지국(Cell-ID) 정보와 Wi-Fi AP 정보를 리스트 형태로 설정합니다. 이 두 속성은 위에서 제시한것처럼 선택적으로 설정하는 속성이지만 위치정보를 측위하기 위해서 둘 중에 하나는 반드시 설정해야 위치정보 결과를 반환 받을 수 있습니다.

 

“cellTowers”는 하나 이상의 기지국(Cell-ID) 정보를 설정해야 하며 JSON형식으로 아래와 같이 작성할 수 있습니다.

{………………………………“cellTowers” : [{“cellId” : 21532831,      // 기지국의 Cell ID

“locationAreaCode” : 2862,  // 기지국의 Location Area Code (LAC)

“mobileCountryCode” : 214,  // 기지국의 Mobile Country Code (MCC)

“mobileNetworkCode” : 7   // 기지국의 Mobile Network Code (MNC)

},

]

………………………………

}

기지국(Cell-ID) 정보는 통신방식에 따라 설정하는 정보값이 다릅니다. 해당 내용을 정리면 아래 표와 같습니다. 검색되는 기지국(Cell-ID) 정보의 통신방식에 따라 해당 내용을 설정합니다.

gsm cdma wcdma
callId Cell ID (CID) Base Station ID UTRAN/GERAN Cell Identity (UC-Id)
locationAreaCode Location Area Code Network ID (NID) Location Area Code
mobileCountryCode Mobile Country Code Mobile Country Code Mobile Country Code
mobileNetworkCode Mobile Network Code System ID (SID) Mobile Network Code

 

“wifiAccessPoints”는 두개 이상의 Wi-Fi AP 정보를 설정해야 하며 JSON형식으로 아래와 같이 작성할 수 있습니다.

{………………………………“wifiAccessPoints” : [{“macAddress”: “01:23:45:67:89:AB”,  // Wi-Fi AP의 MAC Address

“signalStrength”: -65,        // Wi-Fi AP의 신호세기 (dBm)

“age”: 0,             // Wi-Fi AP의 감지하는데 걸린 시간

 ”channel”: 11,           // Wi-Fi AP의 통신 채널

“signalToNoiseRatio”: 40      // Wi-Fi AP의 현재 신호의 noise ratio (dB)

},

]

………………………………

}

“cellTowers”“wifiAccessPoints” 는 필수 항목은 아니지만 위치정보 측위를 위해서 두 속성 중 하나는 반드시 설정해야 위치정보를 반환 받을 수 있습니다. 지금까지 정리한 Geolocation API의 요청 파라미터 정보를 JSON형식의 Request Body로 구성하여 요청하면 아래와 같이 JSON형식으로 위치정보를 반환 받을 수 있습니다.

{“location”: {“lat”: 51.0, // 위치정보의 위도 정보“lng”: -0.1 // 위치정보의 경도 정보},

“accuracy”: 1200.4 // 위치정보의 정확도로서 위추주위의 반경을 meter로 제공

}

요청에 대하여 에러가 발생할 경우에는 아래와 같이 JSON형식으로 오류정보를 반환 받을 수 있습니다.

{“errors”: [   // 오류 상세정보를 리스트로 제공{“domain”: “global”,“reason”: “parseError”,

“message”: “Parse Error”,

}

],

“code”: 400,      // HTTP 응답의 상태와 같은 오류 상태의 코드

“message”: “Parse Error” // 오류 메세지

}

}

“errors” 의 리스트에 반환되는 오류정보를 정리하면 아래 표와 같습니다.

reason domain code 내용
dailyLimitExceeded usageLimits 403 일일 사용량을 초과하였을 경우
keyInvalid usageLimits 400 API_KEY와 Geolocation API가 disable을 경우
userRateLimitExceeded usageLimits 403 사용자에게 할당한 사용량을 초과 하였을 경우
notFound geolocation 404 위치정보에 대한 결과 정보가 없을 경우
parseError global 400 파라메터정보가 유효하지 않은 JSON 형식일 경우

 

5. Android OS에서 Geolocation API를 이용하여 현재 위치정보 측위

Android OS에서 Geolocation API를 이용해서 측위한 현재 위치정보를 아래와 같이 지도에 마킹해 보겠습니다. Java Util의 Map Obejct를 이용해서 Request Body를 구성하기 위해 Simple Json을 이용해서 JSON 형식으로 변환하였습니다.

/* Wi-Fi AP 정보 설정 */ArrayList<Map<String, Object>> wifipPoints = new ArrayList<Map<String, Object>>();for(int index = 0 ; index < wifiInfoList.size() ; index++){Map<String, Object> wifiInfo = wifiInfoList.get(index);Map<String, Object> wifiAP = new HashMap<String, Object>();

wifiAP.put(“macAddress” , wifiInfo.get(“macAddress”));

wifiAP.put(“signalStrength” , wifiInfo.get(“signalStrength”));

wifiAP.put(“age” , wifiInfo.get(“age”));

wifipPoints.add(wifiAccessPoint);

}

requestBody.put(“wifiAccessPoints”, wifiAccessPoints);

 

 

 

/* 기지국 (Cell-ID) 정보 설정 */

ArrayList<Map<String, Object>> cellTowers = new ArrayList<Map<String, Object>>();

for(int index = 0 ; index < cellInfoList.size() ; index++){

Map<String, Object> cellInfo = cellInfoList.get(index);

Map<String, Object> cellTower = new HashMap<String, Object>();

cellTower.put(“cellId” , cellInfo.get(“cellId”));

cellTower.put(“mobileCountryCode” , cellInfo.get(“mobileCountryCode”));

cellTower.put(“mobileNetworkCode” , cellInfo.get(“mobileNetworkCode”));

cellTower.put(“locationAreaCode” , cellInfo.get(“locationAreaCode”));

cellTower.put(“age” , 0);

cellTower.put(“signalStrength” , cellInfo.get(“signalStrength”));

cellTowers.add(cellTower);

}

requestBody.put(“cellTowers”, cellTowers);

 

 

 

/* Request 정보 설정 */

String str_RequestBody = JSONObject.toJSONString(requestBody); TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

String str_MCC = telephonyManager.getNetworkOperator().substring(0, 3);

String str_MNC = telephonyManager.getNetworkOperator().substring(3, 5);

String str_Carrier = telephonyManager.getSimOperatorName();

String str_Radiotype = “none”;

if(telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA){

str_Radiotype = “cdma”;

}

else if(telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM){

str_Radiotype = “gsm”;

}

Map<String, Object> requestBody = new HashMap<String, Object>();

requestBody.put(“homeMobileCountryCode”, str_MCC);

requestBody.put(“homeMobileNetworkCode”, str_MNC);

requestBody.put(“carrier”, str_Carrier);

if(!str_Radiotype.equals(“none”)){

requestBody.put(“radioType”, str_Radiotype);

}

Request Body는 TelephonyManager를 이용해서 기본적인 정보와 기지국(Cell-ID) 정보를 설정하였고 WiFiManage를 이용해서 Wi-Fi AP 정보를 설정하였습니다. 기지국(Cell-ID) 정보와 Wi-Fi AP 정보를 검색하는 부분은 Android API를 참고 하였습니다. Apache Http를 이용해서 HTTPS 프로토콜의 POST방식으로 구성한 Request Body와 함께 API 호출하였습니다.

/* HTTPS POST로 API Request 설정 */HttpClient http = new DefaultHttpClient();HttpPost httpPost = new HttpPost(url_GeoLocation);StringEntity stringEntity = null;try {

stringEntity = new StringEntity(str_RequestBody, “utf-8”);

stringEntity.setContentType(“application/json”);

} catch (UnsupportedEncodingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

httpPost.setEntity(stringEntity);

 

HttpResponse responsePost;

try {

responsePost = http.execute(httpPost);

HttpEntity resEntity = responsePost.getEntity();

String str_ResponseData = EntityUtils.toString(resEntity);

 

JSONObject root = (JSONObject) JSONValue.parse(str_ResponseData);

JSONObject location = (JSONObject) root.get(“location”);

 

Map<String, Object> result = new HashMap<String, Object>();

if(location != null){

result.put(“lat”, location.get(“lat”));

result.put(“lng”, location.get(“lng”));

result.put(“accuracy”, root.get(“accuracy”));

}

else{

JSONObject error = (JSONObject) root.get(“error”);

result.put(“lat”, 0.0);

result.put(“lng”, 0.0);

result.put(“accuracy”, 0.0);

result.put(“message”, error.get(“message”));

result.put(“code”, error.get(“code”));

}

return result;

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

응답 결과는 Simple Json을 이용해서 Java Util의 Map Object로 변환 후 Google Map에 Marker를 이용하여 결과를 출력하면 아래와 같습니다. 결과를 확인해보면 WI-FI AP를 이용해서 얻은 위치정보는 Android OS의 Location API와 동일한 위치를 마킹하고 있는것을 확인할 수 있고 기지국(Cell-ID)을 이용해서 얻은 위치정보는 약간의 오차가 있는것을 확인할 수 있습니다.

result

 

 

 

참고자료 :

– Google Maps Geolocation API – https://developers.google.com/maps/documentation/business/geolocation/

– 위치정보의 서비스 동향과 패러다임의 변화 – http://www.kisa.or.kr/uploadfile/201306/201306211453125421.pdf

– TTA Journal : 스마트폰 위치기반 서비스(LBS) 기술 동향