适用于越狱iOS设备的应用程序:一致的后台操作

时间:2013-03-16 11:46:32

标签: ios jailbreak airplay cydia mpnowplayinginfocenter

我是一个名为AirFloat的Cydia调整的作者。一个实现AirPlay音频协议(以前称为AirTunes)的应用程序,可以将音频流式传输到您的iOS设备。 AirFloat最初是一个App Store应用程序,直到Apple从App Store启动它。

我已经在Cydia免费提供了它。目前,该应用程序完全像以前的App Store版本一样位于Cydia。因此,我得到了很多要求让它在后台运行的请求。但我无法让它发挥作用。

基本上我在考虑两种方法。

注意:AirFloat会在iOS锁定屏幕上显示当前播放的曲目。

  1. 创建一个守护程序,它运行实际的AirPlay实现,并使用notify与UI应用程序通信。这有效。的种类。它运行并播放音频,但MPNowPlayingInfoCenter似乎不能从非UI应用程序更新。此外,当守护程序以用户 mobile 运行时。

  2. 第二种方法是让它在UI应用程序中完成所有工作。但我没有被暂停的困难。我已将“所需背景模式”设置为音频连续。服务器可能仍在运行,但随后Bonjour广告被关闭,因为运行循环在后台停止。其次,应该使用SpringBoard自动启动应用程序,并在异常退出时重新启动。

  3. 我个人更喜欢第二种方法,因为我会避免进行进程间通信。对于这种工作方法,我需要完整的后台执行(包括运行循环),并在SpringBoard启动时启动并在异常退出时重新启动。

    有人对如何解决这个问题有任何建议吗?

2 个答案:

答案 0 :(得分:2)

首先感谢您使用AirFlow RAOP的惊人作品非常困难!

所以你能做的就是

<强> 1。创建后台任务处理程序为d​​ispatch_block_t,假设

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

<强> 2。定义此背景和前台任务处理程序的某处

        // 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。现在让我们在应用程序中处理委托后台模式(在您可以使用app .plist中的不同选项激活后台模式之前定义):

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

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

<强> 4。让我们看看背景异步任务选择器的作用

            -(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 (...) {
         }
        }

我知道这个解决方案很好但我知道有时会发生这种情况,iOS无论如何都会杀死应用后台任务。无论如何,如果用户突然在前台和后台之间切换应用程序,它将无限期地工作。

答案 1 :(得分:1)

部分答案。如果你将“voip”添加为后台模式,它将由SpringBoard自动启动。