我有一个从SHOUTcast服务器播放流音频的应用程序.当应用程序在前台并且禁用自动锁定时,一切正常.该应用程序还可以在后台播放音频,此功能在iOS 6和iOS 7上一直运行正常.但是现在我的用户报告说,在升级到iOS 8后约10分钟后,背景音频会停止.
我可以通过在iOS 8上运行应用程序自己来重现问题.由于应用程序本身很复杂,所以我做了一个简单的演示来显示问题.我使用Xcode 6,Base SDK设置为iOS 8.我已经在我的Info.plist中添加了UIBackgroundModes的音频.有人知道下面的代码有什么问题吗?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *streamingURL = [NSURL URLWithString:@"http://www.radiofmgold.be/stream.PHP?ext=pls"]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:streamingURL]; [self setPlayerItem:playerItem]; AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem]; [player setAllowsExternalPlayback:NO]; [self setPlayer:player]; [player play]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; [[AVAudioSession sharedInstance] setActive: YES error: nil]; return YES; }
解决方法
我在iOS 8.0.2下遇到了同样的问题.我的远程音频源在mp3播放.
似乎内部错误导致AVAudioSession重新启动.你可以用不同的方式来处理它:
似乎内部错误导致AVAudioSession重新启动.你可以用不同的方式来处理它:
您可以观察AVPlayerItem的状态.
void* YourAudioControllerItemStatusContext = "YourAudioControllerItemStatusContext"; ... @implementation YourAudioController ... - (void)playStream { ... AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:streamUrl]; [item addObserver:self forKeyPath:@"status" options:0 context:MJAudioControllerItemStatusContext]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == YourAudioControllerItemStatusContext) { AVPlayerItem *item = object; if (item.status == AVPlayerItemStatusFailed) { [self recoverFromError]; } }
这种方式看起来不是可靠的,因为在AVPlayerItem的状态发生变化之前可能会有很大的时间延迟 – 如果它改变了.
我通过observeValueForKeyPath调试,发现AVPlayerItem的状态更改为AVErrorMediaServicesWereReset,并且具有错误代码-11819设置.
由于我经历了AVErrorMediaServicesWereReset错误,我研究了什么导致这个错误 – 这是AVAudioSession疯了.参考Apple的Technical Q&A,您应该注册AVAudioSessionMediaServicesWereResetNotifications.把你的代码放在某个地方:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionWasReset:) name:AVAudioSessionMediaServicesWereResetNotification object:nil];
- (void)audioSessionWasReset:(NSNotification *)notification { [self recoverFromError]; }
在recoverFromError方法中,尝试以下方法之一:
>显示一条警告,描述在iOS 8下的问题,流需要重新启动
>通过再次设置AVAudioSession激活流并通过新的AVPlayerItem实例化一个新的AVPlayer实例
在这个时刻,我知道如何处理它的唯一方法.问题是为什么AudioSession正在重新启动.
UPDATEiOS 8.1接缝的发布已经解决了这个问题.