I'm testing my app in XCode 6 and find an issue with AVAudioSession in iOS8.
When I call
[[AVAudioSession sharedInstance] setActive:NO error:nil];
I get the following error message:
AVAudioSession.mm:623: -[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
In AVAudioSession.h, it says
Note that this method will throw an exception in apps linked on or after iOS 8 if the session is set inactive while it has running or paused I/O (e.g. audio queues, players, recorders, converters, remote I/Os, etc.).
But I'm not sure how can I check if there's running I/O and how can I dispose all when I need to reset the audio session.
I solved this problem, inserting this code in the method of AVAudioPlayerDelegate.
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
[audioPlayer stop];
[audioPlayer prepareToPlay];
}
where audioPlayer is a variable declared in the header of my class.
the instruction prepareToPlay should resolve your problem!
Be warned. If you are playing a movie (even with no sound and the audio track removed) then it will still create an I/O thread which will always cause the above error to be thrown.
I'm using AVAudioEngine and AVAudioPlayerNode to play sounds. I meet the same problem. My environment is iOS 10.
I use AVAudioSession.sharedInstance()
to handle AVAudioSession. When I run my app in simulator everything is fine, but when I switch it to my device. It failed.
I suppose that I'm using the same session to handle recording and playing. So it may cause some strange issues. In my case, I record the sound and delay 1s to play it. So when I use stopRecordingAudio()
, I add this piece of code :
if audioEngine.running {
audioEngine = AVAudioEngine() // var audioEngine = AVAudioEngine()
try! AVAudioSession.sharedInstance().setActive(false)
}
After redefining audioEngine, audioEngine had been forced to stop and session was released. Crash is never happened again.
Hope this message could help you.
Swift 5, IOS 12
I use AVPlayer, it does not have a prepareToPlay method. Therefore, Alessio Campanelli's answer does not solve my problem. But I noticed the following
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
After you call the pause method, the player plays the audio file for a while. Although other properties say that it is in a pause. So the only solution I found is
player.pause()
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
do {
try AVAudioSession.sharedInstance().setActive(false)
} catch let error {
print(error)
}
}
In fact, even 0.1 seconds is sufficient. This is a bad way, but I could not find anything better. If anyone knows how to check when the player stops playing the audio file, let me know.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With