본문 바로가기

공부/안드로이드

내 위치 측정할 때 프로바이더 전환..

네이버맵이나 올레네비같은 경우는..


실행하면 무조껀 GPS 프로바이더로 요청을 해서 신호가 잡힐때까지 대기한다.


그리고 GPS가 잡히기 전엔 네트워크 프로바이더로 얻은 좌표를 뿌려주는듯 하다.


전엔.. 최초에 GPS 프로바이더로 요청을 하고 타임아웃을 걸어서 일정시간내에 위치정보가 수신되지 않으면 


네트워크 프로바이더로 전환하여 위치정보를 수신하도록 했었다.


이렇게 처리하면 문제점이.. 위치측위를 하는 로직이 완전 처음부터 시작하지 않는 이상에야 최초의 위치제공자를 전환할 수 없다는 것이다.


여기에서 위치제공자가 전환되어야 하는 경우는 실내 -> 실외, 또는 실외 -> 실내의 경우가 될 것이다.


네이버 지도나 올레네비와 같은 방식으로 처리를 하려면 하나의 LocationManager에 각각의 위치제공자에 대한 LocationListener를 달아서 처리를 해주면 된다. 


GPS는 GPS대로 측위를 할 것이고, NETWORK는 NETWORK 대로 측위를 한다. 


GPS의 리스너쪽에 플래그를 두어서 위치정보가 수신되지 않을 경우를 체크하여 NETWORK 쪽에서 처리를 해주면 된다.


여기에서 또 한가지 문제가 발생하는데..


실내에서는 어차피 GPS로 신호를 받지 못하기 때문에 최초에 GPS 위치정보가 떨어질 때 플래그를 체크하면 실외로 나갔다는것을 알 수 있다.


하지만 실외에서 실내로 들어왔을 땐..... 위치정보가 떨어지지 않기 때문에 LocationListener의 onLocationChanged가 호출되지 않아서 상태변화를 체크할 수 있는 방법이 없는것 같다.(LocationListener의 onProviderEnabled나 onProviderDisabled는 유저에 의해서 GPS가 on, off 된것을 체크하고  onStatusChanged는 수신가능한 위성의 수가 바뀔 때 호출되는듯 하다. GpsStatus의 listener를 사용해보려고도 했으나 fail)


결국 가장 최근에 수신한 GPS 위치정보의 생성시간이 네트워크 위치정보의 생성시간과 일정시간 이상 차이가 난다면 GPS로 위치수신이 불가하다고 판단 -> 네트워크 프로바이더로 수신한 위치정보를 사용하도록 처리하면 될것 같다.


테스트는 아직 해보지 않았는데 방금 대충 발로 짠 소스를 첨부...


시간날때 테스트 해보고 수정해서 다시 올려야겠다...




1
package com.kimdh.exam; 2 3 import android.app.Activity; 4 import android.content.Context; 5 import android.location.Location; 6 import android.location.LocationListener; 7 import android.location.LocationManager; 8 import android.os.Bundle; 9 10 public class GpsTest extends Activity { 11 private LocationManager mLocMan; 12 private boolean isGpsReceived; 13 /** Called when the activity is first created. */ 14 @Override 15 public void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.main); 18 isGpsReceived = false; 19 mLocMan = (LocationManager)getSystemService(Context.LOCATION_SERVICE); 20 } 21 22 public void onPause(){ 23 super.onPause(); 24 mLocMan.removeUpdates(gpsListener); 25 mLocMan.removeUpdates(netListener); 26 } 27 28 public void onResume(){ 29 super.onResume(); 30  mLocMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 10, gpsListener);

31  mLocMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 10, netListener);

32 } 33 34 public void updateWithNewLocation(Location location, String provider){ 35 // 여기에서 처리를 해준다. 36 // provider 값으로 location이 어떤 provider에서 들어왔는지 알 수 있다. 37 Location loc; // 최종적으로 확정된 위치정보가 저장 될 객체 38 if(isGpsReceived) { // gps 수신여부 체크 39 if(LocationManager.GPS_PROVIDER.equals(provider)) { 40 loc = location; // gps 위치정보 41 } else { 42 long gpsGenTime = mLocMan.getLastKnownLocation(LocationManager.GPS_PROVIDER).getTime(); // 마지막으로 수신된 GPS 위치정보 43 long curTime = System.currentTimeMillis(); // 현재 시간 44 if((curTime-gpsGenTime) > 20000){ // gps 정보가 20초 이상 오래된 정보이면 네트워크 위치정보 사용 45 loc = location; 46 isGpsReceived = false; // 플래그를 해제 47 } 48 } 49 } else { 50 loc = location; // 네트워크 위치정보 51 } 52 } 53 54 LocationListener gpsListener = new LocationListener() { 55 @Override 56 public void onStatusChanged(String provider, int status, Bundle extras) { 57 58 } 59 @Override 60 public void onProviderEnabled(String provider) { 61 62 } 63 @Override 64 public void onProviderDisabled(String provider) { 65 66 } 67 @Override 68 public void onLocationChanged(Location location) { 69 isGpsReceived = true; // gps 위치정보가 수신되면 플래그를 set 70 updateWithNewLocation(location, "gps"); 71 } 72 }; 73 74 LocationListener netListener = new LocationListener() { 75 @Override 76 public void onStatusChanged(String provider, int status, Bundle extras) { 77 78 } 79 @Override 80 public void onProviderEnabled(String provider) { 81 82 } 83 @Override 84 public void onProviderDisabled(String provider) { 85 86 } 87 @Override 88 public void onLocationChanged(Location location) { 89 updateWithNewLocation(location, "network"); 90 } 91 }; 92 }


반응형