在iOS 8上,Xcode中的MPNowPlayingInfoCenter信息未显示。

8

我正在开发一款音乐应用程序,它应该可以在后台播放音乐。

我使用 MPMoviePlayerController 播放音乐。以下是初始化 MPMoviePlayerController 的代码:

NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
resourcePath = [resourcePath stringByAppendingString:@"/music.m4a"];
NSError* err;
self.player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:resourcePath]];
if (err) {
    NSLog(@"ERROR: %@", err.localizedDescription);
}
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
[session setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self.player setShouldAutoplay:NO];
[self.player setControlStyle: MPMovieControlStyleEmbedded];
self.player.view.hidden = YES;
[self.player prepareToPlay];

当我执行[self.player play];时,音乐就开始播放了。 但我还想在锁屏界面和控制中心显示歌曲名称、专辑名称和专辑封面。我正在使用以下代码:

Class playingInfoCenter = NSClassFromString(@"MPNowPlayingInfoCenter");
    if (playingInfoCenter) {
        NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
        MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage: [UIImage imageNamed:@"artwork.png"]];
        [songInfo setObject:@"SongName" forKey:MPMediaItemPropertyTitle];
        [songInfo setObject:@"ArtistName" forKey:MPMediaItemPropertyArtist];
        [songInfo setObject:@"AlbumTitle" forKey:MPMediaItemPropertyAlbumTitle];
        [songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
        [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
    }

但是在锁屏界面上没有显示任何内容。控制中心也没有显示出来。
我该怎么解决这个问题?我在网上没有找到任何有用的信息。
谢谢,Fabian。

你的代码是否真正被执行了? - matt
是的,[[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo objectForKey:MPMediaItemPropertyTitle] 返回正确的歌曲名。 - FTFT1234
啊哈!这真是个好消息。所以你的代码不仅在运行,而且实际上成功地设置了“nowPlayingInfo”。那么让我问你一下——你是第一响应者吗?这样你就可以成功地从锁屏和控制中心接收远程控制事件了吗? - matt
我认为那就是问题所在。除非你是第一响应者,否则你无法影响锁屏界面。 - matt
好的,我该如何解决这个问题? - FTFT1234
显示剩余2条评论
4个回答

31
问题在于您没有满足成为锁屏和控制中心主人的要求,如我在我的书中所解释的。您应该看到相当于现代(iOS 8)的这个: enter image description here 事实上,您没有看到它表明您省略了一个或多个要求,我在此列出(直接引用自我的书):
- 您的应用程序必须包含一个UIResponder,该UIResponder在其响应链中从canBecomeFirstResponder返回YES,并且该响应者必须实际是第一响应者。 - 响应链中某个UIResponder,在第一响应者处或以上,必须实现remoteControlReceivedWithEvent:。 - 您的应用程序必须调用UIApplication实例方法beginReceivingRemoteControlEvents。 - 您的应用程序的音频会话策略必须为Playback。 - 您的应用程序必须发出一些声音。
我不知道您省略了哪个方面; 您可能希望将代码与工作示例进行比较,这里是示例:https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch14p653backgroundPlayerAndInterrupter/backgroundPlayer/backgroundPlayer/ViewController.m

是的,这就是解决方案。非常感谢你的帮助! - FTFT1234
非常欢迎。这是很多要求!忽略其中一个很容易,然后事情就会神秘地不起作用。:( - matt
你在通过WKWebView播放时,有没有成功让它工作?我可以修改其他来源的正在播放内容,但是通过WKWebView播放时不行。 - pir800
这个在AVQueuePlayer中可行吗?也就是说,我能不能从外部向AVPlayer添加NSMutableDictionary来设置艺术品等内容? - amisha.beladiya
@matt 那篇帖子对我非常有帮助,解决了我的问题,谢谢! - Evgeniy Kleban
1
我验证了我的应用程序确实完成了列表中的所有操作,但是当我第一次启动应用程序并播放流时,锁定屏幕控件和信息不会出现。我必须停止并重新启动流(Icecast),然后在第二次尝试时,锁定屏幕控件和信息才会出现。第一次尝试和第二次尝试的步骤完全相同(即没有线程或异步竞争条件)。因此,我不知道为什么第一次尝试时锁定屏幕无法正常工作。 - Ken Roy

11

我希望扩展@matt的答案- 当您使用AVAudioSessionCategoryOptionMixWithOthers选项时,设置nowPlayingInfo是无用的。


1
如果你添加了.mixWithOthers关键字,你将无法像预期的那样设置控制中心细节。 - owenfi

0
想要解释一下@zakhej的答案——当设置AVAudioSessionCategoryOptionMixWithOthers时会发生什么。
  1. MPNowPlayingInfoCenter是一个单例,这意味着只有一个应用程序可以设置它。
  2. AVAudioSession与其他应用程序共享,每个应用程序都可以设置它。
所以,当您设置类别AVAudioSessionCategoryAmbient、AVAudioSessionCategoryPlayAndRecord并与其他人混合,AVAudioSessionCategoryPlayback并与其他人混合时,设置MPNowPlayingInfoCenter的nowPlayingInfo是无用的。

0
进一步扩展@matt的答案,当应用程序返回前台(applicationDidBecomeActive)时,需要调用endReceivingRemoteControlEvents和resignFirstResponder。否则,操作系统会认为您是一个不良行为者(或忘记关闭它们),并完全关闭您显示睡眠控件的能力,即使您再次调用beginReceivingRemoteControlEvents。我添加了这些调用,现在睡眠控件总是在应该显示时显示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接