iOS 9 : beginBackgroundTaskWithExpirationHandler i

2019-01-29 05:17发布

问题:

i'm working on VOIP call and adding support to iOS < 10. For incoming VOIP call when app is in background, i'm using UILocalNotification (deprecated in iOS 10).

To make a call 60 secs (or 1 minute) i'm using this code

    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;
    }
}

to extend background process time to 1 minute and it's working in iOS 10.1.1 (iPhone) but not working in iOS 9.3.5 (iPad). Somehow handler is invoking 30-33 secs?

UPDATE:

i tried to comment this code :

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

Still i'm able to do 30-33 secs i.e i don't know why this is not working?

回答1:

I Would Suggest you to Put Code in this Structure and Use this Code

-(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
    });
});
}


回答2:

As you are building a VOIP application, in info.plist you should be able to set UIBackgroundModes to voip and UIApplicationExitsOnSuspend to NO to allow background tasks.

Check out this apple help page on "Declaring Your App’s Supported Background Tasks" for more information.

When I last built an application that ran in the background (albeit it was for background location services, not for a voip app), I had to put a disclaimer on the app store listing about the app using excessive battery life. I'm not sure if this is relevant anymore though.

Also see this answer on SO.



回答3:

Instead of using an NSTimer, I will suggest you schedule several UILocalNotification, each has an increasing fireDate, then set your UILocalNotification sound last for the increased interval. For example, say your sound can last for 20 seconds, then you schedule 3 UILocalNotification with fireDate at 0,+20,+40 seconds from now.

Of course if user answers your call you need to cancel the remaining UILocalNotification.