iOS 9: beginBackgroundTaskWithExpirationHandler вызывается до истечения времени ожидания

я работаю над вызовом VOIP и добавляю поддержку в iOS ‹ 10. Для входящего вызова VOIP, когда приложение находится в фоновом режиме, я использую UILocalNotification (устарело в iOS 10).

Чтобы сделать звонок 60 секунд (или 1 минуту), я использую этот код

    count = 0;
                    apnTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                                                target:self
                                                              selector:@selector(showIncomingCall:)
                                                              userInfo:userInfo
                                                               repeats:YES];
    self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
                        NSLog(@"ALVOIP : BACKGROUND_HANDLER_NO_MORE_TASK_RUNNING.");
                        [application endBackgroundTask:self.backgroundTask]; 
                        self.backgroundTask = UIBackgroundTaskInvalid;
                    }];


    -(void)showIncomingCall:(NSTimer *)timer
{
    if (count < 60)
    {

            UIApplication *application = [UIApplication sharedApplication];
            [application presentLocalNotificationNow:localNotification];
            NSLog(@"Time Remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]);

        count = count + 3;
        return;
    }

    // TIMEOUT : STOP TIMER AND LOCAL NOTIFICATION BACKGROUND TASK
    [self invalidateCallNotifying];
}

-(void)invalidateCallNotifying
{
    [apnTimer invalidate];
    if (self.backgroundTask != UIBackgroundTaskInvalid)
    {
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
        self.backgroundTask = UIBackgroundTaskInvalid;
    }
}

чтобы увеличить время фонового процесса до 1 минуты, и он работает в iOS 10.1.1 (iPhone), но не работает в iOS 9.3.5 (iPad). Каким-то образом обработчик вызывает 30-33 секунды?

ОБНОВИТЬ:

я пытался прокомментировать этот код:

self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
                        NSLog(@"ALVOIP : BACKGROUND_HANDLER_NO_MORE_TASK_RUNNING.");
                        [application endBackgroundTask:self.backgroundTask]; 
                        self.backgroundTask = UIBackgroundTaskInvalid;
                    }];

Тем не менее я могу сделать 30-33 секунды, то есть я не знаю, почему это не работает?


person Abhishek Thapliyal    schedule 16.02.2017    source источник


Ответы (3)


Я бы посоветовал вам поместить код в эту структуру и использовать этот код

-(void)yourMethod
{
 __block UIBackgroundTaskIdentifier background_task;
background_task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void){
    [[UIApplication sharedApplication] endBackgroundTask: background_task];
    background_task = UIBackgroundTaskInvalid;
}];

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

//Some Methods Calls

    dispatch_async(dispatch_get_main_queue(), ^{
        //View Controller Change
    });
});
}
person ChenSmile    schedule 16.02.2017
comment
Мне нужно продлить время, когда приложение находится в фоновом режиме, чтобы ничего не менять в контроллере представления. - person Abhishek Thapliyal; 16.02.2017
comment
@Abhishek Thapliyal использует вашу логику внутри этого метода - person ChenSmile; 16.02.2017
comment
Не понимаю, как это будет корректироваться в моем коде. Мне не нужна смена контроллера vie или какой-либо вызов, только вызов таймера - person Abhishek Thapliyal; 16.02.2017

Когда вы создаете приложение VOIP, в info.plist вы должны иметь возможность установить UIBackgroundModes на voip и UIApplicationExitsOnSuspend на NO, чтобы разрешить выполнение фоновых задач.

Посетите эту страницу справки Apple. в разделе «Объявление поддерживаемых фоновых задач вашего приложения» для получения дополнительной информации.

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

Также см. этот ответ на SO.

person ingh.am    schedule 16.02.2017
comment
Спасибо за ваш ответ, но все еще получаю максимум 36 секунд в iOS 9 :( - person Abhishek Thapliyal; 16.02.2017
comment
Также я попытался прокомментировать этот код: self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{ NSLog(@ALVOIP: BACKGROUND_HANDLER_NO_MORE_TASK_RUNNING.); [приложение endBackgroundTask:self.backgroundTask]; self.backgroundTask = UIBackgroundTaskInvalid; }]; это не работает и, следовательно, не продлевает время, так как после комментирования я все еще могу сделать 30-33 секунды - person Abhishek Thapliyal; 16.02.2017
comment
@AbhishekThapliyal Если вы пытаетесь воссоздать таймер, когда приложение приостановлено, чтобы увеличить время фоновой обработки, я думаю, что это поведение перестало работать с iOS 7. В настоящее время я работаю над проектом, в котором мне нужно снова изучить фоновые задачи, поэтому я дайте вам знать, что я нахожу. - person ingh.am; 17.02.2017
comment
@AbhishekThapliyal Извините за вопрос, но можете ли вы подтвердить, что строите на реальном устройстве, а не только на симуляторе? - person ingh.am; 17.02.2017

Вместо использования NSTimer я предлагаю вам запланировать несколько UILocalNotification, каждый из которых имеет увеличивающуюся дату пожара, а затем установить звук UILocalNotification последним для увеличенного интервала. Например, предположим, что ваш звук может длиться 20 секунд, затем вы планируете 3 UILocalNotification с fireDate через 0,+20,+40 секунд.

Конечно, если пользователь ответит на ваш звонок, вам нужно отменить оставшееся UILocalNotification.

person Qiulang    schedule 20.02.2017
comment
но я хочу воспроизводить звук входящего вызова также для локального уведомления - person Abhishek Thapliyal; 20.02.2017
comment
Я скажу, что использование разных звуков для разных целей может быть хорошей идеей. - person Qiulang; 20.02.2017
comment
я имею в виду с локальным уведомлением, мне нужно воспроизвести звук также в течение 1 минуты - person Abhishek Thapliyal; 20.02.2017
comment
3 уведомления, каждые 20 секунд, значит 60 секунд - person Qiulang; 20.02.2017