Google Play 서비스의 Fused Location Provider를 이용한 현재위치 측위

안드로이드에서 LocationManager를 이용해서 현재위치를 측위할 때 개발자가 직접 기능을 구현하기 때문에 측위 방법의 선택과 그에 대한 고려사항이 많아 복잡하고 어려웠습니다. 이번 블로그에서는 이런 문제를 해결할수 있는 FusedLocationProvider API와 Google Play 서비스에 대하여 간단히 소개하도록 하겠습니다.

 

1. iOS의 위치측위 방법 (CLLocationManager)
//헤더파일 설정 (.h)#import@interface PhotoViewController : UIViewController <CLLocationManagerDelegate>{

CLLocationManager *locationManager;

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

}

@property (nonatomic, strong) CLLocationManager *locationManager;

 

 

//소스파일 설정 (.m)

locationManager = [[CLLocationManager alloc]init];// 초기화

locationManager.delegate = self;// delegate 연결

locationManager.desiredAccuracy = kCLLocationAccuracyBest;// 정확도 최고로 설정

[locationManager startUpdatingLocation];// 현재 위치 업데이트

NSLog(@”%f”,locationManager.location.coordinate.latitude);// latitude

NSLog(@”%f”,locationManager.location.coordinate.longitude);// longitude

iOS는 CLLocationManager를 통해 측위요청하면 CLLocationManager에서 설정하는 정확도 레벨에 근거해 GPS, Wi-FI, CellTower 순으로 측위하여 측위된 결과를 CLLocationManagerDelegate를 통해 CLLocationManager에 전달됩니다. 사용자는 해당정보를 CLLocation을 통해 확인할 수 있습니다. iOS는 OS단과 해당 API가 해당 서비스에 대한 모든 처리를 담당하고 있기 때문에 개발자는 간단하게 API를 호출하여 현재 위치를 측위할 수 있습니다.

 

2. 안드로이드 위치측위 방법 (LocationManager)
//AndroidManifest.xml<!– 위치측위에 사용한 Provider 권한 설정. –><uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION” />

<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION” />

 

 

//안드로이드 Activity Class

private LocationManager locationManager;

private boolean gps_enabled = false;

private boolean network_enabled = false;

 

@Override

public voidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

 

locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);

gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);//GPS 이용가능 여부

network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);//Network 이용가능 여부

if(!gps_enabled && !network_enabled){

Log.d(“LocationManagerTest”,“nothing is enabled”)//모두 사용 불가

return;

}

 

if((gps_enabled)//GPS를 이용한 측위요청

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);// 현재 위치 업데이트

 

if((network_enabled)//Network를 이용한 측위요청

locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);// 현재 위치 업데이트

}

 

LocationListener locationListenerGps = new LocationListener() {

public void onLocationChanged(Location location) {

double x =location.getLatitude();

double y = location.getLongitude();

locationManager.removeUpdates(this);

locationManager.removeUpdates(locationListenerNetwork);

 

Log.d(“LocationManagerTest”,“gps enabled”+x + “\n” + y, duration)

}

 

public void onProviderDisabled(String provider) {

}

 

public void onProviderEnabled(String provider) {

}

 

public void onStatusChanged(String provider, int status, Bundle extras) {

}

};

 

LocationListener locationListenerNetwork = new LocationListener() {

public void onLocationChanged(Location location) {

double x = location.getLatitude();

double y = location.getLongitude();

locationManager.removeUpdates.removeUpdates(this);

locationManager.removeUpdates.removeUpdates(locationListenerGps);

Log.d(“LocationManagerTest”,“network enabled”+x + “\n” + y, duration)

}

 

public void onProviderDisabled(String provider) {

}

 

public void onProviderEnabled(String provider) {

}

 

public void onStatusChanged(String provider, int status, Bundle extras) {

}

};

