Получение количества спутников, используемых в исправлении GPS с Android

Я пытаюсь получить количество спутников, используемых в исправлении GPS. Я реализовал два разных метода, как показано ниже:

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

}

Ни одно из событий прослушивателя (onGpsStatusChanged и onLocationChanged) никогда не срабатывает, хотя на моем телефоне включен автономный GPS. У меня есть набор разрешений ACCESS_FINE_LOCATION:

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

Я загрузил стороннее приложение под названием GPS Status, и оно смогло правильно отображать количество спутников, поэтому я знаю, что это не проблема с моим Droid X2.

Любые идеи?


person Justin    schedule 14.05.2012    source источник


Ответы (4)


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

Должно быть

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
person techiServices    schedule 14.05.2012
comment
Некоторым это помогло со вторым подходом, теперь запускается событие onLocationChanged, однако в его местоположении всегда 0 спутников. GetExtras (). GetInt (satellites) - person Justin; 14.05.2012
comment
В итоге это сработало ... Я думал, что пробовал два разных метода, но оказалось, что мне нужны оба, чтобы они работали! - person Justin; 14.05.2012

Вот код, который в итоге заработал.

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

}
person Justin    schedule 14.05.2012
comment
Почему вы закомментировали заявление if(sat.usedInFix())? Я бы не комментировал эту строку, если вы хотите, чтобы ваш счетчик совпадал с количеством спутников, которые фактически использовались в самом последнем исправлении. - person John R.B. Palmer; 04.03.2013

Если вы не можете получить количество спутников с помощью GPS_EVENT_SATELLITE_STATUS, тогда вы можете реализовать свою активность NmeaListener.

Если вы реализуете NmeaListener, вам нужно будет проанализировать строку сообщения, полученную в onNmeaReceived, чтобы извлечь количество спутников. Форматы NMEA описаны здесь. Затем вы можете выполнить поиск в Google по запросу "Java" + "анализатор NMEA".

person NickT    schedule 14.05.2012
comment
Мне трудно поверить, что мне приходится вручную анализировать данные NMEA только для того, чтобы получить количество спутников. Первый метод также обрабатывает событие GPS_EVENT_FIRST_FIX, он должен быть запущен. Кроме того, вы не упомянули второй метод, который должен запускаться при смене местоположения ... - person Justin; 14.05.2012
comment
Хм, я почти уверен, что когда мой телефон запускал Gingerbread, он всегда возвращал 0 спутников. Теперь его запущенная ICS. Я ДЕЙСТВИТЕЛЬНО вижу количество спутников в GPS_EVENT_SATELLITE_STATUS. Отредактирую свой ответ. - person NickT; 14.05.2012
comment
Мой Sony Ericsson Xperia Pro с Gingerbread 2.3.4 также возвращает 0 спутников. Анализ данных NMEA тоже не помогает (также 0 качества) и основан на stackoverflow.com/questions/587441/ кажется, что NMEA ненадежен, и мне придется выберите конкретный двоичный формат устройства GPS. - person Piovezan; 15.05.2013

Я заставил его работать, выполнив следующий код. locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocationUpdateHandler()); int nSatellites = location.getExtras().getInt("satellites", -1);

Было обнаружено, что nSatellites> 0, когда я начал получать исправления (onLocationChanged обратные вызовы).

person notytony    schedule 12.06.2014