Обновление фонового местоположения iOS 9 и обновление на сервере с помощью веб-службы

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

Проблема с iOS 9, когда приложение находится в фоновом режиме, некоторое время оно останавливает обновление местоположения и через некоторое случайное время снова запускается.

Это журналы сбоев, которые я нашел в журналах устройств.

Exception Type:  00000020
    Exception Codes: 0x000000008badf00d
    Exception Note:  SIMULATED (this is NOT a crash)
    Highlighted by Thread:  2

    Application Specific Information:
    <BKNewProcess: 0x15646220; com.com.com; pid: 1168; hostpid: -1> has active assertions beyond permitted time: 
    {(
        <BKProcessAssertion: 0x15537b80> id: 1168-1B744B09-0EB7-4B01-A6FE-F167669E4439 name: Called by UIKit, from <redacted> process: <BKNewProcess: 0x15646220; com.com.com; pid: 1168; hostpid: -1> permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:1168 preventSuspend  preventIdleSleep  preventSuspendOnSleep ,
        <BKProcessAssertion: 0x15643480> id: 1168-59515322-D982-46F8-94A5-0DD259406664 name: Called by UIKit, from <redacted> process: <BKNewProcess: 0x15646220; com.com.com; pid: 1168; hostpid: -1> permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:1168 preventSuspend  preventIdleSleep  preventSuspendOnSleep 
    )}
    Elapsed total CPU time (seconds): 6.880 (user 6.880, system 0.000), 9% CPU 
    Elapsed application CPU time (seconds): 0.081, 0% CPU

Примечание. В iOS 7 и iOS 8 все работает отлично.

Я пробовал несколько решений, доступных в stackoverflow, но я не могу найти точные решения, которые могут решить проблему.

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

Любая помощь будет высоко ценится.

Заранее спасибо.

ОБНОВЛЕНИЕ

AppDelegate.h

@property (nonatomic, retain) CLLocation *currentLocation;
@property (nonatomic, strong) NSTimer* locationUpdateTimer;
-(void)updateUsersLocation;
-(void)distroyTimer;

AppDelegate.m

-(void)callLocationManager
{
    @autoreleasepool
    {
        UIAlertView * alert;
        //We have to make sure that the Background App Refresh is enable for the Location updates to work in the background.
        if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusDenied)
        {
            alert = [[UIAlertView alloc]initWithTitle:ALERTTITLE
                                              message:@"The app doesn't work without the Background App Refresh enabled. To turn it on, go to Settings > General > Background App Refresh"
                                             delegate:nil
                                    cancelButtonTitle:@"Ok"
                                    otherButtonTitles:nil, nil];
            [alert show];
            return;
        }
        else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted)
        {
            alert = [[UIAlertView alloc]initWithTitle:ALERTTITLE
                                              message:@"The functions of this app are limited because the Background App Refresh is disable."
                                             delegate:nil
                                    cancelButtonTitle:@"Ok"
                                    otherButtonTitles:nil, nil];
            [alert show];
            return;
        }
        else if(![CLLocationManager locationServicesEnabled])
        {
            UIAlertView *alert = [[UIAlertView alloc]
                                  initWithTitle:@""
                                  message:@"Please enable GPS service for HiHo Mobile From settings"
                                  delegate:nil
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles:nil];
            [alert show];
            return;
        }
        else
        {
            if (!self.locationManager)
            {
                self.locationManager = [[CLLocationManager alloc] init];
            }
            self.locationManager.delegate = self;
            // self.locationManager.distanceFilter = kCLDistanceFilterNone;
            self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
            self.locationManager.distanceFilter = 10.0f;
            self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;

            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
            {
                [self.locationManager requestAlwaysAuthorization];
            }

            if ([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)])
            {
                self.locationManager.allowsBackgroundLocationUpdates  = YES;
            }
            if ([self.locationManager respondsToSelector:@selector(pausesLocationUpdatesAutomatically)])
            {
                self.locationManager.pausesLocationUpdatesAutomatically= NO;
            }
            if([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)])
            {
                [self.locationManager setAllowsBackgroundLocationUpdates:YES];
            }
            [self.locationManager stopMonitoringSignificantLocationChanges];
            [self.locationManager startUpdatingLocation];

            if ([USERDEFAULTS boolForKey:@"someFlag"]==YES)
            {
                [self distroyTimer];
                self.locationUpdateTimer =
                [NSTimer scheduledTimerWithTimeInterval:180
                                                 target:self
                                               selector:@selector(updateUsersLocation)
                                               userInfo:nil
                                                repeats:YES];
                [[NSRunLoop mainRunLoop]addTimer:self.locationUpdateTimer forMode:NSRunLoopCommonModes];
            }
            else
            {
                [self.locationManager stopUpdatingLocation];
                [self.locationManager startMonitoringSignificantLocationChanges];
            }
        }
    }
}

-(void)distroyTimer
{
    if ([self.locationUpdateTimer isValid])
    {
        [self.locationUpdateTimer invalidate];
        self.locationUpdateTimer = nil;
    }
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    NSLog(@"latitude: %f, longitude: %f",newLocation.coordinate.latitude, newLocation.coordinate.longitude);
    self.currentLocation = newLocation;
}

// Напишите свой код для обновления местоположения на сервере

