фоновые службы определения местоположения не работают в ios 7

<p>я недавно обновил свои устройства ios для использования ios 7. одно из разрабатываемых нами приложений использует фоновые службы определения местоположения для отслеживания местоположения устройства, и все наши тестеры сообщили, что приложение больше не отображается для отслеживания в фоновом режиме под ios 7. </p><p>мы убедились, что фоновая настройка для приложения включена в настройках устройства, и предыдущая сборка работала безупречно под ios 6. даже если устройство было зациклено, приложение перезапустится после обновления местоположения. </p><p>есть ли что-то еще, что нужно сделать, чтобы это работало под ios 7? </p>

<p>вот решение, которое я использовал для получения непрерывного местоположения от устройств ios 7, независимо от того, находится оно на переднем плане или на заднем плане.</p><p>вы можете найти полное решение и объяснение в блоге, а также на github: -</p><ol> <li><p> <a href="http://mobileoop.com/background-location-update-programming-for-ios-7">программирование обновления фонового местоположения для ios 7 и 8</a> </p></li> <li><p> <a href="https://github.com/voyage11/location">github project: программирование фонового обновления местоположения для ios 7 и 8</a> </p></li> </ol><p>методы и объяснение: -</p><ol> <li><p>я перезапускаю диспетчер местоположений каждую 1 минуту в функции <strong>didupdatelocations</strong></p></li> <li><p>я позволяю диспетчеру местоположений получать местоположения от устройства в течение 10 секунд, а затем выключить его (для экономии заряда аккумулятора).</p></li> </ol><p>частичный код ниже: -</p><pre><code>-(void)locationmanager:(cllocationmanager *)manager didupdatelocations:(nsarray *)locations{ for(int i=0;i<locations.count;i++){ cllocation * newlocation = [locations objectatindex:i]; cllocationcoordinate2d thelocation = newlocation.coordinate; cllocationaccuracy theaccuracy = newlocation.horizontalaccuracy; nstimeinterval locationage = -[newlocation.timestamp timeintervalsincenow]; if (locationage > 30.0) continue; //select only valid location and also location with good accuracy if(newlocation!=nil&&theaccuracy>0 &&theaccuracy<2000 &&(!(thelocation.latitude==0.0&&thelocation.longitude==0.0))){ self.mylastlocation = thelocation; self.mylastlocationaccuracy= theaccuracy; nsmutabledictionary * dict = [[nsmutabledictionary alloc]init]; [dict setobject:[nsnumber numberwithfloat:thelocation.latitude] forkey:@"latitude"]; [dict setobject:[nsnumber numberwithfloat:thelocation.longitude] forkey:@"longitude"]; [dict setobject:[nsnumber numberwithfloat:theaccuracy] forkey:@"theaccuracy"]; //add the vallid location with good accuracy into an array //every 1 minute, i will select the best location based on accuracy and send to server [self.sharemodel.mylocationarray addobject:dict]; } } //if the timer still valid, return it (will not run the code below) if (self.sharemodel.timer) return; self.sharemodel.bgtask = [backgroundtaskmanager sharedbackgroundtaskmanager]; [self.sharemodel.bgtask beginnewbackgroundtask]; //restart the locationmaanger after 1 minute self.sharemodel.timer = [nstimer scheduledtimerwithtimeinterval:60 target:self selector:@selector(restartlocationupdates) userinfo:nil repeats:no]; //will only stop the locationmanager after 10 seconds, so that we can get some accurate locations //the location manager will only operate for 10 seconds to save battery nstimer * delay10seconds; delay10seconds = [nstimer scheduledtimerwithtimeinterval:10 target:self selector:@selector(stoplocationdelayby10seconds) userinfo:nil repeats:no]; } </code></pre><p><strong>обновление от мая 2014 г.</strong>: я получил несколько запросов на добавление примеров кодов при отправке местоположения на сервер в течение определенного промежутка времени. я добавил примеры кодов, а также объединил исправление для backgroundtaskmanager, чтобы решить проблему с фоном, работающим в течение длительного периода времени. если у вас есть какие-либо вопросы, приглашаем вас присоединиться к нам для обсуждения здесь: <a href="http://mobileoop.com/background-location-update-programming-for-ios-7">фоновое программирование обновления местоположения для ios 7 с обновлением местоположения для обсуждения на сервере</a> </p><p><strong>обновление в январе 2015 года</strong>: если вы хотите получать обновление местоположения даже тогда, когда приложение приостановлено, см.: <a href="https://stackoverflow.com/questions/27742677/how-to-get-location-updates-for-ios-7-and-8-even-when-the-app-is-suspended">получение обновлений местоположения для приложения ios, даже когда оно приостановлено</a> </p>

<p>если вы посмотрите видео сессия wwdc 2013 № 204 - что нового в многозадачности pdf, на странице № 15 ясно упоминается, что приложения не будут запускаться в фоновом режиме, если пользователь убьет его из переключателя приложений. пожалуйста, смотрите изображение,</p><p><img src="https://i.stack.imgur.com/rwtyk.png" alt="enter image description here"></p>

<p>я думаю, что они сделали оптимизацию (возможно, с использованием датчиков движения), чтобы обнаружить «относительно» стационарное позиционирование телефона, и они останавливают обновления местоположения. это только предположение, но мои тесты в настоящее время показывают:</p><ol> <li>начальные локации обновлений; (проверено с точностью 10 и 100 метров, 3 раза каждый)</li> <li>выключите экран устройства, чтобы поместить приложение в фоновом режиме;</li> <li>оставьте устройство неподвижным (например, на столе) на 30 минут.</li> </ol><p>данные, которые я записываю, показывают, что гео-обновления перестают поступать через ~ 15 м и 30 с. при этом вся другая фоновая обработка, которую вы делаете, также прекращается.</p><p>моим устройством является iphone 5 с ios 7.</p><p>я на 95% уверен, что это не так на ios 6/6.1. где для получения гео-обновлений с точностью до 100 м используется непрерывная работа в фоновом режиме.</p><p><strong> обновление </strong></p><p>если вы перезапускаете диспетчер местоположений каждые 8 минут, он должен работать непрерывно.</p><p><strong> обновление № 2 </strong></p><p>я не проверял это в последнем, но именно так я перезапустил его, когда писал пост. я надеюсь, что это полезно.</p><pre><code>- (void)tryrestartlocationmanager { nstimeinterval now = [[nsdate date] timeintervalsince1970]; int seconds = round(floor(now - locationmanagerstarttimestamp)); if ( seconds > (60 * 8) ) { [locationmanager stopupdatinglocation]; [locationmanager startupdatinglocation]; locationmanagerstarttimestamp = now; } } </code></pre>

<p>одно из моих приложений для ios должно регулярно отправлять обновление местоположения на сервер, и у нас сработал следующий подход ...</p><p>начиная с ios 7:</p><ul> <li>приложение, должно быть, уже использовало службы определения местоположения (startupdatinglocation) до того, как оно стало фоновым, чтобы подходило для фоновой среды выполнения.</li> <li>тайм-аут фонового периода был сокращен с 10 минут до 3 минут.</li> <li>остановка обновлений местоположения (через stopupdatinglocation) запустит обратный отсчет 3 .\_\_ минуты backgroundtimeremaining</li> <li>начальное обновление местоположения, пока оно уже находится в фоновом режиме, не будет сбросить backgroundtimeremaining</li> </ul><p>таким образом, не останавливайте обновления местоположения в любое время ... вместо этого, предпочтите использовать необходимую точность (точное местоположение против грубого местоположения). грубое расположение не потребляет много батареи ... так что это решение решает вашу проблему.</p><p>после долгих поисков в интернете, нашел ссылку, которая обеспечивает жизнеспособное решение для ios 7. решение заключается в следующем:</p><ul> <li>пока приложение все еще находится на переднем плане, запускайте обновления местоположения (startupdatinglocation), но устанавливайте фильтры точности и расстояния на очень подробные (например, 3 км) обновления. это важно сделать. на переднем плане (в applicationdidenterbackground слишком поздно).</li> <li>когда требуется детализированное разрешение, временно установите фильтры точности и расстояния , чтобы получить наилучшее возможное местоположение, и затем верните их обратно к детализированным значениям курса, но никогда не останавливайте обновления местоположения </li> <li>поскольку обновления местоположения всегда включены, приложение не прекратит работу , когда перейдет в фоновый режим.</li> </ul><p>и убедитесь, что вы добавили следующее в info.plist вашего приложения «location» к ключу uibackgroundmodes «location-services» и «gps» к ключу uirequireddevicecapabilities</p><p>кредиты: <a href="http://gooddevbaddev.wordpress.com/2013/10/22/ios-7-running-location-based-apps-in-the-background/">http://gooddevbaddev.wordpress.com/2013/10/22/ios-7-running-location-based-apps-in-the-background/</a> </p>

<p>я нашел другой поток <a href="https://stackoverflow.com/questions/18901583/start-location-manager-in-ios-7-from-background-task">запустите location manager в ios 7 из фоновой задачи</a> sash упомянул, что </p><blockquote> <p>я нашел проблему/решение. когда пришло время запустить службу определения местоположения и остановить фоновую задачу, фоновую задачу следует остановить с задержкой (я установил 1 секунду). в противном случае служба определения местоположения не запустится.</p> </blockquote><p>кто-нибудь может попробовать и проверить? </p><p>николай, ты можешь вставить свой код сюда? я пытался перезапустить диспетчер местоположения каждые 8 минут, но он не работает непрерывно.</p><p><strong>обновление:</strong></p><p>после поиска high и low я нашел решение от apple forum!</p><p>в ios 7 вы <strong>не можете запустить службу определения местоположения в фоновом режиме</strong>. если вы хотите, чтобы служба определения местоположения продолжала работать в фоновом режиме, вы должны запустить ее на переднем плане, и она будет продолжать работать в фоновом режиме. </p><p>если вы похожи на меня, остановите службу определения местоположения и используйте таймер, чтобы перезапустить ее в фоновом режиме, она не будет работать. </p><p>для получения более подробной информации вы можете посмотреть первые 8 минут видео 307 с wwdc 2013: <a href="https://developer.apple.com/wwdc/videos/">https://developer.apple.com/wwdc/videos/</a> </p><p><strong>фев 2014 обновление:</strong> я могу получать местоположение постоянно с устройства, использующего ios 7 после нескольких месяцев попыток. вы можете увидеть полный ответ здесь: <a href="https://stackoverflow.com/questions/18946881/background-location-services-not-working-in-ios-7/21966662#21966662">фоновые службы определения местоположения не работают в ios 7</a> </p>

<p>значок в строке состояния включен? это странное поведение, которое я имел тоже . проверьте мой вопрос: <a href="https://stackoverflow.com/questions/18919333/startmonitoringsignificantlocationchanges-but-after-some-time-didupdatelocations">startmonitoringsignificantlocationchanges, но через некоторое время didupdatelocations больше не вызывается</a> </p><p>я обнаружил, что произошли значительные изменения местоположения, но простая остановка и перезапуск службы (для значительных изменений) не приводили к запуску новых местоположений.</p>

<p>вы должны установить для свойства <code>pauseslocationupdatesautomatically</code> класса <code>cllocationmanager</code>class значение<strong> false </strong>, чтобы отключить систему от приостановки обновления местоположения.</p>