iOS 8在10分钟后停止在后台播放音频

s1m*_*m0n 11 audio cocoa-touch avfoundation ios ios8

我有一个从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;
}
Run Code Online (Sandbox Code Playgroud)

Hen*_*rik 7

我在iOS 8.0.2下遇到了同样的问题.我的远程音频源以mp3播放.似乎内部错误导致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];
        }
    }
Run Code Online (Sandbox Code Playgroud)

这种方式似乎不可靠,因为在AVPlayerItem的状态发生变化之前可能存在巨大的时间延迟 - 如果它发生了变化.

我通过observeValueForKeyPath调试,发现AVPlayerItem的状态更改为AVErrorMediaServicesWereReset并设置了错误代码-11819.

由于我遇到了AVErrorMediaServicesWereReset错误,我研究了导致此错误的原因 - 这是AVAudioSession疯了.参考Apple 的技术问答,您应该注册AVAudioSessionMediaServicesWereResetNotifications.把它放在代码中的某个地方:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionWasReset:) name:AVAudioSessionMediaServicesWereResetNotification object:nil];
Run Code Online (Sandbox Code Playgroud)

然后添加此方法:

- (void)audioSessionWasReset:(NSNotification *)notification {
    [self recoverFromError];
}
Run Code Online (Sandbox Code Playgroud)

在recoverFromError方法中,尝试以下操作之一:

  • 显示一个警报,描述iOS 8下的问题并且需要重新启动流
  • 通过再次激活AVAudioSession重新启动流并使用新的AVPlayerItem实例化新的AVPlayer实例

目前,这是我知道如何处理它的唯一方式.问题是为什么AudioSession重新启动.

更新 iOS 8.1接缝的发布已经解决了这个问题.


Luk*_*lor 5

我也经历过同样的问题,并且已经在运行iOS 8.0.2的iPhone 5s和运行iOS 8.1 beta 2的iPad Mini Retina上进行了测试,这意味着这在即将推出的测试版中并未修复.大约30分钟后,两人都停止播放音频.

当AVPlayer.status == AVPlayerItemStatusFailed时,您可以注销AVPlayer.status以获取有关错误的更多详细信息.我收到:

Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action" UserInfo=0x178a75bc0 {NSLocalizedDescription=Cannot Complete Action, NSLocalizedRecoverySuggestion=Try again later.}

即使在尝试捕获并停止并启动我的播放器时,我也会收到致命错误,告诉我AVPlayer已被解除分配.此时,可能值得尝试按照Hendrik的建议重新初始化新的AVPlayer实例.这仍然无法解决当您尝试重新初始化时音频将临时切断的事实.您的AVPlayer也可能会在重新初始化之前收到通知,这意味着您将收到致命错误; 这远非永久性修复.

也许其他人会有更多的运气,可以提供更具体的解决方案.与此同时,我也向Apple报告了这个错误.

2014年10月15日更新: Apple以此状态关闭了我的错误报告:重复18152675(已结束).