-(void)updateUsersLocation
{
    // Your code goes here.
}

Примечание. Постоянное обновление служб определения местоположения значительно разряжает батарею вашего устройства iOS. Поэтому, как только вы не используете обновленное местоположение, вы можете использовать significant locations.


person Vatsal K    schedule 02.10.2015    source источник
comment
Это кажется слишком похожим на проблему, с которой я столкнулся. Вы случайно не используете локалитику?   -  person quant24    schedule 16.10.2015
comment
Нет, мы не используем локализацию. Мы отслеживаем обновление местоположения с помощью нашего собственного бэкэнда и используем устройство NSLog().   -  person Vatsal K    schedule 19.10.2015
comment
@quant24 как вы решили проблему с Localytics? В чем была проблема?   -  person Alex Brashear    schedule 09.03.2016
comment
@VatsalK Я работаю над таким же проектом. Можете ли вы предоставить пример кода?   -  person venky    schedule 28.04.2016
comment
@venky Я удалил таймеры для остановки и повторного запуска обновления менеджера местоположения. Тогда приложение не будет приостанавливаться, и вы будете обновлять местоположение в фоновом режиме в течение более длительного времени.   -  person Vatsal K    schedule 28.04.2016
comment
@VatsalK Вы можете отправлять данные на сервер без использования таймера и фоновой задачи? Мне нужно отправлять обновление местоположения на сервер каждые 20 секунд, даже если приложение находится в фоновом режиме.   -  person venky    schedule 28.04.2016
comment
@venky Ну, я использовал для этого таймер, но вы можете добавить некоторую логику синхронизации с помощью метода - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation, используя временную температуру, и получать разницу каждые 20 секунд.   -  person Vatsal K    schedule 29.04.2016
comment
@venky Я обновил вопрос с рабочим исходным кодом, надеюсь, это поможет вам.   -  person Vatsal K    schedule 29.04.2016


Ответы (3)


Вы должны использовать фоновый режим обновлений местоположения, чтобы получать обновления местоположения в фоновом режиме, тогда ваше приложение будет просыпаться из фона, когда когда-либо вызывается didupdalocation См. документы для лучшего понимания.

person Imran    schedule 02.10.2015
comment
Я уже обновил эти вещи и сохранил ‹key›UIBackgroundModes‹/key› ‹array› ‹string›fetch‹/string› ‹string›location‹/string› ‹/array› Также для iOS 9 мы добавили ‹key›allowsBackgroundLocationUpdates ‹/key› ‹string›YES‹/string›, чтобы мы могли обновлять местоположение и в фоновом режиме. - person Vatsal K; 02.10.2015
comment
Можете ли вы опубликовать код обновления вашего местоположения и загрузить код? - person Imran; 02.10.2015
comment
Я использовал эти классы для обновления местоположения. И установлен таймер для обновления местоположения на сервере. self.locationUpdateTimer = [NSTimer ScheduleTimerWithTimeInterval: kPingFrequencyTime target: self selector: @selector (updateLocation) userInfo: nil Repeats: YES]; - person Vatsal K; 02.10.2015

Я была такая же проблема.

Новый параметр allowsBackgroundLocationUpdates не может оставаться в plist, вы должны поместить его в код.

myLM = [[CLLocationManager alloc] init];
if([myLM respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
   [myLM setAllowsBackgroundLocationUpdates: YES];
}
person Eduardo Herzer    schedule 02.10.2015
comment
Да, я добавил это условие вместе с pausesLocationUpdatesAutomatically. if ([self.locationManager responsesToSelector:@selector(allowsBackgroundLocationUpdates)]) { self.locationManager.allowsBackgroundLocationUpdates = YES; } if ([self.locationManager responsesToSelector:@selector(pausesLocationUpdatesAutomatically)]) { self.locationManager.pausesLocationUpdatesAutomatically= NO; } - person Vatsal K; 03.10.2015
comment
@VatsalK Вы запрашиваете авторизацию пользователя с помощью requestAlwaysAuthorization? Вы запускаете диспетчер местоположения, когда приложение все еще находится на переднем плане? Можете ли вы опубликовать, как вы создаете, настраиваете и инициализируете диспетчер локалей? Также убедитесь, что вы нигде не останавливаетесь! - person Eduardo Herzer; 06.10.2015
comment
Да, я использую requestAlwaysAuthorization. Поскольку все работает нормально в режиме переднего плана, и я не останавливаю диспетчер местоположения, пока это не предполагается. - person Vatsal K; 07.10.2015

У меня есть таймер для запуска и остановки диспетчера местоположений, так как я отправил тот же вопрос разработчикам Apple, и они предложили мне сохранить один менеджер местоположений для приложения и удалить таймеры, которые могут получить < strong>затрагивается во время потоков, пока приложение работает в фоновом режиме, поэтому, наконец, я удалил логику таймеров, и теперь диспетчер местоположений постоянно обновляет местоположение, пока пользователь не выйдет из системы. Это может разрядить батарею, но это единственное решение, которое я нашел и которое работает для нашего приложения.

person Vatsal K    schedule 26.11.2015
comment
Для выражения благодарности у вас есть кнопка плюса :) Никакой явной благодарности не требуется. - person Honza Zidek; 26.11.2015