2012-05-14 5 views
5

Sto cercando di recuperare il numero di satelliti utilizzati nella correzione GPS. Ho implementato due metodi diversi, come illustrato di seguito:Recupero di # satelliti utilizzati nella correzione GPS da Android

package ti.utils; 

import android.app.Activity; 
import android.content.Context; 
import android.location.GpsSatellite; 
import android.location.GpsStatus; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Bundle; 

public class Gps { 

    private static final int TWO_MINUTES = 1000 * 60 * 2; 
    private static Location Location; 
    public static int Satellites = -1; 

    public static void StartTracking(Activity activity) 
    { 
     final LocationManager locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE); 

     //listen for gps status changes. 
     GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() { 
      public void onGpsStatusChanged(int event) { 
       Log("In onGpsStatusChanged event: " + event); 
       if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS || event == GpsStatus.GPS_EVENT_FIRST_FIX) { 
        GpsStatus status = locationManager.getGpsStatus(null); 
        Iterable<GpsSatellite> sats = status.getSatellites(); 
        // Check number of satellites in list to determine fix state 
        Satellites = 0; 
        for (GpsSatellite sat : sats) { 
         //if(sat.usedInFix()) 
         Satellites++; 
        } 
        Log("Setting Satellites from GpsStatusListener: " + Satellites); 
       } 
      } 
     }; 
     locationManager.addGpsStatusListener(gpsStatusListener); 

     //listen for location changes. 
     LocationListener locationListener = new LocationListener() { 
      public void onLocationChanged(Location location) { 
       // Called when a new location is found by the network location provider. 
       try 
       { 
        Log("Location changed! Speed = " + location.getSpeed() + " & Satellites = " + location.getExtras().getInt("satellites")); 
        boolean isBetter = isBetterLocation(location, Location); 
        if(isBetter) 
        { 
         Log("Set to new location"); 
         Location = location; 
         Satellites = location.getExtras().getInt("satellites"); 
         Log("Setting Satellites from LocationListener: " + Satellites); 
        } 
       } 
       catch(Exception exc) 
       { 
        Log(exc.getMessage()); 
       } 
      } 
      public void onStatusChanged(String provider, int status, Bundle extras) {} 
      public void onProviderEnabled(String provider) {} 
      public void onProviderDisabled(String provider) {} 
     }; 
     locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); 
    } 

    /** Determines whether one Location reading is better than the current Location fix 
     * @param location The new Location that you want to evaluate 
     * @param currentBestLocation The current Location fix, to which you want to compare the new one 
     */ 
    protected static boolean isBetterLocation(Location location, Location currentBestLocation) { 
     if (currentBestLocation == null) { 
      // A new location is always better than no location 
      return true; 
     } 

     // Check whether the new location fix is newer or older 
     long timeDelta = location.getTime() - currentBestLocation.getTime(); 
     boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; 
     boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; 
     boolean isNewer = timeDelta > 0; 

     // If it's been more than two minutes since the current location, use the new location 
     // because the user has likely moved 
     if (isSignificantlyNewer) { 
      return true; 
     // If the new location is more than two minutes older, it must be worse 
     } else if (isSignificantlyOlder) { 
      return false; 
     } 

     // Check whether the new location fix is more or less accurate 
     int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); 
     boolean isLessAccurate = accuracyDelta > 0; 
     boolean isMoreAccurate = accuracyDelta < 0; 
     boolean isSignificantlyLessAccurate = accuracyDelta > 200; 

     // Check if the old and new location are from the same provider 
     boolean isFromSameProvider = isSameProvider(location.getProvider(), 
       currentBestLocation.getProvider()); 

     // Determine location quality using a combination of timeliness and accuracy 
     if (isMoreAccurate) { 
      return true; 
     } else if (isNewer && !isLessAccurate) { 
      return true; 
     } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { 
      return true; 
     } 
     return false; 
    } 

    /** Checks whether two providers are the same */ 
    private static boolean isSameProvider(String provider1, String provider2) { 
     if (provider1 == null) { 
      return provider2 == null; 
     } 
     return provider1.equals(provider2); 
    } 

    private static void Log(String message) { 
     if(message != null && message.length() > 0) { 
      //android.util.Log.i(LCAT, message); 
      org.appcelerator.kroll.common.Log.i("SygicModule", message); 
     } 
    } 

} 

Nessuno dei due eventi ascoltatore (onGpsStatusChanged & onLocationChanged) mai il fuoco, anche se ho il GPS stand-alone abilitato sul mio telefono. Ho il set di autorizzazioni ACCESS_FINE_LOCATION:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 

Ho scaricato un'applicazione 3rd party chiamato Stato GPS ed è stato in grado di visualizzare correttamente il # dei satelliti, quindi so che non è un problema con il mio Droid X2.

Qualche idea?

risposta

3
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); 

Dovrebbe essere

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); 
+0

Questa aiutato alcuni con il secondo approccio, ora l'evento onLocationChanged è sparato, però ha sempre 0 satelliti nelle location.getExtras(). GetInt ("satelliti") – Justin

+0

Questo ha finito per lavorare ... Pensavo provando due metodi separati, ma risulta che avevo bisogno di entrambi per farlo funzionare! – Justin

+0

Sono contento che tu abbia funzionato;) – techiServices

0

Se non è possibile ottenere il numebr dei satelliti attraverso GPS_EVENT_SATELLITE_STATUS allora si potrebbe avete la vostra attività implementare NmeaListener.

Se si implementa NmeaListener, sarà necessario analizzare la stringa di messaggio ricevuta in onNmeaReceived per estrarre il numero di satelliti. I formati NMEA sono descritti here. Quindi ti potrebbe piacere fare una ricerca su Google per "Java" + "parser NMEA"

+0

