iOS8 AVAudioSession setActive 错误

42

我正在XCode 6中测试我的应用程序,并发现在iOS8中使用AVAudioSession时出现了问题。

当我调用

[[AVAudioSession sharedInstance] setActive:NO error:nil];

我会得到以下错误消息:

AVAudioSession.mm:623:-[AVAudioSession setActive:withOptions:error:]: 停用具有正在运行的I/O的音频会话。在停用音频会话之前,所有I/O都应该停止或暂停。

在AVAudioSession.h中,它说

请注意,如果在运行或暂停I/O(例如音频队列、播放器、录制器、转换器、远程 I/O等)的情况下将会话设置为非活动状态,则此方法将在iOS 8及其之后链接的应用程序中引发异常。

但我不确定如何检查是否存在正在运行的I/O以及在需要重置音频会话时如何处理所有内容。


1
你能解释一下背景,并给出一个使用案例,为什么要检查是否有正在运行的I/O吗? - vladof81
如果没有这样的错误,我就不需要检查正在运行的I/O。所以情况是,当我调用setActive:NO时,我想确保没有正在运行的I/O。 - xialin
1
@Anton 不是一个修复方案,但我发现我正在使用的另一个库 - pjsip - 在更低的级别上控制启动/停止音频会话。所以,我处理它的方式是如果我知道音频会话已经设置好了,就避免调用 setActive。这只是我的情况。你需要弄清楚是否有其他东西与你的应用程序共享音频会话。 - xialin
5个回答

9
我在AVAudioPlayerDelegate方法中插入了以下代码,成功解决了这个问题。
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
  [audioPlayer stop];
  [audioPlayer prepareToPlay];
}

audioPlayer是我类中头文件声明的变量。

执行prepareToPlay指令应该可以解决你的问题!


@d4Rk 在我的iOS 9.3上可以:[audioPlayer stop]; [audioPlayer prepareToPlay]; [[AVAudioSession sharedInstance] setActive:NO error:nil]; - Alejandro Iván
在我的情况下,视频播放器(AVPlayer)也会出现相同的错误,因为它根本没有这些方法。 - Vyachaslav Gerchicov

1
我正在使用AVAudioEngine和AVAudioPlayerNode播放声音。我遇到了同样的问题。我的环境是iOS 10。
我使用AVAudioSession.sharedInstance()来处理AVAudioSession。当我在模拟器中运行我的应用程序时,一切都很好,但当我将其切换到我的设备时,它失败了。
我认为我正在使用相同的会话来处理录制和播放。因此,可能会导致一些奇怪的问题。在我的情况下,我录制声音并延迟1秒钟才播放。因此,当我使用stopRecordingAudio()时,我添加了这段代码:
if audioEngine.running {
    audioEngine = AVAudioEngine() // var audioEngine = AVAudioEngine()
    try! AVAudioSession.sharedInstance().setActive(false)
}

重新定义了audioEngine后,audioEngine被强制停止并释放了session。之后再也没有出现过崩溃情况。希望这条信息能对你有所帮助。

1

Swift 5,IOS 12

我使用AVPlayer,它没有prepareToPlay方法。因此,Alessio Campanelli的answer不能解决我的问题。 但是我注意到以下内容

player.pause()

print("currentTime:",  player.currentTime().seconds) //currentTime: 4.258164744
print("status:", player.status.rawValue) //status: 1 (readyToPlay)
print("timeControlStatus:", player.timeControlStatus.rawValue) //timeControlStatus: 0 (paused)
print("rate:", player.rate) //rate: 0.0

sleep(1)

print("currentTime:",  player.currentTime().seconds) //currentTime: 4.261325767
print("status:", player.status.rawValue) //status: 1 (readyToPlay)
print("timeControlStatus:", player.timeControlStatus.rawValue) //timeControlStatus: 0 (paused)
print("rate:", player.rate) //rate: 0.0

在调用pause方法后,播放器会暂停一段时间的音频文件。尽管其他属性表明它处于暂停状态。因此我找到的唯一解决方案是:
player.pause()
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
    do {
        try AVAudioSession.sharedInstance().setActive(false)
    } catch let error {
        print(error)
    }
}

事实上,即使0.1秒也足够了。这是一种不好的方法,但我找不到更好的方法。如果有人知道如何检查播放器何时停止播放音频文件,请告诉我。

1

请注意,如果您正在播放电影(即使没有声音并且已删除音频轨道),它仍会创建I/O线程,这将始终导致上述错误被抛出。


1

在AVAudioSession setActive NO之前,我暂停了我的AVplayer;

[self.audioPlayer pause]; [[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];


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