Android: requestLocationUpdates aktualizuje lokalizację co najwyżej co 45 sekund

Tło

Piszę aplikację na Androida, której główną funkcją jest śledzenie lokalizacji użytkownika i powiadamianie, gdy użytkownik zbliży się do jakiegoś punktu. Dlatego muszę aktualizować lokalizację użytkownika w regularnych odstępach czasu, a interwały te powinny się zmniejszać, gdy użytkownik zbliża się do celu. Więc kiedy użytkownik znajduje się w odległości, powiedzmy, 1 km od celu, chcę, aby lokalizacja była aktualizowana co 20 sekund i tak dalej, dopóki użytkownik nie dotrze.

Problem

Kiedy test it (provider = LocationManager.NETWORK_PROVIDER), wywołanie requestLocationUpdates(provider, minTime, minDistance, locationListener) z dowolnym minTime < 45000 ma taki sam efekt jak minTime = 45000, tzn. dostaję aktualizacje z interwałem dokładnie 45 sekund.
Wiem, że minimalny parametr czasu to tylko "podpowiedź", ale nie jest traktowany jako podpowiedź przez moją aplikację. Dostaję aktualizacje z określonym interwałem, dopóki ten interwał nie przejdzie poniżej 45 sekund. Wydaje się, że minimalny czas 45 sekund między aktualizacjami lokalizacji jest zakodowany na twardo w Androidzie, ale to byłoby trochę dziwne. Poza tym nigdy o tym nie słyszałem. problem wcześniej i nie udało mi się znaleźć go tutaj na Stackoverflow.

Ponieważ nie jestem w stanie uzyskać częstych aktualizacji, moim obejściem (na razie) jest ręczne wywołanie requestLocationUpdates, gdy potrzebna jest nowa lokalizacja, a następnie użycie pierwszej dostępnej lokalizacji. Aby to zrobić w małych odstępach czasu używam handler.postDelayed(myRunnable, updateInterval), aby opóźnić połączenia, a myRunnable następnie zajmuje się wywołaniem requestLocationUpdates. Jednak ta metoda działa tylko około 50 (pozornie przypadkowych) procent czasu.

Czy ktoś wie problemu i czy jest jakiś sposób, aby go naprawić? Czy tylko ja mogę ustawić minTime = 0 i mieć nadzieję na najlepsze?

Kod źródłowy

Oto kod źródłowy myRunnable, którego run() metodę regularnie wywołuję ręcznie za pomocą handler.postDelayed(myRunnable, updateInterval):

public class MyRunnable implements Runnable {
    private LocationManager manager;
    private LocationListener listener;

    @Override
    public void run() {
        // This is called everytime a new update is requested
        // so that only one request is running at a time.
        removeUpdates();

        manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        listener = new LocationListener() {
            @Override
            public void onLocationChanged(Location loc) {
                location = loc;
                latitude = loc.getLatitude();
                longitude = loc.getLongitude();
                accuracy = Math.round(loc.getAccuracy());

                handler.sendMessage(Message.obtain(handler, KEY_MESSAGE_LOCATION_CHANGED));

                checkForArrival();
            }

            // Other overrides are empty.
        };

        if(!arrived)
            manager.requestLocationUpdates(provider, updateInterval, 0, listener);
    }

    /**
     * Removes location updates from the LocationListener.
     */
    public void removeUpdates() {
        if(!(manager == null || listener == null))
            manager.removeUpdates(listener);
    }

    // Another method for "cleaning up" when the user has arrived.
}


A oto moje handler:

handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
            case KEY_MESSAGE_LOCATION_CHANGED:
                if(myRunnable != null) {
                    myRunnable.removeUpdates();
                    handler.postDelayed(myRunnable, updateInterval);
                }
                break;
            }
        }
    };


Dodatkowe informacje

Cała aktualizacja lokalizacji działa w usłudze.

Przeczytałem doc kilka razy, Wygooglowałem problem i próbowałem różne inne obejścia. Nic tak nie robi.

Wylogowałem się z tego, a jedyną ekscytującą rzeczą, którą można zobaczyć, jest duże "ignorowanie" moich częstych próśb o lokalizację. Wszystkie właściwe metody są wywoływane.

