1、在文件APPDelegate.m里,实现方法“- (void)remoteControlReceivedWithEvent:(UIEvent *)event”的重写,用来接收控制中心的事件。
1 // 在APPDelegate.m中声明一个通知事件的key
2 NSString *const AppDelegateReceiveRemoteEventsNotification = @"AppDelegateReceiveRemoteEventsNotification";
3
4 /// 锁屏页面的控制事件(必须在这里重写该方法,在播放页面重写不起作用)
5 - (void)remoteControlReceivedWithEvent:(UIEvent *)event {
6 if (event.type == UIEventTypeRemoteControl) {
7 // 发送通知给音频播放界面 进行某些处理
8 [[NSNotificationCenter defaultCenter] postNotificationName:AppDelegateReceiveRemoteEventsNotification object:event];
9 }
10 }
Appdelegate里就设置这些。
2、在音频播放界面
1 // 设置控制中心交互需要导入
2 #import <MediaPlayer/MediaPlayer.h>
3
4 /// 注册通知
5 - (void) registerAllNotifications {
6 // 后台通知
7 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(apllicationWillResignActiveNotification:) name:UIApplicationWillResignActiveNotification object:nil];
8
9 // 进入前台通知
10 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(apllicationWillEnterForegroundNotification:) name:UIApplicationWillEnterForegroundNotification object:nil];
11
12 // 锁屏界面事件
13 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(AppDelegateReceiveRemoteEventsNotification:) name:AppDelegateReceiveRemoteEventsNotification object:nil];
14 }
15
16
17 #pragma mark - 通知方法实现
18 /// 进入后台
19 - (void) apllicationWillResignActiveNotification:(NSNotification *)n {
20 NSError *error = nil;
21 // 后台播放代码
22 AVAudioSession *session = [AVAudioSession sharedInstance];
23 [session setActive:YES error:&error];
24 if(error) {
25 // NSLog(@"ListenPlayView background error0: %@", error.description);
26 }
27 [session setCategory:AVAudioSessionCategoryPlayback error:&error];
28 if(error) {
29 // NSLog(@"ListenPlayView background error1: %@", error.description);
30 }
31
32 /// 进后台 设置接收远程控制
33 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
34
35 // 上面代码实现后台播放 几分钟后会停止播放
36 // 添加任务id 实现后台连续播放
37 backTaskID = [self backgroundPlayerID:backTaskID];
38 }
39
40 // 实现一下backgroundPlayerID:这个方法:
41 - (UIBackgroundTaskIdentifier)backgroundPlayerID:(UIBackgroundTaskIdentifier)backTaskId {
42 NSError *error = nil;
43 // 设置并激活音频会话类别
44 AVAudioSession *session = [AVAudioSession sharedInstance];
45 [session setCategory:AVAudioSessionCategoryPlayback error:nil];
46 if(error) {
47 NSLog(@"ListenPlayView background error2: %@", error.description);
48 }
49 [session setActive:YES error:nil];
50 if(error) {
51 NSLog(@"ListenPlayView background error3: %@", error.description);
52 }
53
54 // 设置后台任务ID
55 UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
56 newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
57 if(newTaskId != UIBackgroundTaskInvalid && backTaskId != UIBackgroundTaskInvalid) {
58 [[UIApplication sharedApplication] endBackgroundTask:backTaskId];
59 }
60
61 return newTaskId;
62 }
63
64
65 /// 进入前台通知
66 - (void) apllicationWillEnterForegroundNotification:(NSNotification *)n {
67 // 进前台 设置不接受远程控制
68 [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
69 }
70
71 /// 远程控制事件通知
72 - (void)AppDelegateReceiveRemoteEventsNotification:(NSNotification*)noti {
73 if (!noti) return;
74 if (!noti.object) return;
75 if (![noti.object isKindOfClass:[UIEvent class]]) return;
76
77 UIEvent *event = (UIEvent *)noti.object;
78 if (event.type == UIEventTypeRemoteControl) {
79 // 根据远程控制事件类型,在播放界面设置播放、暂停、下一个、上一个
80 switch (event.subtype) {
81 case UIEventSubtypeRemoteControlPlay:
82 // play
83 break;
84 case UIEventSubtypeRemoteControlPause:
85 // pause
86 break;
87 case UIEventSubtypeRemoteControlNextTrack:
88 // next
89 break;
90 case UIEventSubtypeRemoteControlPreviousTrack:
91 // last
92 break;
93 default: break;
94 }
95 }
96 }
97
98 /// 移除所有通知
99 - (void)removeAllNotifications {
100 [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
101
102 [[NSNotificationCenter defaultCenter] removeObserver:self name:AppDelegateReceiveRemoteEventsNotification object:nil];
103
104 [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
105 }
上面这些实现了控制中心和播放界面的交互。此时,控制中心还没有显示当前播放的音频信息(嗯,我还没有设置)。如下:
1 /// 设置锁屏界面的播放音频的相关信息
2 /// 可在适当时机调用该方法(开始播放时、将要进入后台、音频切换)
3 - (void) setupNowPlayingAudioInfo {
4 /** 设置信息的类型
5 * MPMediaItemPropertyAlbumTitle : 专辑名
6 * MPMediaItemPropertyAlbumTrackCount : 专辑个数
7 * MPMediaItemPropertyAlbumTrackNumber : 当前播放的专辑位置
8 * MPMediaItemPropertyArtist : 艺术家
9 * MPMediaItemPropertyArtwork : 封面
10 * MPMediaItemPropertyComposer : 作曲家
11 * MPMediaItemPropertyDiscCount : 迪斯科 数量
12 * MPMediaItemPropertyDiscNumber : 当前位置
13 * MPMediaItemPropertyGenre : 流派
14 * MPMediaItemPropertyPersistentID : ID
15 * MPMediaItemPropertyPlaybackDuration : 后台播放时长
16 * MPMediaItemPropertyTitle : 标题
17 */
18
19 NSMutableDictionary *songDict = [NSMutableDictionary dictionary];
20
21 // 音频名字
22 [songDict setObject:@"她来听我的演唱会" forKey:MPMediaItemPropertyTitle];
23
24 // 歌手
25 [songDict setObject:@"张学友" forKey:MPMediaItemPropertyArtist];
26
27 // 歌曲的总时间
28 [songDict setObject:@(200) forKeyedSubscript:MPMediaItemPropertyPlaybackDuration];
29
30 // 当前时间
31 [songDict setObject:@(30) forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
32
33 // 播放速率
34 [songDict setObject:@(1.0) forKey:MPNowPlayingInfoPropertyPlaybackRate];
35
36 // 锁屏音频封面
37 MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:@"封面.png"]];
38 [songDict setObject:artwork forKey:MPMediaItemPropertyArtwork];
39
40 // 设置控制中心歌曲信息
41 [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songDict];
42 }
这时,锁屏界面已经可以显示音频对应的信息了。
还有最后一步设置(动态设置控制中心的按钮状态),如:当前播放的音频是播放列表最后一条,设置控制中心的下一个按钮不可点击。。。
1 /// 设置控制中心的按钮状态(保持与播放界面对应按钮状态一致)
2 /// 调用时机(如切换音频时,设置锁屏界面音频信息时)
3 - (void) setupRemoteControlButtonStatus {
4 // 只有设置了target 才能设置控制中心(锁屏界面)的按钮状态
5
6 // 设置控制中心下一个按钮 和播放页面的下一个按钮状态同步
7 MPRemoteCommand *next = [MPRemoteCommandCenter sharedCommandCenter].nextTrackCommand;
8 next.enabled = self.nextButton.enabled;
9 [next addTarget:self action:@selector(remoteCommandAction:)];
10
11 // 设置控制中心上一个按钮 和播放页面的上一个按钮状态同步
12 MPRemoteCommand *last = [MPRemoteCommandCenter sharedCommandCenter].previousTrackCommand;
13 last.enabled = self.theLastButton.enabled;
14 [last addTarget:self action:@selector(remoteCommandAction:)];
15
16 // 设置控制中心播放|暂停按钮 和 播放页面的播放|暂停按钮状态同步
17 MPRemoteCommand *play = [MPRemoteCommandCenter sharedCommandCenter].playCommand;
18 play.enabled = self.playButton.enabled;
19 [play addTarget:self action:@selector(remoteCommandAction:)];
20
21 MPRemoteCommand *pause = [MPRemoteCommandCenter sharedCommandCenter].pauseCommand;
22 pause.enabled = self.playButton.enabled;
23 [pause addTarget:self action:@selector(remoteCommandAction:)];
24 }
25
26 /// 实现target action
27 - (void)remoteCommandAction:(MPRemoteCommand *)com {
28 // 这里不用具体做些什么 do nothing..
29 // 控制中心的事件已经在通知AppDelegateReceiveRemoteEventsNotification里实现了
30 }