1、音频想要支持后台播放,需要进行一些设置,申请响应的后台权限:附后台播放设置链接
2、因为APP内有视频课程,所以申请了后台权限以后视频也可以后台、锁屏播放(播放视频的声音),这里需要根据自己的需求单独进行处理。
3、申请后台、锁屏播放以后,主要的问题就是通知中心的控制问题,特别是当视频和音频同时存在时,需要进行相应的处理,才能展示出想要的效果。
MPNowPlayingInfoCenter //更新控制信息
MPRemoteCommandCenter //进行远程控制
//文章更新:MPRemoteCommandCenter
AudioPlayer 与VideoPlayer 与 后台播放
出现的问题如下:
(1)APP内播放VideoPlayer,发现没有在Video相关的页面写“MPNowPlayingInfoCenter”与“MPRemoteCommandCenter”相关的代码,通知中心居然有了响应的播放信息,而且远程控制居然还管用。
(2)APP内首次播放过Video以后,再播放Audio,发现通知中心的音乐控制台居然不显示了,再次播放Video也不显示
出现这个问题的主要原因出在AVPlayerViewController,IOS 10增加了一个属性
/*!
@property updatesNowPlayingInfoCenter
@abstract Whether or not the now playing info center should be updated. Default is YES.
*/
@property (nonatomic) BOOL updatesNowPlayingInfoCenter API_AVAILABLE(ios(10.0));
正是因为有了这个属性,当我们播放Video时,才会出现自动更新NowPlayingInfoCenter,在锁屏、后台时,才会显示出相关的播放信息
所以,当我们需要在APP内播放视频时,设置属性
AVPlayerViewController *playerVC =[[AVPlayerViewController alloc] init];
playerVC.updatesNowPlayingInfoCenter = NO;
这样播放视频的时候,就不会更新NowPlayingInfoCenter的相关信息。
(3)然后,嗯嗯,又出现了新的问题
在APP内,首先播放一个音频,NowPlayingInfoCenter更新了有关的信息。在音频播放中,我们点击播放了一个视频,音频被暂停(产品需求)。然后发现,NowPlayingInfoCenter还是音频的相关信息,而且进度条还是前进,播放时间还在更新。由此可以推断,NowPlayingInfoCenter是自己有一个Timer,进行进度条和播放时间的更新。
我参考了市面上几款常见的APP,看看他们是怎么做的(操作完全相同,先在APP内播放一个音频,然后在音频播放时,再播放一个视频)
网易云音乐:NowPlayingInfoCenter 保持着上一个音频的相关音乐信息和进度,播放按钮显示“播放中”,但是播放时间和进度条 不继续变化。点击播放控制按钮,按钮变为“暂停”,再点击,视频声音停止,继续播放音频音乐。

喜马拉雅:NowPlayingInfoCenter 保存着上一个音频相关额信息,进度条和播放时间仍在持续更新中,嗯嗯,就是这样的。播放按钮显示“播放中”,点击播放控制按钮,按钮变为“暂停”,视频声音停止,继续播放音频音乐。

知乎:知乎有视频课程与音频课程,可以试听;NowPlayingInfoCenter 不显示播放信息,进度条和播放时间也不显示。播放按钮显示“播放中”,点击播放控制按钮,按钮变为“暂停”,再点击,没有播放音频音乐,按钮短暂变换为“播放”,然后变成“暂停”。

我们自己的实现效果:NowPlayingInfoCenter 不显示播放信息,进度条和播放时间也不显示。播放控制按钮也不可点击。

在视频点击播放时,调用下面的代码:
- (void)setupLockScreenControlInfo {
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
// 锁屏播放
MPRemoteCommand *playCommand = commandCenter.playCommand;
playCommand.enabled = NO;
[playCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
return MPRemoteCommandHandlerStatusCommandFailed;
}];
// 锁屏暂停
MPRemoteCommand *pauseCommand = commandCenter.pauseCommand;
pauseCommand.enabled = NO;
[pauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
return MPRemoteCommandHandlerStatusCommandFailed;
}];
MPRemoteCommand *stopCommand = commandCenter.stopCommand;
stopCommand.enabled = NO;
[stopCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
return MPRemoteCommandHandlerStatusCommandFailed;
}];
// 播放和暂停按钮(耳机控制)
MPRemoteCommand *playPauseCommand = commandCenter.togglePlayPauseCommand;
playPauseCommand.enabled = NO;
[playPauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
return MPRemoteCommandHandlerStatusCommandFailed;
}];
// 拖动进度条
if (@available(iOS 9.1, *)) {
MPRemoteCommand *changePlaybackPositionCommand = commandCenter.changePlaybackPositionCommand;
changePlaybackPositionCommand.enabled = NO;
[changePlaybackPositionCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
return MPRemoteCommandHandlerStatusCommandFailed;
}];
} else {
// Fallback on earlier versions
}
}
- (void)setupLockScreenMediaInfo {
//给MPNowPlayingInfoCenter传递空信息
MPNowPlayingInfoCenter *playingCenter = [MPNowPlayingInfoCenter defaultCenter];
NSMutableDictionary *playingInfo = [NSMutableDictionary new];
[playingCenter setNowPlayingInfo:playingInfo];
}
当我们重新点击播放一个音频时
//把MPRemoteCommandCenter的控制enabled = YES
//写在viewWillAppear
- (void) setRemoteControlCmmmentEnable
{
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
commandCenter.playCommand.enabled = YES;
commandCenter.pauseCommand.enabled = YES;
commandCenter.stopCommand.enabled = YES;
commandCenter.changePlaybackPositionCommand.enabled = YES;
}
注:在工程中,AudioPlayer 是一个单例, MPRemoteCommandCenter的相关控制信息也只能调用一次,若多次调用,点击事件就会响应多次。So,这里只设置 enable。