When using AVPlayer to play audio from an url it will
discontinue to play when for example disconnecting from wifi.
[player play];
Does not resume the AVPlayer
player.rate // Value is 1.0
player.currentItem.isPlaybackLikelyToKeepUp // Value is YES
player.status // Value is AVPlayerStatusReadyToPlay
player.error // Value is nil
But the player is not playing any audio.
How do I handle a disconnect from AVPlayer, for reconnecting the AVPlayer
and start playing again?
In order to handle network changes, you have to add an observer for AVPlayerItemFailedToPlayToEndTimeNotification
.
- (void) playURL:(NSURL *)url
{
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemFailedToPlayToEndTime:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
self.player = [AVPlayer playerWithPlayerItem:playerItem];
[self.player play];
}
- (void) playerItemFailedToPlayToEndTime:(NSNotification *)notification
{
NSError *error = notification.userInfo[AVPlayerItemFailedToPlayToEndTimeErrorKey];
// Handle error ...
}
0xced's answer for Swift 3/4:
var playerItem: AVPlayerItem?
var player: AVPlayer?
func instantiatePlayer(_ url: URL) {
self.playerItem = AVPlayerItem(url: url)
self.player = AVPlayer(playerItem: self.playerItem)
NotificationCenter.default.addObserver(self, selector: #selector(playerItemFailedToPlay(_:)), name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime, object: nil)
}
func playerItemFailedToPlay(_ notification: Notification) {
let error = notification.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error
}
You should add observer for AVPlayerItemPlaybackStalledNotification.
AVPlayerItemFailedToPlayToEndTimeNotification has no value for me on this problem.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackStalled:) name:AVPlayerItemPlaybackStalledNotification object:trackItem];
As the doc says, file-based playback does not continue if necessary streaming media wasn’t delivered in a timely fashion over a network.
The notification’s object is the AVPlayerItem instance whose playback
was unable to continue because the necessary streaming media wasn’t
delivered in a timely fashion over a network. Playback of streaming
media continues once a sufficient amount of data is delivered.
File-based playback does not continue.
This explained why AVPlayer can resume HLS streams after network switch, but cannot do the same if I use AVPlayer to play TuneIn resources which is file-based.
Then the answer becomes simple.
- (void)playbackStalled:(NSNotification *)notification {
if ([self isFileBased:streamUri]) {
// Restart playback
NSURL *url = [NSURL URLWithString:streamUri];
AVPlayerItem *trackItem = [AVPlayerItem playerItemWithURL:url];
AVPlayer *mediaPlayer = [AVPlayer playerWithPlayerItem:trackItem];
[self registerObservers:trackItem player:mediaPlayer];
[mediaPlayer play];
}
}
Further reading on discussion of automaticallyWaitsToMinimizeStalling.