2013-08-21 2 views
1

J'ai un service qui a besoin de connaître l'emplacement du téléphone. Les principales activités du service sont réalisées dans un fil comme suit (avec des trucs de traitement enlevé:Localisation finder en service bloqué par sémaphore?

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 

La mise en œuvre de la classe LocationFinder (encore une fois, un peu simplifiée):

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; 
} 
} 

Mon problème est que la La routine onLocationChanged n'est pas appelée, même si je sais qu'il y a de nouvelles lectures.Par exemple, lorsque je suis configuré pour lire en mode passif, je lance Waze et je me vois en mouvement.Est-il possible que l'appel à onLocationChanged soit bloqué par le sémaphore? Comment puis-je contourner cela? Je veux être en mesure de modifier les paramètres pour requestLocationUpdate dynamiquement.

Répondre

1

Je pense que l'obtention d'un badge tumbleweed est un honneur très douteux, mais voici la réponse: Oui, l'appel .acquire() bloque le thread, et la méthode onLocationChanged() n'est pas appelée.

La solution est d'avoir un gestionnaire exécuter un exécutable, comme:

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

Runnable locationRun = new Runnable() { 

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

Le principe général est que vous envoyez et gérer les événements, plutôt que de courir une boucle d'interrogation . Si vous devez gérer un non-événement, par ex. aucun nouvel emplacement lu, puis vous définissez un compte à rebours.