I am using AVPlayer for music playback. My problem is that after an incoming call, the player won't resume. How do I handle this when an incoming call comes?
I am using AVPlayer for music playback. My problem is that after an incoming call, the player won't resume. How do I handle this when an incoming call comes?
Hi everyone who read this. Want to share my experience with AVAudioSessionInterruptionNotification. It drove me crazy. I spent a day to find a solution. I tried everything written above and nothing helped. iOS 13.2.3. So for some reason this notification is not working properly with AVAudioSessionCategoryPlayback. And the fix for me was just to replace it with AVAudioSessionCategoryPlayAndRecord and I started to receive the AVAudioSessionInterruptionTypeEnded See example below:
-(void)setupAudioSession {
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeDefault error:nil];
[[AVAudioSession sharedInstance] setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
}
After that register your observer, like this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionHandleIntrruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
And actually implement the interruption method:
- (void)audioSessionHandleIntrruption:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo;
int interruptionType = [userInfo[AVAudioSessionInterruptionTypeKey] intValue];
if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
//Interruption begun
} else if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
int interruptionOption = [userInfo[AVAudioSessionInterruptionOptionKey] intValue];
BOOL shouldResumePlayback = interruptionOption == AVAudioSessionInterruptionOptionShouldResume;
if (shouldResumePlayback) {
//Resume playback if needed
}
}
}
Hope this could save to someone a lot of time.
I have to wait for 2 seconds to make it work.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.player.play()
}
The whole func:
func playerInterruption(notification: NSNotification) {
guard let userInfo = notification.userInfo,
let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
let type = AVAudioSessionInterruptionType(rawValue: typeValue) else {
return
}
if type == .began {
// Interruption began, take appropriate actions (save state, update user interface)
player.pause()
}
else if type == .ended {
guard let optionsValue =
userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else {
return
}
let options = AVAudioSessionInterruptionOptions(rawValue: optionsValue)
if options.contains(.shouldResume) {
// Interruption Ended - playback should resume
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.player.play()
}
}
}
}
I was getting the same problem in "AVAudioPlayer" controller. Using "AVAudioSession.interruptionNotification" we can resume audio playing once interruption ended even though audio playing in the background.
@objc func interruptionNotification(notification: Notification) {
guard let type = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt,
let interruption = AVAudioSession.InterruptionType(rawValue: type) else {
return
}
if interruption == .began{
print("Pause audio....")
self.player?.pause()
do {
try AVAudioSession.sharedInstance().setActive(false)
print("AVAudioSession is inactive")
} catch let error as NSError {
print(error.localizedDescription)
}
}
if interruption == .ended{
print("Play audio....")
do {
try AVAudioSession.sharedInstance().setActive(true)
print("AVAudioSession is Active again")
self.player?.play()
} catch let error as NSError {
print(error.localizedDescription)
}
}
}
Here first you need to InActive AVAudioSession when it's interrupted and Active AVAudioSession once interruption ended. It's working perfectly please try it!