我是一个名为AirFloat的Cydia调整的作者。一个实现AirPlay音频协议(以前称为AirTunes)的应用程序,可以将音频流式传输到您的iOS设备。 AirFloat最初是一个App Store应用程序,直到Apple从App Store启动它。
我已经在Cydia免费提供了它。目前,该应用程序完全像以前的App Store版本一样位于Cydia。因此,我得到了很多要求让它在后台运行的请求。但我无法让它发挥作用。
基本上我在考虑两种方法。
注意:AirFloat会在iOS锁定屏幕上显示当前播放的曲目。
创建一个守护程序,它运行实际的AirPlay实现,并使用notify与UI应用程序通信。这有效。的种类。它运行并播放音频,但MPNowPlayingInfoCenter似乎不能从非UI应用程序更新。此外,当守护程序以用户 mobile 运行时。
第二种方法是让它在UI应用程序中完成所有工作。但我没有被暂停的困难。我已将“所需背景模式”设置为音频和连续。服务器可能仍在运行,但随后Bonjour广告被关闭,因为运行循环在后台停止。其次,应该使用SpringBoard自动启动应用程序,并在异常退出时重新启动。
我个人更喜欢第二种方法,因为我会避免进行进程间通信。对于这种工作方法,我需要完整的后台执行(包括运行循环),并在SpringBoard启动时启动并在异常退出时重新启动。
有人对如何解决这个问题有任何建议吗?
答案 0 :(得分: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。现在让我们在应用程序中处理委托后台模式(在您可以使用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自动启动。