2013-08-21 59 views
1

我有需要知道手機位置的服務。該服務的主要活動是在一個線程中進行如下(與處理的東西去掉:服務中的位置查找器被信號量阻塞?

Semaphore locationAcquired = new Semaphore(1); 
LocationFinder finder; 

... 
public void run() { 
      delaySeconds = 60; 
      Looper.prepare(); 
      while (true) { 
       try { 

        finder.StartFinder(); 

       locationAcquired.acquire(); 
       // do some stuff... 
       } catch (InterruptedException e) { 
        if (isDestroy) { 
         Log.d(TAG, "Closing Monitor Thread"); 
         break; 
        } // else just wake up and process the location 
       } catch (Exception e) { 
        e.printStackTrace(); 

       } 
      } // end while 
     } // end run 

的LocationFinder類實現(再次聲明,略有簡化):

package com.ksdagile.opengate; 

import... 

public class LocationFinder { 

public static final int ONE_SECOND = 1000; 

LocationListener locationListener; 
String provider = LocationManager.PASSIVE_PROVIDER; // passive by default 
LocationManager locationManager; 
public Location currentLocation; 
long updateSeconds; 
private boolean isLooking = false; 
OpenGateService openGateService; 

public LocationFinder(LocationManager _lm, OpenGateService _openGateService) { 

    openGateService = _openGateService; 
    locationManager = _lm; 
    // initialize with whatever location might be available 
    currentLocation = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER); 


    locationListener = new LocationListener() { 
     @Override 
     public void onLocationChanged(Location location) { 
      // A new location update is received. Do something useful with it. In this case, 
      // we're sending the update to a handler which then updates the UI with the new 
      // location. 
      currentLocation = location; 
      String newLoc = String.format("Found new Location lat:%.2f long:%.2f", currentLocation.getLatitude(), currentLocation.getLongitude()); 
      Log.d(getClass().getName(), newLoc); 
      openGateService.locationAcquired.release(); 
     } 
        // simple implementations of onProvider<> etc. 
    }; 

} 

public void SetProvider(boolean isActive) { 
    if (isActive) 
     provider = LocationManager.GPS_PROVIDER; 
    else 
     provider = LocationManager.PASSIVE_PROVIDER; 
} 

public void SetFrequency(long delay) { 
    updateSeconds = delay; 
} 

public void StartFinder() { 
    if (!isLooking) { 
     isLooking = true; 
     locationManager.requestLocationUpdates(provider, updateSeconds*ONE_SECOND, 10, locationListener); 
     Log.d(getClass().getName(), String.format("Request location from %s provider, every %d sec.", provider, updateSeconds));    
    } else 
     Log.d(getClass().getName(), "Location request running"); 
} 

public void StopFinder() { 
    locationManager.removeUpdates(locationListener); 
    isLooking = false; 
} 

public boolean IsLocating() { 
    return isLooking; 
} 
} 

我的問題是, onLocationChanged例程不會被調用,即使我知道有新的讀數,例如,當被配置爲以被動模式讀取時,我運行Waze並看到自己正在移動。onLocationChanged的調用是否被信號量阻塞了?如果是這樣,我該如何解決這個問題?我希望能夠動態地更改requestLocationUpdate的參數。

回答

1

我認爲得到一個風滾草徽章是一個非常可疑的榮譽,但這裏是答案: 是的,.acquire()調用阻塞線程,並且onLocationChanged()方法不被調用。

解決的辦法是有一個處理器運行一個可運行的,如:

public void onLocationChanged(Location location) { 
      xxxService.locHandler.post(xxxService.locationRun); 
     } 

其中

Runnable locationRun = new Runnable() { 

    @Override 
    public void run() { 
     // handle stuff for new location 
    } 
}; 

總的原則是,你發送和處理事件,而不是運行一個輪詢循環。如果您需要處理非事件,例如沒有新的位置讀取,然後你設置了倒數計時器。