What is the proper way to handle background tasks in iOS

独自空忆成欢 提交于 2020-01-12 10:52:31

问题


I have a voip app and it needs to run in the background. To my understanding these are the things I need to do:

  1. Flag the app as voip.
  2. Set the 'application does not run in background' flag to NO.
  3. Set an expiration handler, a piece of code that extends the standard 10 minutes of execution time you get.
  4. More?

I set both flags in the info.plist file and I get my 10 minutes. I tried what is suggested in this post. Here is my code:

//in didFinishLaunchingWithOptions:
expirationHandler = ^{
    NSLog(@"ending background task");
    [[UIApplication sharedApplication] endBackgroundTask:bgTask];

    NSLog(@"restarting background task");
    bgTask = UIBackgroundTaskInvalid;
    bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];

    NSLog(@"finished running background task");
};

//in applicationDidEnterBackground
NSLog(@"entering background mode");
bgTask = UIBackgroundTaskInvalid;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // inform others to stop tasks, if you like
    [[NSNotificationCenter defaultCenter] postNotificationName:@"MyApplicationEntersBackground" object:self];

    //this while loop is just here for testing
    inBackground = true;
    while (inBackground) {
        NSLog(@"stayin alive!!"); //this keeps going forever
        sleep(10);
    }
});

The situation:

I use a third party library that handles the communication with our webservice. The service is a CommuniGate pro server. I receive presence updates (online/offline) and instant messages from contacts via the library. The library is CommuniGate's ximss library, a protocol they made which is similar to xmpp and is used for xml-based sip requests, as well as IM and presence. When the user logs in to the app, he sees his contacts (CmmuniGate friends list) and he can choose to call one. After a ximss verification message has been sent and the other side accepted the call it logs the start time of the call and starts a facetime call.

The problem:

When the app enters the background by pressing the home button, I start seeing the 'stayin alive' message in the log and every ten minutes I see that it restarts the background task.
When the app enters the background by pressing the power button, the 'staying alive' messages start showing up for ten minutes, after that it restarts the background task and start restarting it about every 50-100 miliseconds.
I would've been fine with this for now, even it eats battery, because I have time to work on updates and our users don't own the ipads, we do. The problem for me now is that the ximss library loses it's connection (it is session-based). I could restart the session in the library, but this means quite a bit of data transfer to fetch the contacts list and some users use 3g.
I can't edit the library's source, nor can I see it, so I don't know if it creates the sockets the right way.

What do I have to do to handle both situations correctly? I don't even understand why there is a difference.


回答1:


You cannot re-extend background tasks like this; your app is likely to be terminated. If this is working, it's because you have the background voip mode enabled, not because you are restarting the background task.

Once you have set the voip plist entry, iOS will attempt to keep your app alive as long as possible and restart it if it does get terminated. From Implementing a VoIP App:

Including the voip value in the UIBackgroundModes key lets the system know that it should allow the app to run in the background as needed to manage its network sockets. An app with this key is also relaunched in the background immediately after system boot to ensure that the VoIP services are always available.

In addition to setting this key, if you need to periodically run code to keep your voip connection alive, you can use the setKeepAliveTimeout:handler: method on UIApplication.

See also Tips for Developing a VoIP App:

There are several requirements for implementing a VoIP app:

  1. Add the UIBackgroundModes key to your app’s Info.plist file. Set the value of this key to an array that includes the voip string.

  2. Configure one of the app’s sockets for VoIP usage.

  3. Before moving to the background, call the setKeepAliveTimeout:handler: method to install a handler to be executed periodically. Your app can use this handler to maintain its service connection.

  4. Configure your audio session to handle transitions to and from active use.

  5. To ensure a better user experience on iPhone, use the Core Telephony framework to adjust your behavior in relation to cell-based phone calls; see Core Telephony Framework Reference.

  6. To ensure good performance for your VoIP app, use the System Configuration framework to detect network changes and allow your app to sleep as much as possible.

Almost all of the documentation you need is on the Apple developer site.



来源:https://stackoverflow.com/questions/18247808/what-is-the-proper-way-to-handle-background-tasks-in-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!