App for jailbroken iOS device: Consistent background operation

前端 未结 2 885
闹比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.

    0 讨论(0)
  • 2021-01-14 21:38

    Partial answer. If you add "voip" as Background Mode, it gets started automatically by SpringBoard.

    0 讨论(0)
提交回复
热议问题