2013-02-24 2 views
2

Мне нужно постоянно получать обновления местоположения пользователя, когда приложение переходит в фоновый режим, и, как я нашел в документации Apple, это одна из длительных фоновых задач, которые разрешены для реализации. Мне также необходимо сделать некоторые обработки и сетевые вызовы для отправки на сервер информации, когда уведомления о местоположении будут уведомлены. То, что я пытаюсь сделать, в общих чертах, что-то вроде этого:Понимание фонового отслеживания местоположения пользователя в iOS

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ 
     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 

    // Background task   
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSLog(@"Background time remaining: %f seconds (%d mins)", 
    [[UIApplication sharedApplication] backgroundTimeRemaining], 
    (int)([[UIApplication sharedApplication] backgroundTimeRemaining]/60)); 

     // Need to get data from database here 

     // Finished 
     if (bgTask != UIBackgroundTaskInvalid) { 
     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
     } 

    }); 

    // Start location manager 
    locationManager = [[CLLocationManager alloc] init]; 
    if ([CLLocationManager locationServicesEnabled]) {   
     locationManager.delegate = self; 
     locationManager.distanceFilter = 20; 
     locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
     [locationManager startUpdatingLocation]; 
    } 
} 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Want to perform some data processing here, including concurrent tasks 
     // and several network calls to get and send data to server 

     [self locationProcessingCompleted]; 

    }); 
} 

- (void)locationProcessingCompleted 
{ 
    // Check results. If needed, some more data processing and several network 
    // calls to send data to server 

    // Close background task 
    if (bgTask != UIBackgroundTaskInvalid) { 
     [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    } 
} 

I don`t найти пример коды продолжительном фоновой задачи в отношении услуг по определению местоположения, и у меня есть несколько вопросов по этому поводу :

a) Необходимо ли выполнить весь фоновый код в очереди dispatch_async? Другими словами, весь код в applicationDidEnterBackground: должен выполняться асинхронно, включая настройки менеджера местоположений?

b) [[UIApplication sharedApplication] backgroundTimeRemaining] возвращает очень большое значение. На этот раз не должно быть около 10 минут?

c) Я хочу выполнить: выполнить начальную задачу конечной длины, начать обновление местоположения, а затем выполнить некоторые другие задачи конечной длины каждый раз, когда запускается didUpdateToLocation:. Я установил значение locationUIBackgroundModes в Info.plist. Правильно ли мой подход? Будет ли я постоянно обновлять места, а затем я могу выполнить задачу с конечной длиной менее 10 минут при каждом полученном обновлении?

Пожалуйста, мне нужна помощь по этим вопросам. Заранее спасибо

ответ

2

Все, что вам нужно сделать, это добавить «Регистры приложений для обновления местоположения» в разделе «Необходимые фоновые режимы», вы можете отредактировать файл plist в текстовом редакторе и добавить следующий код или использовать xcode для добавления необходимого фона режимы.

<key>UIBackgroundModes</key> 
<array> 
    <string>location</string> 
</array> 

метод didUpdateToLocation будет вызываться (даже если ваше приложение находится в фоновом режиме). Вы можете выполнить любую вещь, на основании этого вызова метода ...

Снимок из Xcode

Snapshot of Xcode

+1

+1 Это решение на ios 6 !!! – 2013-08-21 12:53:20

+0

Это не касается оригинального вопроса о плакатах. Настройка UIBackgroundModes дает вам обновления, но это не позволяет вам достаточно времени на обработку, чтобы фактически выполнять сетевые подключения и выполнять настоящую работу. И backgroundTimeRemaining остается огромным числом, указывая, что он не был установлен, даже если вы создаете фоновое задание в методе обработки местоположений. Мой опыт в том, что мои фоновые операции убиваются за считанные секунды. –

+2

Извините, я хотел бы не согласиться с тем, что одно из моих приложений, которое работает в App Store, многое делает на основе обновлений местоположения в фоновом режиме (доступ к сети, обработка данных и отправка локальных уведомлений и т. Д.). Я предполагаю (может быть, неправильно), что ваш комментарий основан на предположениях/знаниях, а не на опыте конкретной ситуации или может быть, что вы делаете что-то не так, если у вас возникают проблемы при обработке в аналогичном случае. – Zee

0

В соответствии с вашим кодом при условии вы выделяя LocationManager на applicationDidEnterBackground, я хотел бы предложить вам распределите LocationManager в методе didFinishLaunchingWithOptions, а затем вызовите метод startUpdatingLocation в методе applicationDidEnterBackground.

Вам также может потребоваться вызвать stopUpdatingLocation в вашем приложенииWillEnterForeground (в случае, если вам не требуется получать обновления местоположения, когда приложение находится на переднем плане).

Совет: Не включайте GPS с лучшей точностью в течение длительного времени, так как он очень быстро съедает батарею (в течение 3-4 часов, согласно моему опыту).

+0

проблема с дизайном: если я хочу также иметь возможность слушать обновления местоположения при приложении на переднем плане и отображать их на карте, что должно быть лучшим способом? Должен ли я хранить экземпляр «locationManager» в «AppDelegate» и отправлять уведомления для просмотра контроллеров в режиме переднего плана? – AppsDev

+0

Требуется ли обновление местоположения в фоновом режиме, имея методы «locationManager» и его делегаты в «AppDelegate», или это возможно/правильно/лучше, чтобы иметь другой экземпляр класса с его собственными методами «locationManager» и «делегировать», и то пусть 'AppDelegate' просто создает его? – AppsDev

0

Отказ от ответственности: Я работаю Cintric

Мы также хотели, чтобы иметь возможность точно отслеживать местоположение пользователей в фоновом режиме (даже после того, как приложение было убито). Мы долгое время решали проблему, особенно фокусируясь на разряде батареи.

Мы разместили замечательное сообщение в блоге о том, как мы его решили. http://www.blog.cintric.com/?p=121 А также предоставляют бесплатное решение SDK для перетаскивания.С одной строкой кода вы можете постоянно отслеживать местоположение в фоновом режиме и использовать только 1% батареи. Кроме того, вы можете установить класс в качестве его делегата, чтобы вы могли отправлять информацию на ваш сервер (в том числе в фоновом режиме без использования фоновой задачи api).

Вы можете скачать файл .framework, перетащите его в свой проект и инициализировать с помощью одной строки кода: [CintricFind initWithApiKey:@"YOUR_API_KEY_HERE" andSecret:@"YOUR_SECRET_HERE"];

Вы можете получить ключ API бесплатно. Есть документы, объясняющие каждый из них здесь: https://www.cintric.com/docs/ios

Смежные вопросы