Każda pomoc będzie bardzo doceniana!

Author: stemadsen, 2012-03-01

3 answers

Możesz ustawić minTime na dowolną wartość. Aktualizacja będzie jednak dostępna dopiero po udostępnieniu nowej lokalizacji. Sieć aktualizuje się tylko co 45 sekund na każdym telefonie, który posiadam. Wydaje się, że jest to ograniczenie dostawcy sieci. Jeśli chcesz częstszych aktualizacji użyj dostawcy GPS. W zależności od sprzętu GPS powinieneś uzyskać maksymalną szybkość aktualizacji około 4Hz.

 7
Author: Frohnzie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-02 03:25:32

Masz całkowitą rację, minimalny czas 45 sekund jest harcoded w Androidzie.

To wygląda na kod źródłowy klasy NetworkLocationProvider, kiedy był jeszcze w core Androida:]}

Http://www.netmite.com/android/mydroid/frameworks/base/location/java/com/android/internal/location/NetworkLocationProvider.java

Spójrz na zmienną:

private static final long MIN_TIME_BETWEEN_WIFI_REPORTS = 45 * 1000; // 45 seconds

I metoda:

@Override
public void setMinTime(long minTime) {
    if (minTime < MIN_TIME_BETWEEN_WIFI_REPORTS) {
        mWifiScanFrequency = MIN_TIME_BETWEEN_WIFI_REPORTS;
    } else {
        mWifiScanFrequency = minTime;
    }
    super.setMinTime(minTime);
}

Teraz NetworkLocationProvider jest poza rdzeniem Androida, można go znaleźć w sieci.apk in / system / app

Możesz znaleźć wyjaśnienie, dlaczego jest poza rdzeniem tutaj:

Https://groups.google.com/forum/?fromgroups=#! topic / android-platform / 10yr0r2myga

/ Align = "left" / Spójrz na dekompilację NetworkProvider:

Http://android.fjfalcon.com/xt720/miui-trans/apk-decompiled/NetworkLocation/smali/com/google/android/location/NetworkLocationProvider.smali

.line 149
const-wide/32 v4, 0xafc8

iput-wide v4, p0, Lcom/google/android/location/NetworkLocationProvider;->mWifiScanFrequency:J

Jako możesz się domyślić, jeśli przekonwertujesz 0xafc8 na dziesiętny, otrzymasz 45000 milisekund

Nie znalazłem wyjaśnienia dlaczego 45 sekund. Przypuszczam, że będą powody, takie jak unikanie przeciążenia usług lub innych zastosowań, których nie chcą. W rzeczywistości API geolokalizacyjne ma limit 100 zapytań:

Https://developers.google.com/maps/documentation/business/geolocation/#usage_limits

Ale wydaje się, że nie przestrzegają tej zasady w aplikacji Google Maps. Jeśli otwórz go i tylko aktywna lokalizacja sieciowa możesz zauważyć, że lokalizacja yout jest aktualizowana znacznie częściej niż 45 sekund.

Zauważyłem ten wiersz podejrzanie często (33 razy na sekundę) w logcat, gdy Google Maps jest otwarty:

02-20 17:12:08.204: V / LocationManagerService( 1733): getAllProviders

Myślę, że Google Maps ponownie wywołuje removeUpdates() i requestLocationUpdates (), aby uzyskać nową pozycję.

Więc myślę, że nie ma rozwiązania i to jest najlepsze możesz to zrobić, jeśli chcesz uzyskać lokalizacje sieciowe w ciągu 45 sekund.

 18
Author: djpeinado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-21 08:45:31

Miałem podobny problem. Wywołałem locationManager.requestSingleUpdate() na końcu onLocationChanged() i wymusiło to powrót do aktualizacji. Możesz ustawić polecenie delay, a następnie wykonać requestSingleUpdate, upewniając się, że zawiera locationListener.

[4]}próbowałem stworzyć zegar GPS, ale aktualizacje były niespójne aktualizowanie gdziekolwiek od 1-5 sekund lub tak. ale to może zadziałać dla innej aplikacji.
 0
Author: rznazn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-19 00:45:36