Trovo difficile credere di dover analizzare manualmente i dati NMEA solo per recuperare il numero di satelliti. Il primo metodo gestisce anche l'evento GPS_EVENT_FIRST_FIX, questo dovrebbe essere attivato. Inoltre, non ha menzionato il secondo metodo, che dovrebbe essere licenziato sul cambiamento posizione ... – Justin

+0

Hmm, io sono abbastanza certo che quando il mio telefono ha Gingerbread, è sempre restituito 0 satelliti. Ora eseguendo ICS FARE, vedo i satelliti numerici in GPS_EVENT_SATELLITE_STATUS. Modificherò la mia risposta. – NickT

+0

Il mio Sony Ericsson Xperia Pro con Gingerbread 2.3.4 restituisce anche 0 satelliti. Analisi dei dati NMEA non aiuta (anche 0 qualità), e sulla base di http://stackoverflow.com/questions/587441/roll-your-own-nmea-parser-or-use-an-open-source- gps-parser sembra che NMEA sia inaffidabile e dovrò andare per il formato binario specifico del dispositivo GPS. – Piovezan

6

Ecco il codice che ha funzionato.

package ti.utils; 

import android.app.Activity; 
import android.content.Context; 
import android.location.GpsSatellite; 
import android.location.GpsStatus; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Bundle; 

public class Gps { 

    private static final int TWO_MINUTES = 1000 * 60 * 2; 
    private static Location Location; 
    public static int Satellites = -1; 

    public static void StartTracking(Activity activity) 
    { 
     final LocationManager locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE); 

     //listen for gps status changes. 
     GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() { 
      @Override 
      public void onGpsStatusChanged(int event) { 
       Log("In onGpsStatusChanged event: " + event); 
       if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS || event == GpsStatus.GPS_EVENT_FIRST_FIX) { 
        GpsStatus status = locationManager.getGpsStatus(null); 
        Iterable<GpsSatellite> sats = status.getSatellites(); 
        // Check number of satellites in list to determine fix state 
        Satellites = 0; 
        for (GpsSatellite sat : sats) { 
         //if(sat.usedInFix()) 
         Satellites++; 
        } 
        Log("Setting Satellites from GpsStatusListener: " + Satellites); 
       } 
      } 
     }; 
     locationManager.addGpsStatusListener(gpsStatusListener); 

     //listen for location changes. 
     LocationListener locationListener = new LocationListener() { 
      @Override 
      public void onLocationChanged(Location location) { 
       // Called when a new location is found by the network location provider. 
       /*try 
       { 
        Log("Location changed! Speed = " + location.getSpeed() + " & Satellites = " + location.getExtras().getInt("satellites")); 
        boolean isBetter = isBetterLocation(location, Location); 
        if(isBetter) 
        { 
         Log("Set to new location"); 
         Location = location; 
         Satellites = location.getExtras().getInt("satellites"); 
         Log("Setting Satellites from LocationListener: " + Satellites); 
        } 
       } 
       catch(Exception exc) 
       { 
        Log(exc.getMessage()); 
       }*/ 
      } 
      public void onStatusChanged(String provider, int status, Bundle extras) {} 
      public void onProviderEnabled(String provider) {} 
      public void onProviderDisabled(String provider) {} 
     }; 
     locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); 
    } 

    /** Determines whether one Location reading is better than the current Location fix 
     * @param location The new Location that you want to evaluate 
     * @param currentBestLocation The current Location fix, to which you want to compare the new one 
     */ 
    protected static boolean isBetterLocation(Location location, Location currentBestLocation) { 
     if (currentBestLocation == null) { 
      // A new location is always better than no location 
      return true; 
     } 

     // Check whether the new location fix is newer or older 
     long timeDelta = location.getTime() - currentBestLocation.getTime(); 
     boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; 
     boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; 
     boolean isNewer = timeDelta > 0; 

     // If it's been more than two minutes since the current location, use the new location 
     // because the user has likely moved 
     if (isSignificantlyNewer) { 
      return true; 
     // If the new location is more than two minutes older, it must be worse 
     } else if (isSignificantlyOlder) { 
      return false; 
     } 

     // Check whether the new location fix is more or less accurate 
     int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); 
     boolean isLessAccurate = accuracyDelta > 0; 
     boolean isMoreAccurate = accuracyDelta < 0; 
     boolean isSignificantlyLessAccurate = accuracyDelta > 200; 

     // Check if the old and new location are from the same provider 
     boolean isFromSameProvider = isSameProvider(location.getProvider(), 
       currentBestLocation.getProvider()); 

     // Determine location quality using a combination of timeliness and accuracy 
     if (isMoreAccurate) { 
      return true; 
     } else if (isNewer && !isLessAccurate) { 
      return true; 
     } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { 
      return true; 
     } 
     return false; 
    } 

    /** Checks whether two providers are the same */ 
    private static boolean isSameProvider(String provider1, String provider2) { 
     if (provider1 == null) { 
      return provider2 == null; 
     } 
     return provider1.equals(provider2); 
    } 

    private static void Log(String message) { 
     if(message != null && message.length() > 0) { 
      //android.util.Log.i(LCAT, message); 
      org.appcelerator.kroll.common.Log.i("UtilsModule", message); 
     } 
    } 

} 
+1

Perché hai l'istruzione 'if (sat.usedInFix())' commentata? Vorrei non commentare quella riga se vuoi che il tuo conteggio sia dei satelliti effettivamente usati nella correzione più recente. –

0

L'ho ottenuto lavorando seguendo il codice. locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocationUpdateHandler()); int nSatellites = location.getExtras().getInt("satellites", -1);

nSatellites è risultato essere> 0 una volta che ho iniziato a ricevere correzione (onLocationChanged callback).