Android는 GPS, Network 중에서 개발자가 측위할 방법를 직접 선택하고 구현해야 합나디. Wi-Fi를 통한 위치 확인은 Manifest를 통해 권한 설절(ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION)을 설정한 경우에 따라 위치 측위가 가능합니다. LocationManager를 통해 측위요청을 할때 GPS, Network 중 이용가능한 Provider를 검색하고, Provider 정보와 함께 요청하면 등록한 LocationListener를 통해 측위된 결과를 확인할 수 있습니다. 위의 소스는 사용가능한 Provider정보를 통해 GPS, Wi-Fi, CellTower 중 하나만을 선택하여 측위하였지만 iOS와 같이 순차적으로 선택하여 각각의 위치를 획득, 비교하여 해당결과 전달하게 되면다면 여러조건에 대하여 고려해야할 부분이 발생하고 정확한 결과를 위해 보정(getBestprovider, isBetterLocation, PassiveProvider)이 필요하기 때문에 아마 위의 소스보다 더 복잡할 것입니다.

 

3. Fused Location Provider를 이용한 위치 측위

Fused Location Provider는 Google I/O 2013에서 기존의 LocationManager를 개선한 위치측위 기술입니다. Fused Location Provider의 특징은 저전력으로 위치측위의 정확도를 향상시켰고, 기존보다 간편하게 API 호출하여 위치를 측위할 수 있도록 개선되었습니다. Fused Location Provider는 Google Play 서비스를 통해 API형태로 사용할 수 있습니다.

play-services-diagram

Google Play 서비스는 구글에서 제공하는 다양한 서비스들을 손쉽게 사용할 수 있도록 제공하는 클라이언트 라이브러리입니다. 구글 플레이 스토어를 통한 자동 플랫폼 업데이트를 지원하기 때문에 OS버전이나, 통신사 버전에 따른 디바이스 지원에 대한 걱정없이 구글이 제공하는 최신의 기능을 쉽게 빠르게 사용할 수 있습니다.

google_play_service_install

 

Google Play 서비스 라이브러리는 Android-SDK의 “./extras/google/google_play_services” 폴더에 라이브러리 프로젝트, 문서. Sample 정보가 저장되어 있습니다. 만약 해당폴더가 없다면 Eclipse의 Android SDK Manager를 통해 다운로드 받을 수 있습니다. Google Play 서비스 라이브러리는 Android Project로 제공되기는 때문에 Eclipse의 Import Project를 통해 “./extras/google/google_play_services/libproject” 위치의 Android Project를 Import 합니다. Import된 Project Properties의 Android 속성 중 Library 항목에서 “is Library”를 체크하여 project의 속성을 Library로 설정합니다. 마지막으로 나의 Project Properties에서 Android 속성의 Library 항목에 Import한 Google Play 서비스 Project를 Add하면 Google Play 서비스를 사용하기 위한 설정이 완료됩니다.

 

설정이 완료되었다면 Google Play 서비스를 통해 Fused Location Provider API를 호출해 보도록 하겠습니다. Google Play 서비스를 통해 구글에서 제공하는 다양한 API를 호출하기 위해서는 Google Client를 통해 접근승인을 받은 후 API를 사용할 수 있습니다. Google Clinet를 이용한 접근승인 요청 내용은 아래와 같이 작성할 수 있습니다.

//Google Play 서비스 접근승인 요청public GoogleApiClient.Builder setGoogleServiceBuilder(){

//Google Api Client 생성

GoogleApiClient.Builder mGoogleApiClientBuilder = new GoogleApiClient.Builder(this.activity);

mGoogleApiClientBuilder.addApi(LocationServices.API);//Fused Location Provider API 사용요청

 

//Google Client Connection Callback 클래스

CallbackConnectedGoogleService callbackConnectedGoogleService = new CallbackConnectedGoogleService(this);

mGoogleApiClientBuilder.addConnectionCallbacks(callbackConnectedGoogleService);

