赞
踩
iOS AVPlayer 实现后台音乐播放
最近听网易云音乐,当进入后台时候,播放音乐的感觉,于是找到了AVPlayer与MPRemoteCommandCenter来实现后台音乐播放。
什么是MPNowPlayingInfoCenter呢?
MPNowPlayingInfoCenter:即时播放中心能够用于播放APP中正在播放的媒体信息. 播放的信息会显示在锁屏页面和多任务管理页面.如果用户是用airplay播放的话 会自动投射到相应的设备上.
app进入后台的情况?
当 App 退到后台时,会进入 suspend 状态,若此时在播放视频,则会自动暂停。我们需要实现的效果是,当 App 退到后台时,视频中的声音还能继续播放。另外,我们还同时实现视频的连续播放功能,和在锁屏界面控制视频播放的功能。
设置app支持后台运行,开启background modes。Required background modes -> App plays audio。也可以修改info.plist,在里面添加Required background modes,并在下面添加一项 App plays audio or streams audio/video using AirPlay。
在app启动的时候,在AppDelegate中设置AVAudioSessionCategoryPlayback
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// 告诉app支持后台播放
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive:YES error:nil];
return YES;
}
使用AVPlayer来播放音频mp3
// 初始化播放器和视图 self.player = [[AVPlayer alloc] init]; // 监听播放进度 __weak typeof(self) weakSelf = self; [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1, NSEC_PER_SEC) queue:NULL usingBlock:^(CMTime time) { [weakSelf updateProgressView]; }]; // 播放视频 [self playWithUrl:_urlList[_currentIndex]]; [self updateMusicInfo];
// 更新锁屏界面信息 - (void)refreshLockScreenInfo { if (!_player) { return; } // 1.获取锁屏中心 MPNowPlayingInfoCenter *playingInfoCenter = [MPNowPlayingInfoCenter defaultCenter]; // 初始化一个存放音乐信息的字典 NSMutableDictionary *playingInfoDict = [NSMutableDictionary dictionary]; // 2、设置歌曲名 [playingInfoDict setObject:[NSString stringWithFormat:@"歌曲%ld", (long)_currentIndex + 1] forKey:MPMediaItemPropertyTitle]; [playingInfoDict setObject:[NSString stringWithFormat:@"专辑%ld", (long)_currentIndex + 1] forKey:MPMediaItemPropertyAlbumTitle]; // 3、设置封面的图片 UIImage *image = [UIImage imageNamed:self.coverList[_currentIndex]]; if (image) { MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:image]; [playingInfoDict setObject:artwork forKey:MPMediaItemPropertyArtwork]; } // 4、设置歌曲的时长和已经消耗的时间 NSNumber *playbackDuration = @(CMTimeGetSeconds(_player.currentItem.duration)); NSNumber *elapsedPlaybackTime = @(CMTimeGetSeconds(_player.currentItem.currentTime)); if (!playbackDuration || !elapsedPlaybackTime) { return; } [playingInfoDict setObject:playbackDuration forKey:MPMediaItemPropertyPlaybackDuration]; [playingInfoDict setObject:elapsedPlaybackTime forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; [playingInfoDict setObject:@(_player.rate) forKey:MPNowPlayingInfoPropertyPlaybackRate]; //音乐信息赋值给获取锁屏中心的nowPlayingInfo属性 playingInfoCenter.nowPlayingInfo = playingInfoDict; }
- (void)addObservers { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(removePlayerOnPlayerLayer) name:UIApplicationDidEnterBackgroundNotification object:nil]; [center addObserver:self selector:@selector(resetPlayerToPlayerLayer) name:UIApplicationWillEnterForegroundNotification object:nil]; } - (void)removePlayerOnPlayerLayer { } - (void)resetPlayerToPlayerLayer { }
// 添加远程控制 - (void)createRemoteCommandCenter { MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter]; MPRemoteCommand *pauseCommand = [commandCenter pauseCommand]; [pauseCommand setEnabled:YES]; [pauseCommand addTarget:self action:@selector(remotePauseEvent)]; MPRemoteCommand *playCommand = [commandCenter playCommand]; [playCommand setEnabled:YES]; [playCommand addTarget:self action:@selector(remotePlayEvent)]; MPRemoteCommand *nextCommand = [commandCenter nextTrackCommand]; [nextCommand setEnabled:YES]; [nextCommand addTarget:self action:@selector(remoteNextEvent)]; MPRemoteCommand *previousCommand = [commandCenter previousTrackCommand]; [previousCommand setEnabled:YES]; [previousCommand addTarget:self action:@selector(remotePreviousEvent)]; if (@available(iOS 9.1, *)) { MPRemoteCommand *changePlaybackPositionCommand = [commandCenter changePlaybackPositionCommand]; [changePlaybackPositionCommand setEnabled:YES]; [changePlaybackPositionCommand addTarget:self action:@selector(remoteChangePlaybackPosition:)]; } } - (void)remotePlayEvent { [self playVideo]; } - (void)remotePauseEvent { [self pauseVideo]; } - (void)remoteNextEvent { [self playNextVideo]; } - (void)remotePreviousEvent { [self playPreviousVideo]; } - (void)remoteChangePlaybackPosition:(MPRemoteCommandEvent *)event { MPChangePlaybackPositionCommandEvent * playbackPositionEvent = (MPChangePlaybackPositionCommandEvent *)event; [self seekToTime:playbackPositionEvent.positionTime]; }
- (void)updateMusicInfo {
self.teamAnnounceView.nameLabel.text = self.musicNameList[_currentIndex];
[UIView transitionWithView:self.teamAnnounceView.bgImageView duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
self.teamAnnounceView.bgImageView.image = [UIImage imageNamed:self.coverList[_currentIndex]];
} completion:nil];
[UIView transitionWithView:self.teamAnnounceView.coverImageView duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
self.teamAnnounceView.coverImageView.image = [UIImage imageNamed:self.coverList[_currentIndex]];
} completion:nil];
}
// 更新进度条进度 - (void)updateProgressView { self.currentDuration = CMTimeGetSeconds(_player.currentItem.duration); CGFloat progress = CMTimeGetSeconds(_player.currentItem.currentTime) / _currentDuration; // 可以通过监听playerItem结束的通知来切换歌曲 // 当结束时需要移除对当前playerItem的监听,然后添加下一个playerItem的监听 // 这里直接通过判断进度条是否完成,来切换歌曲 // // 监听播放通知的写法如下: // [[NSNotificationCenter defaultCenter] addObserver:self // selector:@selector(playerItemDidReachEnd:) // name:AVPlayerItemDidPlayToEndTimeNotification // object:self.playerItem]; if (progress == 1.0f) { [self playNextVideo]; } else { [self.teamAnnounceView.progressSlider setValue:progress]; } }
// 拖动进度条监听
- (void)videoProgressDidChanged:(UISlider *)sender {
if (sender.value == 1.0f) {
[self playNextVideo];
return;
}
NSTimeInterval duration = CMTimeGetSeconds(_player.currentItem.duration);
[self seekToTime:duration * sender.value];
}
- (void)removeCommandCenterTargets
{
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
[[commandCenter playCommand] removeTarget:self];
[[commandCenter pauseCommand] removeTarget:self];
[[commandCenter nextTrackCommand] removeTarget:self];
[[commandCenter previousTrackCommand] removeTarget:self];
if (@available(iOS 9.1, *)) {
[commandCenter.changePlaybackPositionCommand removeTarget:self];
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。