2013-03-16 126 views
2

我是一个名为AirFloat的Cydia调整的作者。实现AirPlay音频协议(以前称为AirTunes)的应用程序,使您可以将音频流到您的iOS设备。 AirFloat最初是一款App Store应用程序,直到Apple从App Store启动。越狱iOS设备应用程序:一致的后台操作

我从那以后在Cydia免费提供。目前该应用程序在Cydia中的位置与之前的App Store版本完全相同。由于这个原因,我得到了很多要求使其在后台工作的请求。但我无法让它工作。

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

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

  1. 创建一个后台程序,它运行实际的AirPlay的实现,并使用notify一个UI的应用程序进行通信。这工作。有点。它运行并播放音频,但MPNowPlayingInfoCenter似乎无法从非UI应用程序更新。当守护进程以用户移动运行时。

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

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

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

回答

2

首先感谢你与AirFlow RAOP的惊人的作品是相当困难的事情!

所以你可以做的是

1.创建一个后台任务处理为dispatch_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.现在让我们来看看h andle在应用程序委托的背景模式(定义之前,你可以在应用的.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

非常感谢!我将用即将发布的版本对此进行测试。谢谢! – Trenskow 2013-04-20 10:36:49

+0

从iOS7起,背景活动从600秒缩短。 (5分钟)至180秒。 (3分钟),所以调用doBackgroundTaskAsync(延迟*)的选择器必须在大于等于180.0f后被调用 – loretoparisi 2014-09-28 22:48:17

1

部分答案。如果您将“voip”添加为背景模式,它将由SpringBoard自动启动。

+0

This Works。它会自动启动。一切皆好。但必须有某种方式让它始终在后台运行。像MobilePhone.app或MobileMail.app一样。 – Trenskow 2013-03-17 15:02:56

相关问题