2010年9月9日 星期四

Android: Get the GPS location with timeout

Android 要取得目前的位置, 除了在設定裡手動啟動 GPS定位外, 還要註冊 LocationListener 使得在位置更新能觸發 method: onLocationChanged().

GPS如果在室內收不到訊號時. 就不會觸發onLocationChanged(), 很多時候我們只要抓目前的位置去作後續的處理. 所以需要 timeout 機制以避免程式無限制的等下去. 因為gps持續運作會很耗電力.

但android 目前沒有timout的機制. 以下是一段加入timeout機制的例子. 其中呼叫 initGPS() 後程式同時啟動 GPS 與 network 兩種方式定位. 在timeout 時間內兩種定位都取得位置後程式回傳最優位置. 如果gps在時間內先取得定位 程式直接回傳最優位置. 如果timeout時間到還沒取得定位. 程式回傳 lastlocation.

直接copy貼上程式後面. 然後修改註記 '***********************'的地方就可以用了.



//----------------------Get the Best current location with timeout. By Sikazi-----------------------------------
//**********果要跳出程式時要強制關閉GPS定位,onDestroy()必須加入 stopAllUpdate()*********
private int TIMEOUT_SEC = 35;   //********* Timeout Sec *********************************
private boolean flagGetGPSDone = false;
private boolean flagNetworkDone = false;
private boolean flagGPSEnable = true;
private boolean flagNetworkEnable = true;
private LocationManager myLocationManager01;
private Location culocationGPS = null;
private Location culocationNetwork = null;
private Location bestLocation = null;
private Handler  handler = new Handler();
private int counts = 0;

private Runnable showTime = new Runnable() {
    public void run() {
     counts++;
     // Timeout Sec, 超過TIMEOUT設定時間後,直接設定FLAG使得getCurrentLocation抓取    lastlocation.
     if( counts > TIMEOUT_SEC ){
     flagGetGPSDone = true;
     flagNetworkDone = true;
     }        
     bestLocation = getCurrentLocation();
    
     if (bestLocation == null){
//如果 bestLocation == null 表示未取得最新位置, 繼續等待 continue wait......
     handler.postDelayed(this, 1000);
     }else{
     //***********已經取得最佳位置呼叫 下一步, Job Done, Call next Step******************    
nextStep(bestLocation );
     //****************************************************************************************
     }
    }
};

private void initGPS(){
myLocationManager01 = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
startAllUpdate();
handler.postDelayed(showTime, 1000);

flagGPSEnable = myLocationManager01.isProviderEnabled("gps");
flagNetworkEnable = myLocationManager01.isProviderEnabled("network");
if(!flagGPSEnable){
flagGetGPSDone = true;
}else{
flagGetGPSDone = false;
}
if(!flagNetworkEnable){
flagNetworkDone = true;
}else{
flagNetworkDone = false;
}
bestLocation = null;
counts = 0;
}  

//Turn on the  GPS NETWORK update
public void startAllUpdate(){
myLocationManager01.requestLocationUpdates("gps", 0, 0, mLocationListener01);
myLocationManager01.requestLocationUpdates("network", 0, 0, mLocationListener02);
}

//Turn of  GPS NETWORK update
public void stopAllUpdate(){
myLocationManager01.removeUpdates(mLocationListener01);
myLocationManager01.removeUpdates(mLocationListener02);
}
public final LocationListener mLocationListener01 = new LocationListener(){
    public void onLocationChanged(Location location){
     OnGPSChange();
    }
    public void onProviderDisabled(String provider){}
    public void onProviderEnabled(String provider){}
    public void onStatusChanged(String provider, int status, Bundle extras){}
};

public final LocationListener mLocationListener02 = new LocationListener(){
    public void onLocationChanged(Location location){
     OnNetworkChange();
    }
    public void onProviderDisabled(String provider){}
    public void onProviderEnabled(String provider){}
    public void onStatusChanged(String provider, int status, Bundle extras){}
};

private void OnGPSChange(){
//GPS 比 NETWORK 準 所以GPS定位到後 關掉全部定位
flagGetGPSDone = true;
flagNetworkDone = true;
stopAllUpdate();
}

private void OnNetworkChange(){
flagNetworkDone = true;
myLocationManager01.removeUpdates(mLocationListener02);
}

private Location getCurrentLocation(){
Location retLocation = null;
if ((flagGetGPSDone==true && flagNetworkDone==true)){
culocationGPS = myLocationManager01.getLastKnownLocation("gps");
culocationNetwork = myLocationManager01.getLastKnownLocation("network");
if (culocationGPS == null && culocationNetwork == null){
retLocation = myLocationManager01.getLastKnownLocation("passive");
if(retLocation == null){
retLocation = new Location("passive");
}
}else{
//culocationGPS有沒有比culocationNetwork 好
if( new LocationUtility().isBetterLocation(culocationGPS,culocationNetwork)){
retLocation = culocationGPS;
}else{
retLocation = culocationNetwork;
}
}
//取得最佳LOCATION后 停止所有定位
stopAllUpdate();
}
return retLocation;
}

沒有留言:

張貼留言