Я ищу способ получать фоновое обновление местоположения каждые n минут в моем приложении iOS. Я использую iOS 4.3, и решение должно работать на не взломанных iPhone.
Я пробовал / рассматривал следующие варианты:
CLLocationManager startUpdatingLocation/startMonitoringSignificantLocationChanges
: Это работает в фоновом режиме, как и ожидалось, на основе настроенных свойств, но кажется невозможным принудительно обновлять местоположение каждые n минутNSTimer
: Работает, когда приложение работает на переднем плане, но, похоже, не предназначено для фоновых задач- Локальные уведомления. Локальные уведомления можно планировать каждые n минут, но невозможно выполнить какой-либо код для получения текущего местоположения (без необходимости запуска приложения через уведомление). Этот подход также не кажется чистым подходом, поскольку это не то, для чего должны использоваться уведомления.
UIApplication:beginBackgroundTaskWithExpirationHandler
Насколько я понимаю, это следует использовать для завершения некоторой работы в фоновом режиме (также ограниченной по времени), когда приложение перемещается в фоновый режим, а не для реализации «длительных» фоновых процессов.
Как я могу реализовать эти регулярные фоновые обновления местоположения?
Ответы:
Я нашел решение для реализации этого с помощью форумов разработчиков Apple:
location background mode
NSTimer
в фоновом режиме сUIApplication:beginBackgroundTaskWithExpirationHandler:
n
это меньше , чемUIApplication:backgroundTimeRemaining
он будет работать нормально. Когдаn
оно больше , егоlocation manager
следует снова включить (и отключить), прежде чем не останется времени, чтобы избежать уничтожения фоновой задачи.Это работает, потому что местоположение является одним из трех разрешенных типов фонового выполнения .
Примечание: я потерял некоторое время, протестировав это в симуляторе, где он не работает. Тем не менее, он отлично работает на моем телефоне.
источник
На iOS 8/9/10 для обновления фонового местоположения каждые 5 минут сделайте следующее:
Зайдите в Проект -> Возможности -> Фоновые режимы -> выберите Обновления местоположения
Перейдите в Project -> Info -> добавьте ключ NSLocationAlwaysUsageDescription с пустым значением (или, необязательно, любым текстом)
Чтобы ваше местоположение работало, когда ваше приложение находится в фоновом режиме, и отправляйте координаты в веб-службу или делайте что-нибудь с ними каждые 5 минут, реализуйте это, как показано в коде ниже.
Я не использую фоновые задачи или таймеры. Я тестировал этот код на своем устройстве с iOS 8.1, которое несколько часов лежало на моем столе, а приложение работало в фоновом режиме. Устройство было заблокировано, и код работал правильно все время.
источник
if ([self.locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) { [self.locationManager setAllowsBackgroundLocationUpdates:YES]; }
Я сделал это в приложении, которое я разрабатываю. Таймеры не работают, когда приложение находится в фоновом режиме, но приложение постоянно получает обновления местоположения. Я где-то прочитал в документации (я не могу найти ее сейчас, я опубликую обновление, когда я это сделаю), что метод может вызываться только в активном цикле выполнения, когда приложение находится в фоновом режиме. У делегата приложения есть активный цикл выполнения даже в bg, поэтому вам не нужно создавать свой собственный, чтобы это работало. [Я не уверен, что это правильное объяснение, но вот как я понял из того, что я прочитал]
Прежде всего, добавьте
location
объект для ключаUIBackgroundModes
в info.plist вашего приложения. Теперь вам нужно запустить обновление местоположения в любом месте вашего приложения:Затем напишите метод обработки обновлений местоположения, скажем
-(void)didUpdateToLocation:(CLLocation*)location
, в делегате приложения. Затем реализовать методlocationManager:didUpdateLocation:fromLocation
вCLLocationManagerDelegate
в классе , в котором вы начали менеджер местоположения (поскольку мы установили местонахождение менеджер делегат «я»). Внутри этого метода вам нужно проверить, истек ли временной интервал, после которого вам придется обрабатывать обновления местоположения. Вы можете сделать это, сохраняя текущее время каждый раз. Если это время истекло, вызовите метод UpdateLocation из вашего делегата приложения:Это будет вызывать ваш метод каждые 5 минут, даже если ваше приложение находится в фоновом режиме. Imp: эта реализация разряжает батарею, если точность данных о вашем местоположении не критична, вы должны использовать
[locationManager startMonitoringSignificantLocationChanges]
Перед добавлением этого в ваше приложение, пожалуйста, прочитайте Руководство по программированию для определения местоположения
источник
Теперь, когда iOS6 - лучший способ иметь постоянно работающие службы определения местоположения, это ...
Просто проверил это так:
Я запустил приложение, поехал на задний план и поехал на машине на несколько минут. Затем я иду домой на 1 час и снова начинаю двигаться (не открывая снова приложение). Места начались снова. Затем остановился на два часа и начал снова. Все снова хорошо ...
НЕ ЗАБУДЬТЕ ИСПОЛЬЗОВАТЬ новые сервисы определения местоположения в iOS6
источник
Для кого-то еще с кошмаром выяснить это. У меня есть простое решение.
Добавить таймер с помощью:
Только не забудьте добавить «Регистры приложений для обновлений местоположения» в info.plist.
источник
Вот что я использую:
Я запускаю отслеживание в AppDelegate следующим образом:
источник
К сожалению, все ваши предположения кажутся правильными, и я не думаю, что есть способ сделать это. В целях экономии заряда аккумулятора службы определения местоположения iPhone основаны на движении. Если телефон находится в одном месте, он невидим для служб определения местоположения.
CLLocationManager
Будет вызывать толькоlocationManager:didUpdateToLocation:fromLocation:
тогда, когда телефон получит обновление местоположения, что происходит только в том случае, если одна из трех служб определения местоположения (сотовая вышка, GPS, Wi-Fi) воспринимает изменение.Несколько других вещей, которые могли бы помочь сообщить дальнейшие решения:
Запуск и остановка служб вызывает
didUpdateToLocation
метод делегата, ноnewLocation
может иметь старую временную метку.Мониторинг региона может помочь
При работе в фоновом режиме помните, что может быть трудно получить «полную» поддержку LocationServices, одобренную Apple. Из того, что я видел, они специально разработаны
startMonitoringSignificantLocationChanges
как альтернатива с низким энергопотреблением для приложений, которым требуется фоновая поддержка местоположения, и настоятельно рекомендуют разработчикам использовать это, если приложение не нуждается в этом.Удачи!
ОБНОВЛЕНИЕ: Эти мысли могут быть устаревшими к настоящему времени. Похоже, что люди с успехом с ответом @wjans, выше.
источник
startMonitoringSignificantLocationChanges
не даст никаких обновлений в этом случае.Я написал приложение, используя службы определения местоположения, приложение должно отправлять местоположение каждые 10 секунд. И это сработало очень хорошо.
Просто используйте метод allowDeferredLocationUpdatesUntilTraveled: timeout , следуя документам Apple.
Что я сделал:
Необходимые: зарегистрируйте фоновый режим для обновления Location.
1. Создайте
LocationManger
иstartUpdatingLocation
, сaccuracy
иfilteredDistance
как угодно:2. Чтобы приложение работало вечно, используя
allowDeferredLocationUpdatesUntilTraveled:timeout
метод в фоновом режиме, необходимо перезапуститьupdatingLocation
новый параметр, когда приложение переходит в фоновый режим, например:3. Приложение получает обновленные местоположения как обычно с
locationManager:didUpdateLocations:
обратным вызовом:4. Но вы должны обрабатывать данные в
locationManager:didFinishDeferredUpdatesWithError:
обратном вызове для вашей цели5. ПРИМЕЧАНИЕ. Я думаю, что мы должны сбрасывать параметры
LocationManager
каждый раз, когда приложение переключается между фоновым режимом.источник
pausesLocationUpdatesAutomatically = true
диспетчер местоположений должен приостанавливать обновления, если, по-видимому, нет изменения местоположения (документ Apple ). Во всяком случае, я еще явно не тестировал случайlocation manager pauses updates
: D.pausesLocationUpdatesAutomatically = true
заставляет мое приложение перестать обновлять местоположение.Это необходимо для фонового отслеживания местоположения начиная с iOS 9.
источник
Я использовал метод xs2bush для получения интервала (используя
timeIntervalSinceDate
) в немного расширил его. Я хотел убедиться, что я получаю требуемую точность, которая мне нужна, а также что я не разряжаю батарею, поддерживая радио GPS более чем необходимо.Я постоянно работаю со следующими настройками:
это относительно низкий расход батареи. Когда я готов получить мое следующее периодическое чтение местоположения, я сначала проверяю, находится ли местоположение в пределах моей желаемой точности, если это так, я затем использую местоположение. Если это не так, я увеличу точность с помощью этого:
получить мое местоположение, а затем, когда у меня есть местоположение, я снова понижаю точность, чтобы минимизировать разрядку батареи. Я написал полный рабочий пример этого, а также я написал исходный код для серверной стороны, чтобы собрать данные о местоположении, сохранить их в базе данных и позволить пользователям просматривать данные GPS в режиме реального времени или получать и просматривать ранее сохраненные маршруты. У меня есть клиенты для iOS, Android, Windows Phone и Java Me. Все клиенты изначально написаны, и все они работают правильно в фоновом режиме. Проект имеет лицензию MIT.
Проект iOS предназначен для iOS 6 с использованием базового SDK iOS 7. Вы можете получить код здесь .
Пожалуйста, отправьте вопрос на github, если вы видите какие-либо проблемы с ним. Спасибо.
источник
Кажется, что stopUpdatingLocation - это то, что запускает фоновый сторожевой таймер, поэтому я заменил его в didUpdateLocation на:
который, по-видимому, эффективно отключает GPS. Селектор для фона NSTimer становится:
Все, что я делаю, это периодически переключаю точность, чтобы получать координаты высокой точности каждые несколько минут, и поскольку locationManager не был остановлен, backgroundTimeRemaining остается на своем максимальном значении. Это позволило снизить потребление заряда аккумулятора с ~ 10% в час (с постоянным значением kCLLocationAccuracyBest в фоновом режиме) до ~ 2% в час на моем устройстве
источник
Есть кокосовый модуль APScheduledLocationManager, который позволяет получать фоновые обновления местоположения каждые n секунд с желаемой точностью определения местоположения.
Репозиторий также содержит пример приложения, написанного на Swift 3.
источник
В iOS 9 и watchOS 2.0 в CLLocationManager есть новый метод, который позволяет запрашивать текущее местоположение: CLLocationManager: requestLocation (). Это завершается немедленно, а затем возвращает местоположение делегату CLLocationManager.
Вы можете использовать NSTimer для запроса местоположения каждую минуту с помощью этого метода сейчас, и вам не нужно работать с методами startUpdatingLocation и stopUpdatingLocation.
Однако, если вы хотите захватывать местоположения на основе изменения X метров от последнего местоположения, просто установите для свойства distanceFilter CLLocationManger и значение X для startUpdatingLocation ().
источник
Прилагается решение Swift, основанное на:
Определить
App registers for location updates
в info.plistПостоянно работайте locationManager
Переключение
kCLLocationAccuracy
междуBestForNavigation
(на 5 секунд для определения местоположения) иThreeKilometers
на оставшуюся часть периода ожидания, чтобы избежать разряда батареиЭтот пример обновляет местоположение каждые 1 минуту на переднем плане и каждые 15 минут на заднем плане.
Пример отлично работает с Xcode 6 Beta 6, работающей на устройстве iOS 7.
В делегате приложения (mapView является необязательным указателем на контроллер mapView)
В mapView (locationManager указывает на объект в AppDelegate)
источник