我有一个 AVAudioPlayer 需要在后台继续运行。
音频在 plist 中设置为背景模式,并且在启动时运行:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[[RootController shared].view becomeFirstResponder];
AVAudioSession* session = [AVAudioSession sharedInstance];
[session setDelegate: self];
[session setActive:YES error:nil];
[session setCategory: AVAudioSessionCategoryPlayback error:nil];
- (BOOL)canBecomeFirstResponder { return YES; }
问题
有时 AVAudioPlayer 会进入这种奇怪的状态:
- 正在播放,但是状态栏的播放图标消失了
- 如果我暂停然后播放,图标可能会显示一秒钟,然后消失
- 关键是 - 如果我在播放时调用
setCurrentTime
,播放图标会显示并保持不变
我已经为此投入了大约 20 个小时,希望有任何想法。
最佳答案
漏洞描述
如果您正在播放 AVAudioPlayer
然后您创建 AVPlayer
,播放图标将消失。显然 AVPlayer
立即获得优先权,因为它尚未播放,播放图标从状态栏中消失。
这会导致一些严重的问题:
- 如果应用程序在后台,iOS 将在 5 秒内关闭您的 AVAudioPlayer(因为它没有意识到您正在播放音频)
- 即使正在播放音频,iOS Remote 也会显示播放按钮
- 状态栏中没有显示播放图标
解决方法
首先,如果您不必使用 AVPlayer
,那就别用。我使用它是因为我需要在不先下载的情况下播放远程 MP3。我以前用这个AudioStreamer类但放弃了,因为当流断开连接时它会弹出警报以及我无法修复的其他一些错误。
因此,如果您受困于 AVPlayer,只有一种方法可以重新连接您的 AVAudioPlayer
的播放状态。 如果您在 AVAudioPlayer
上调用 setCurrentTime
,那么它会神奇地将自己重新关联为应用程序的当前播放器。因此,您需要在初始化任何 AVPlayer
之后以及在 AVAudioPlayer
上恢复播放时调用它。
我决定将 AVAudioPlayer 子类化,这样我就可以在全局列表中注册它(当它被初始化时)并在它被释放时注销它。我还覆盖了 play 方法,以便任何恢复播放的调用也将调用 setCurrentTime。然后我将 AVPlayer 子类化,以便在任何时候初始化一个,所有事件的 AVAudioPlayer 都会自己调用 setCurrentTime。最后一件事 - 您必须在短时间(可能是 1 秒)延迟后调用 setCurrentTime
,否则它将无效。
不是开玩笑,这是将近 40 小时的故障排除的结果。
关于ios - AVAudioPlayer 丢失 "Playing"状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11894600/