mGoogleApiClientBuilder.addOnConnectionFailedListener(callbackConnectedGoogleService);

 

GoogleApiClient mGoogleApiClient = mGoogleApiClientBuilder.build();

mGoogleApiClient.connect();

 

return mGoogleApiClientBuilder;

}

 

 

//Google Play 서비스 접근승인 응답

class CallbackConnectedGoogleService implements ConnectionCallbacks, OnConnectionFailedListener{

 

private String LOG_TAG = “CallbackGooglePlacesService”;

private GoogleServiceControl googleServiceControl;

 

public CallbackConnectedGoogleService(GoogleServiceControl googleServiceControl){

this.googleServiceControl = googleServiceControl;

}

 

@Override

public void onConnectionFailed(ConnectionResult result) {

// TODO Auto-generated method stub

Log.d(LOG_TAG, “GoogleService onConnectionSuspended”);

Log.d(LOG_TAG, “Connected Failed : “ + result.getErrorCode());

}

 

@Override

public void onConnected(Bundle connectionHint) {

// TODO Auto-generated method stub

Log.d(LOG_TAG, “GoogleService onConnected”);

Log.d(LOG_TAG, “Connected Success”);

}

 

@Override

public void onConnectionSuspended(int cause) {

// TODO Auto-generated method stub

Log.d(LOG_TAG, “GoogleService onConnectionSuspended”);

Log.d(LOG_TAG, “Suspended cause : “ + cause);

}

}

 

 

GoogleApiClient ClassGoogleApiClient.Builderd에 접근요청과 관련된 다양한 속성을 설정한 후 생성되는 클래스로서 connect() 함수를 통해 접근승인을 요청을 할 수 있습니다. 그리고 GoogleApiClient.Builderd Class의 addApi()함수에는 접근요청할 API의 정보를 설정합니다. Fused Location Provider API를 사용하기 위해 addApi() 함수에 LocationServices.API를 설정하였습니다. connect() 함수를 호출하면 접근승인 요청을 전달하게 되고 리스너로 등록한 CallbackConnectedGoogleService Class로 전달됩니다. ConnectionCallbacks, OnConnectionFailedListener interface을 통해 override한 onConnected(), onConnectionSuspended(), onConnectionFailed()를 통해 각 응답 상태에 따라 결과를 받아서 처리할 수 있습니다. 이와같은 접근승인 요청은 몇개의 API를 사용하더라도 앱에서 한번만 수행하면 됩니다. Drive, Place 등과 같은 다른 서비스를 이용한다면 addApi()함수를 이용해서 원하는 서비스만 추가하면 됩니다.

(Android Develop – Google Play Services)

 

//Fused Location Provider API 호출public void getLastKnownLocation(GoogleApiClient mGoogleApiClient){Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

Log.d(“Fused Location Provider API : Latitude”, mLastLocation.getLatitude());

Log.d(“Fused Location Provider API : Longitude”, mLastLocation.getLongitude());

Log.d(“Fused Location Provider API : Accuracy”, mLastLocation.getAccuracy());

}

접근승인 요청이 성공하면 Fused Location Provider API에 대한 LocationServices Class를 사용할 수 있다. Connection을 요청했던 GoogleApiClient Class의 Instance로 하여 getLastKnownLocation() 함수를 호출하면 현재위치를 측위한 결과값을 Location Class로 받을 수 있다. LocationManager를 이용해서 현재위치를 측위하는 로직에 비해 매우 간소해 진걸 확인할 수 있습니다. getLastKnownLocation()이외에도 측위에 대한 다양한 함수는 Android Develop Reference에서 확인할 수 있습니다.

 

응답받은 결과를 지도에 출력해서 WPS 방식의 Geolocation API와 LocationManager(GPS)와 비교해보면 아래와 같습니다. 아래 위치는 실내에서 측위를 했을때의 결과입니다. Geolocation API은 실내에서도 정확도가 높은 반면 LocationManger에서는 GPS Provider를 이용해서 약간 정확도가 떨어지는 결과를 보여주고 있습니다. 마지막으로 Fused Location Provider API는 Geolocation API와 같이 정확도 높은 결과를 보여주고 있습니다.

