iOS - AVAudioPlayer 在后台不会继续播放下一首歌曲
Posted
技术标签:
【中文标题】iOS - AVAudioPlayer 在后台不会继续播放下一首歌曲【英文标题】:iOS - AVAudioPlayer doesn't continue to next song while in background 【发布时间】:2012-03-12 00:55:04 【问题描述】:所以我有一个应用程序可以播放一堆歌曲,而用户可以翻阅漫画书。我使用 AVAudioPlayer 并将其设置为按固定顺序播放歌曲。因此,当一首歌曲结束时,下一首歌曲将播放。当应用程序打开时,这可以完美运行。当应用程序在后台时会出现问题。我将应用程序设置为在后台播放,效果很好。因此,当用户按下主屏幕时,音乐会继续播放。歌曲结束时会出现问题,假设像打开应用程序时一样播放下一首歌曲。相反,什么也没有发生。根据我的 NSLog 语句,正在调用正确的方法,但没有任何反应。这是我的代码:
- (void)audioPlayerDidFinishPlaying: (AVAudioPlayer *)player successfully: (BOOL) flag
NSLog(@"Song finished");
if ([songSelect isEqualToString: @"01icecapades"])
isPlay = @"yes";
songSelect = @"02sugarcube";
imageSelect = @"playbanner02";
[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];
else if ([songSelect isEqualToString: @"02sugarcube"])
isPlay = @"yes";
songSelect = @"03bullets";
imageSelect = @"playbanner03";
[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];
else if ([songSelect isEqualToString: @"03bullets"])
isPlay = @"yes";
songSelect = @"04satanama";
imageSelect = @"playbanner04";
[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];
else if ([songSelect isEqualToString: @"04satanama"])
isPlay = @"yes";
songSelect = @"05uglyjoke";
imageSelect = @"playbanner05";
[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];
else if ([songSelect isEqualToString: @"05uglyjoke"])
isPlay = @"yes";
songSelect = @"01icecapades";
imageSelect = @"playbanner01";
[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];
上面是识别正在播放的歌曲并设置下一首正确歌曲的代码。然后它触发另一个设置播放器的方法。
- (void)triggerSong
NSLog(@"triggerSong called");
NSString *path;
NSError *error;
// Path the audio file
path = [[NSBundle mainBundle] pathForResource:songSelect ofType:@"mp3"];
// If we can access the file...
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
// Setup the player
player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
//player = [initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
[player setDelegate: self];
// Set the volume (range is 0 to 1)
player.volume = 1.0f;
[player prepareToPlay];
[player setNumberOfLoops:0];
[player play];
NSLog(@"player play");
[error release];
player.delegate = self;
// schedules an action every second for countdown
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTimeLeft) userInfo:nil repeats:YES];
现在我假设这不是最好的方法,但是当应用程序处于前台状态时它会很好。我一直在查看文档,但似乎无法找到导致此问题的原因。我希望有人能够看到我的方法有错误。就像我之前说的,正在调用 triggerSong 方法中的两个 NSLog,所以我看不出为什么没有调用 AVAudioPlayer(播放器)。
我的 info.plist 中也有正确的设置,并且我的 viewDidLoad 中有这个:
//Make sure the system follows our playback status
[[AVAudiosession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
感谢您的任何见解。非常感激。
【问题讨论】:
【参考方案1】:Relevant discussion
简短回答:
您需要在您的第一个视图控制器的 init 或 viewDidLoad 方法中使用此代码:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
带示例的长答案:
这是我的例子。和你一样,我从一个可以在后台播放音乐的应用程序开始,但在第一个剪辑结束后就再也无法继续播放了。我复制了原始 Music.mp3 并将其命名为 Music2.mp3。我的意图是在 Music.mp3 结束后立即播放 Music2.mp3 (audioPlayerDidFinishPlaying:)。我玩弄了一段时间的后台任务,直到我在没有后台任务的情况下完成了这项工作:
-(id)init
self = [super initWithNibName:@"MediaPlayerViewController" bundle:nil];
if(self)
//Need this to play background playlist
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
//MUSIC CLIP
//Sets up the first song...
NSString *musicPath = [[NSBundle mainBundle] pathForResource:@"Music" ofType:@"mp3"];
if(musicPath)
NSURL *musicURL = [NSURL fileURLWithPath:musicPath];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL error:nil];
[audioPlayer setDelegate:self];
return self;
-(IBAction)playAudioFile:(id)sender
if([audioPlayer isPlaying])
//Stop playing audio and change test of button
[audioPlayer stop];
[sender setTitle:@"Play Audio File" forState:UIControlStateNormal];
else
//Start playing audio and change text of button so
//user can tap to stop playback
[audioPlayer play];
[sender setTitle:@"Stop Audio File" forState:UIControlStateNormal];
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
[audioButton setTitle:@"Play Audio File" forState:UIControlStateNormal];
[playRecordingButton setTitle:@"Play Rec File" forState:UIControlStateNormal];
//PLAY THE SECOND SONG
NSString *musicPath2 = [[NSBundle mainBundle] pathForResource:@"Music2" ofType:@"mp3"];
if(musicPath2)
NSURL *musicURL2 = [NSURL fileURLWithPath:musicPath2];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL2 error:nil];
[audioPlayer setDelegate:self];
NSLog(@"Play it again: \n%@", musicPath2);
[audioPlayer play];
最终结果是我的应用现在正在连续循环播放 Music2.mp3,即使应用在后台也是如此。
【讨论】:
没问题!祝你好运。 仅供参考..您的链接错误...应该是devforums.apple.com/message/264397 哇哦。从来没有注意到。感谢您的提醒!我把它修好了,以防其他人经过这里。 当我们使用远程url播放音乐时它也不起作用,它在后台播放一首歌后停止 这仍然是一个非常有用的答案,但苹果论坛中讨论的链接似乎不再有效。不幸的是,archive.org 似乎也没有副本。我手动尝试了developer.apple.com/forums/thread/264397,但它是 404s。【参考方案2】:只是为了确认一下 Squatch 所说的,这也是 Swift 中的解决方案:
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
【讨论】:
【参考方案3】:OS X 使用 AVAudioPlayer 会出现同样的问题,但是 UIApplication 是一个仅限 iOS 的构造。 OS X 需要使用 NSApplication 代替,但 NSApplication 直到应用程序终止才会返回,因此我们需要使用线程。作为奖励,在 NSApplication 的深处有一个 assert() 需要主线程。
此混合 C++/Objective C 函数是解决此 OS X 问题的一种解决方法:
void do_the_dumb (void real_application(void))
std::thread thread ([real_application]()
real_application();
[[NSApplication sharedApplication] terminate: [NSApplication sharedApplication]];
);
[[NSApplication sharedApplication] run];
thread.join();
;
【讨论】:
以上是关于iOS - AVAudioPlayer 在后台不会继续播放下一首歌曲的主要内容,如果未能解决你的问题,请参考以下文章
AVAudioPlayer 问题(如果设备被锁定,音乐文件不会在后台模式下播放)
iOS AvPlayer AvAudioPlayer音频的后台播放问题