Android: requestLocationUpdates обновляет местоположение не чаще, чем каждые 45 секунд - PullRequest
23 голосов
/ 01 марта 2012

Фон

Я пишу приложение для Android, основной функцией которого является отслеживание местоположения пользователя и оповещение, когда пользователь приближается к некоторой точке.Поэтому мне нужно регулярно обновлять местоположение пользователя, и эти интервалы должны уменьшаться по мере приближения пользователя к цели.Поэтому, когда пользователь находится, скажем, в 1 км от цели, я хочу, чтобы местоположение обновлялось каждые 20 секунд и т. Д., Пока пользователь не прибудет.

Проблема

Когда я проверяюэто (provider = LocationManager.NETWORK_PROVIDER), вызов requestLocationUpdates(provider, minTime, minDistance, locationListener) с любым minTime < 45000 имеет тот же эффект, что и minTime = 45000, т.е. я получаю обновления с интервалом точно 45 секунд.
Я знаюпараметр минимального времени - это только «подсказка», но мое приложение не воспринимает его как подсказку.Я получаю обновления с указанным интервалом, пока этот интервал не пройдет ниже 45 секунд.Кажется, что минимальное время в 45 секунд между обновлениями местоположения жестко закодировано в Android, но это было бы странно.Кроме того, я никогда не слышал об этой проблеме раньше, и я не смог найти ее здесь в Stackoverflow.

Поскольку я не могу получать частые обновления, мой способ (на данный момент) заключается в том, чтобы вручную вызватьrequestLocationUpdates всякий раз, когда требуется новое местоположение, а затем просто используйте первое доступное местоположение.Чтобы сделать это с небольшими интервалами, я использую handler.postDelayed(myRunnable, updateInterval) для задержки вызовов, а myRunnable затем отвечает за вызов requestLocationUpdates.Тем не менее, этот метод работает только в 50 (очевидно, случайный) процент времени.

Кто-нибудь знает о проблеме, и есть ли способ ее исправить?Или мой единственный вариант установить minTime = 0 и просто надеяться на лучшее?

Исходный код

Вот исходный код для myRunnable, чей run() метод я регулярно вызываю с помощью 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.
}


А вот и мой 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;
            }
        }
    };


Дополнительная информация

вся служба обновления местоположения работает в службе.

Я прочитал документ несколько раз, Google решил проблему и попробовал различные другие обходные пути.Ничто не делает этого.

Я вычеркнул эту чертову штуку, и единственная захватывающая вещь, которую стоит увидеть - это большой жирный "игнорирование" моих частых запросов на определение местоположения.Вызываются все правильные методы.

Любая помощь будет очень оценена!

Ответы [ 3 ]

18 голосов
/ 20 февраля 2013

Вы совершенно правы, минимальное время 45 секунд затенено в Android.

Это похоже на исходный код класса NetworkLocationProvider, когда он еще был в ядре Android:

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

Посмотрите на переменную:

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

И метод:

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

Теперь NetworkLocationProvider вышел из ядра Android, вы можете найти его в NetworkLocation.apk в / system / app

Вы можете найти объяснение, почему это не в ядре здесь:

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

Но 45 секунд минимальное время, кажется, все ещетам.Посмотрите на эту декомпиляцию 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

Как вы можете догадаться, если вы конвертируете 0xafc8 в десятичное число, вы получите 45000 миллисекунд

Я не нашелобъяснение почему 45 секунд.Я полагаю, что будут причины, например, избегать перегрузки служб или других целей, которые им не нужны.

На самом деле, для Geolocation API существует ограничение в 100 запросов:

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

Но они, похоже, не соблюдают это правило в приложении Google Maps.Если вы откроете его, и у вас будет только активное сетевое местоположение, вы можете заметить, что ваше местоположение обновляется гораздо чаще, чем за 45 секунд.

Я заметил, что эта строка подозрительно часто (33 раза в секунду) в logcat, когда Google Maps открыт:

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

Я полагаю, что Google Maps также снова вызывает removeUpdates () и requestLocationUpdates () для получения новой позиции.

Так что я думаю, что нет решения, и это лучшее, что вы можете сделать, если вы хотите получить сетевые местоположения более чем за 45 секунд.

7 голосов
/ 02 марта 2012

Вы можете установить minTime на любое значение. Однако вы получите обновление только после того, как будет доступно новое местоположение. Сеть обновляется каждые 45 секунд или около того на каждом моем телефоне. Похоже, что это ограничение поставщика сети. Если вы хотите более частые обновления, используйте поставщика GPS. В зависимости от аппаратного обеспечения GPS максимальная частота обновления должна составлять около 4 Гц.

0 голосов
/ 18 апреля 2017

У меня была похожая проблема.Я положил вызов на locationManager.requestSingleUpdate() в конце onLocationChanged(), и он заставил вернуться к обновлениям.Вы можете установить команду задержки и затем выполнить requestSingleUpdate, убедившись, что зарегистрировали locationListener.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...