result

Google Play 서비스의 Fused Location Provider API을 이용해서 현재위치 측위를 간단히 소개하였습니다. Fused Location Provider API는 복잡한 계산이나 세부적인 요소들을 구글의 서비스에서 알아서 처리해주기 때문에 LocationManager에 비해 복잡한 구현없이 정확도 높은 결과를 위치를 측위할 수 있었습니다. 그리고 본문에서 간단히 소개한 Google Play 서비스는 구글에서 제공하는 다양한 서비스를 통합관리되고 있기 때문에 LocationService 이외에도 다양한 서비스들을 간편한 API 형태로 제공하고 있기 때문에 기회가 된다면 참고해 보는것도 많은 도움이 될것 같습니다.

 

 

참고자료 :

– Android Develop – Google Play Services : https://developer.android.com/google/play-services/index.html

– Android Develop – Google Play Services Reference : https://developer.android.com/google/play-services/index.html

 

잃어버린 내 스마트폰은 어디에? 구글 검색으로!

돌아서면 뭔가 잃어버리는 당신! 어디에 뒀는지 모르는 스마트폰을 찾느라 소비하는 시간이 아깝다면 꼭 읽어보세요! 아이폰은 icloud.com 에서 폰찾기 기능을 선택해야 하지만, 안드로이드 폰 유저라면 간단히 크롬 브라우저에서 “Find my phone(내 폰 찾기)”를 검색하기만 하면, 당신의 스마트폰의 위치를 확인하고 벨이 울리게 할 수 있습니다.

Google

단, 초기 로그인이 필요합니다. 바로 지도가 뜨지 않는다면, 검색결과 중 “Android Device Manager”를 선택하고, 위치정보 이용약관에 동의하세요~!

find_my_phone_-_Google_검색

그러면, 아래와 같이 현재 내 스마트폰의 위치, 벨울리기/잠금/초기화 옵션이 있는 지도가 나타납니다. 스마트폰을 분실한 경우, 잠금 or 초기화 옵션을 사용해서 누군가가 분실된 내 스마트폰의 카톡이나 페이스북 등의 계정을 도용하는 것을 방지할 수 있습니다.

150417_findphone_2

혹은, 벨 울리기 버튼을 통해 우리집 어딘가에 숨어있을 스마트폰의 위치를 찾아보세요~!

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) 기술 동향

 

2015년 4월 1일, 이번 만우절의 Google Maps에서는 무슨일이?

4월 1일, Happy April Fool’s Day! 만우절입니다.
작년 구글에서는 지도 위의 포켓몬 151마리를 최초로 잡는 사람에게 구글 입사의 기회를 준다며 많은 취준생들의 마음을 들었다 놨었는데요, 올해 만우절은 어떻게 놀라게할까요?
구글지도에서 왼쪽 하단의 팩맨(Pac-Man) 게임 아이콘을 클릭하시면, READY! 버튼이 나타납니다.

foolsday_googlemaps

클릭했을 때, 저같은 경우에는 아래와 같은 메시지가 나타났는데요, 걱정마시고 “I’m feeling lucky”버튼을 누르시면 게임 플레이가 가능한 곳으로 지도가 이동하게 됩니다.

foolsday_googlemaps(2)

그리고, 왼쪽 메뉴얼에 따라 게임을 즐겨보세요~! 상하좌우 키보드를 활용해 팩맨(Pac-Man)을 움직일 수 있고, 고스트를 피해 파워 쿠키를 다 먹어치우는 게임입니다. 어렵지 않아요 :)

foolsday_googlemaps(3)

딱 오늘(2015.04.01)만 즐길 수 있으니, 놓치지 마세요~!

>> 구글지도 바로가기