I'm using AVPlayer to play remote audio and video files via urls. With my current implementation, everything is fine on iOS8.4 and higher, the only problem is on iOS8.3 where the videos appear but the audio runs in the background.
I create an AVURLAsset
like this:
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:soundURL options:nil];
NSArray *keys = @[@"playable", @"duration"];
avAsset = asset;
[avAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {
NSError *error = nil;
AVKeyValueStatus playableStatus = [asset statusOfValueForKey:@"playable" error:&error];
AVKeyValueStatus durationStatus = [asset statusOfValueForKey:@"duration" error:&error];
switch (playableStatus) {
case AVKeyValueStatusLoaded:{
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:avAsset];
if (!mediaPlayer) {
mediaPlayer = [[AVPlayer alloc] initWithPlayerItem:item];
mediaPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
[item addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[mediaPlayer currentItem]];
} else {
if (isNewURL) {
[mediaPlayer replaceCurrentItemWithPlayerItem:item];
}
}
[mediaPlayer seekToTime:kCMTimeZero];
break;
}
case AVKeyValueStatusLoading:
[SBNotificationMessenger notifyMessage:@"Buffering..."];
break;
case AVKeyValueStatusFailed:
[SBNotificationMessenger notifyError:error.localizedDescription];
break;
default:
break;
}
if (durationStatus == AVKeyValueStatusLoaded) {
dispatch_async(dispatch_get_main_queue(), ^{
startedPlaying(YES);
});
}
}];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == mediaPlayer.currentItem) {
if ([keyPath isEqualToString:@"status"]) {
[self handleMediaPlayerStatus];
} else if ([keyPath isEqualToString:@"rate"]) {
[self handleMediaPlayerRateStatus];
}
}
}
- (void)handleMediaPlayerStatus
{
if (mediaPlayer.status == AVPlayerStatusFailed) {
DDLogError(@"Media player status: failed!");
} else if (mediaPlayer.status == AVPlayerStatusReadyToPlay) {
DDLogInfo(@"Media player status: ready!");
[mediaPlayer play];
} else if (mediaPlayer.status == AVPlayerItemStatusUnknown) {
DDLogInfo(@"Media player status: unknown");
}
}