永远在后台运行iOS应用程序

时间:2013-09-18 11:55:55

标签: ios audio background

我有一个要求,我的应用程序连接到国家/地区频道(美国)并开始播放来自频道的记录。这基本上是一个由用户运行的频道,用户将他们的记录上传到频道,然后逐个播放。连接到频道的用户,他们开始收听频道。

服务器向iOS应用程序发送需要通过套接字播放的记录的URL,iOS应用程序创建AVQueuePlayer以逐个播放URL(使用AVPlayerItems)。

如果我将应用程序保留在后台,当通道充满了大约1天左右的记录时,应用程序会继续运行并继续逐个播放所有记录。我知道AVQueuePlayer负责运行应用程序,而不会因为接收到要玩的新玩家项目而被杀死。

但是如果频道中没有记录,并且如果用户连接到频道,那么如果应用的空闲时间超过10分钟,则app不会在后台播放记录。

我编写了带有后台任务标识符的代码,这使得我的套接字连接保持打开状态,以便始终可以接收新的记录URL。

我在设备中看到了"AppName(my app) has active assertions beyond permitted time"

中的一些崩溃报告

我可以知道这里发生了什么错误。

我也在发布后台任务代码

- (void)keepBroadcastPersistentConnection {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    if(self._bgTaskIdentifier)
        self._bgTaskIdentifier = UIBackgroundTaskInvalid;
    self._bgTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{

        [[UIApplication sharedApplication] endBackgroundTask:self._bgTaskIdentifier];
        self._bgTaskIdentifier = UIBackgroundTaskInvalid;
        CGLog(@"========================================end bg task at time %@", [NSDate date]);
        CGLog(@"Time taken by app to run in bg is %f seconds", [[NSDate date] timeIntervalSinceDate:self.date]);
    }];

    [[BroadcastSocketConnecter sharedSocketConnecter].socketIO sendHeartbeat]; // this keep the socket alive
    self.date = [NSDate date];
    CGLog(@"========================================begin bg task at time %@", self.date);
});
}

由于

1 个答案:

答案 0 :(得分:4)

来自音频会话节目指南:

<强> Why a Default Audio Session Usually Isn’t What You Want

  

场景3.您编写了一个使用音频的流媒体广播应用   用于播放的队列服务。当用户正在收听时,打个电话   按预期到达并停止您的声音。用户选择忽略   通话和解除警报。用户再次点击播放以恢复   音乐流,但没有任何反应。要恢复播放,请用户   必须退出您的应用程序并重新启动它。

     

要正常处理音频队列的中断,请执行   委托方法或写一个音频会话回调函数来允许   你的应用程序继续自动播放或允许   用户手动恢复播放。请参阅“Responding to Audio Session Interruptions。”

很快,解决方案是实施AVAudioSessionDelegate协议'beginInterruptionendInterruption方法。但是,{6}中不推荐使用delegate类的AvAudioSession属性,而应使用Notifications。即,您对AVAudioSessionInterruptionNotification

感兴趣

解决方案。根据这个故事,如果播放停止,那么您应该再次明确激活音频会话,以防止您的应用被终止。

以下是委托实现的来源,但逻辑对通知没有太大变化,所以我觉得它仍然是一个很好的信息来源。

- (void) beginInterruption {
    if (playing) {
        playing = NO;
        interruptedWhilePlaying = YES;
        [self updateUserInterface];
    }
}

NSError *activationError = nil;
- (void) endInterruption {
    if (interruptedWhilePlaying) {
        BOOL success = [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
        if (!success) { /* handle the error in activationError */ }
        [player play];
        playing = YES;
        interruptedWhilePlaying = NO;
        [self updateUserInterface];
    }
}

旧的回复仍然有效但不是优雅的解决方案

您无法在后台开始播放音频。这个答案解释了我在上面评论中提到的内容:https://stackoverflow.com/a/16568437/768935使用AudioSession进行操作似乎对此政策没有影响。

作为解决方案,您需要继续播放音频。如果队列中没有项目,则插入“静音”音轨。但是,我怀疑使用此技巧的应用程序将在App Store中被接受。如果应用程序再次启动,最好通知用户音频播放将恢复。