在iOS4中进入后台以播放音频

18

在谈论后台播放音频时,文档写得相当糟糕。它给人的印象是,为了让当前正在播放的音频继续播放,只需将键/值对添加到info.plist文件中,就可以完成这个奇迹。

然而,情况并非如此。例如,如果我播放的mp3长达2分钟,显然音频足够长,可以在我按下主页按钮将应用程序发送到后台后继续播放。问题在于,即使我在info.plist文件中有那个键/值对,它仍会暂停音频,然后在我切换回应用程序时恢复播放。

Apple声明所有音频支持后台,声音应该在播放结束之前继续播放,然后Apple将挂起您的应用程序。

因此,我的问题是:他们在做什么,我漏掉了什么?我是否也必须以某种方式使用他们的新委托或在applicationDidEnterBackground上调用音频?对我来说,这没有意义,因为我不保存状态(他们使用快速应用程序切换为我保存状态)或在后台处理除音频之外的任何内容,但他们称音频应该自动处理。


抱歉,我的拼写课是从丹·奎尔那里学的 :) - iwasrobbed
2个回答

22

在开始播放歌曲之前(无论是否在前台),您还需要调用beginBackgroundTaskWithExpirationHandler:方法,并在结束时使用endBackgroundTask。

这告诉iOS,即使您的应用程序被放入后台,您也希望能够继续处理。它不会创建新的任务或线程,只是向iOS发出一个标志,表示您要继续运行。即使没有这个方法,音频也会播放完成,但是当它完成后,如果您想要开始另一首歌曲,则必须能够在后台运行。

您可以像这样使用它:

// ivar, initialized to UIBackgroundTaskInvalid in awakeFromNib
UIBackgroundTaskIdentifier bgTaskId; 

开始音频播放时,我们会保存后台任务的ID:

if ([audioPlayer play]) {
  bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}

现在,即使我们被放到后台,由于我们已经告诉iOS我们正在执行需要继续的任务,因此仍将发生audioPlayerDidFinishPlaying:回调。这样,我们就能够获得回调并开始下一个音频文件。

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)success
{
    UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;

    if (self.haveMoreAudioToPlay) {
        newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
        [self playNextAudioFile];
    }

    if (bgTaskId != UIBackgroundTaskInvalid) {
        [[UIApplication sharedApplication] endBackgroundTask: bgTaskId];
    }

    bgTaskId = newTaskId;
}      

2
你真的需要通过完成任务来启动后台音频吗?这与WWDC 2010有关该主题的视频(“Session 109-采用iPhone OS上的多任务处理,第2部分”)中所述的材料相反,在约24分钟时,他们展示了他们的avTouch应用程序被转换为背景音频,关键是要在后台防止进一步GPU使用,因为那会导致应用程序停止。这是通过注册UIApplicationDidEnterBackgroundNotification并在后台防止GPU使用来完成的。 - Joost Schuur
4
如果你想在后台切换音轨,就需要这个功能(这并不完全是原来的问题),否则当音频播放结束时,你的应用将被挂起。请参见此讨论 - progrmr
@iWasRobbed:我发现在这种情况下,除了使用GCD之外,你还应该使用dispatch_async(dispatch_get_global_queue(0, 0), ^{你的音频播放代码});。 - Alex1987
@progrmr,看起来你不是唯一一个给出这个答案的人,但我已经在Spotify框架之上实现了一个音乐应用程序,并且它可以正常工作(即使在后台切换歌曲时)甚至不需要初始化后台任务。要么我做错了什么,只有在以后才能发现,要么可能自2010年(iOS 4)以来,iOS 6中的后台音频工作方式已经发生了变化? - Alex
1
@Andrei,我已经好几年没有处理后台音频了,所以我无法确定现在什么有效。自2010年以来,很多东西都发生了变化。 - progrmr
显示剩余5条评论

17

文档中缺少的一部分是您需要设置音频会话。

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

加上那个,你就可以开始了。


至少有人意识到了! :) - Joshua Weinberg
Josh,你已经得到了勾号,不用担心 :) 它运行得非常好。stackoverflow在我的慢网络上出了问题,所以我不得不关闭浏览器来解决它。 - iwasrobbed
只是随便玩玩 :) 如果您觉得文档中没有清楚地说明它依赖于音频会话,那么您应该提交一个关于文档错误的报告。 - Joshua Weinberg
好的,我会注意的,这样我们就可以避免其他人的头痛了。再次感谢。 - iwasrobbed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接