App for jailbroken iOS device: Consistent background operation

前端 未结 2 884
闹比i
闹比i 2021-01-14 21:08

I am the author of a Cydia tweak called AirFloat. An app that implements the AirPlay audio protocol (previously known as AirTunes), making it possible to stream audio to

2条回答
  •  生来不讨喜
    2021-01-14 21:36

    First thank you for your amazing works with AirFlow RAOP is pretty hard thing!

    So what you could do is to

    1. Create a background task handlers as dispatch_block_t, let's say

         dispatch_block_t myDummyBackgroundTaskBlock = {
            [[UIApplication sharedApplication] endBackgroundTask:myDummyBackgroundTask];
            myDummyBackgroundTask = UIBackgroundTaskInvalid;
            myDummyBackgroundTask = [app beginBackgroundTaskWithExpirationHandler:myDummyBackgroundTask];
        };
    

    2. Define somewhere this background and foreground tasks handler

            // foreground
            -(void)handleTasksForApplicationInForeground {
            if(myDummyBackgroundTask) { // reset that task
               [[UIApplication sharedApplication] endBackgroundTask: myDummyBackgroundTask];
               myDummyBackgroundTask = UIBackgroundTaskInvalid;
             }
            }
    
             // background
             -(void) handleTasksForApplicationInBackground {
                 UIDevice *device = [UIDevice currentDevice];
                 BOOL backgroundSupported = NO;
                if ([device respondsToSelector:@selector(isMultitaskingSupported)])
                 backgroundSupported = device.multitaskingSupported;
                if(backgroundSupported && backgroundEnabled) { // perform a background task
    
                    myDummyBackgroundTaskBlock = ^{
                        [[UIApplication sharedApplication] endBackgroundTask: myDummyBackgroundTaskBlock];
                        myDummyBackgroundTaskBlock = UIBackgroundTaskInvalid;
                   };
    
                   SEL sel = @selector(doDummyBackgroundTask);
                   [self doBackgroundTaskAsync:sel];
    
                   [self performSelector:@selector(doBackgroundTaskAsync:) withObject:nil afterDelay:500.0f]; /// LP: this is the funny part since iOS will kill the task after 500 sec.
                     }
                   }
    

    3. Now let's handle in the application delegate the background mode (As defined before you can activate background mode with different options in your app .plist):

            -(void)applicationDidEnterBackground:(UIApplication *)application {
               [self handleTasksForApplicationInBackground];
             }
    
            -(void)applicationWillEnterForeground:(UIApplication *)application {
               [self handleTasksForApplicationInForeground];
             }
    

    4. Let's see what the background async task selector does

                -(void) doBackgroundTaskAsync:(SEL)selector {
    
                @try {
                     if( [[UIApplication sharedApplication] backgroundTimeRemaining] < 5 ) { 
                       return;
                     }
    
                   if(!myDummyBackgroundTaskBlock) { // need to create again on-the-fly
                        myDummyBackgroundTaskBlock = ^{
                              [[UIApplication sharedApplication] endBackgroundTask:myDummyBackgroundTask];
                             myDummyBackgroundTask = UIBackgroundTaskInvalid;
                        };
                     }
    
                    myDummyBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:myDummyBackgroundTaskBlock];
                  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    
                   while ([[UIApplication sharedApplication] backgroundTimeRemaining] > 5.0) {
                      int delta = 5.0;
                      [self performSelector: selector ];
                      sleep(delta);
                  }
                });
              }
               @catch (...) {
             }
            }
    

    I know that this solution works nice but I know that sometimes it happens that iOS will kill the app background task anyway. Anyway if the users suddenly switches the app between foreground and background it will works indefinitely.

提交回复
热议问题