iOS - AVAudioPlayer不会在后台继续播放下一首歌曲
因此,我有一个应用程序,播放一串歌曲,而用户可以翻阅漫画书。我使用AVAudioPlayer,并且设置了按照设定的顺序播放歌曲。所以当一首歌完成时,下一首将会播放。当应用程序打开时,此功能完美无瑕。当应用程序在后台时发生问题。我将应用程序设置为在后台播放,而且工作正常。所以当用户按下主屏幕时,音乐继续播放。问题发生在歌曲结束时,它应该像打开应用时播放下一首歌一样。相反没有任何反应根据我的NSLog语句正确的方法被调用,但没有任何反应。这是我的代码:iOS - AVAudioPlayer不会在后台继续播放下一首歌曲
- (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方法中的两个NSLogs被调用,所以我不明白为什么AVAudioPlayer(播放器)没有被调用。
我也有我的info.plist正确的设置,我有这个在我viewDidLoad中:
//Make sure the system follows our playback status
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
感谢任何见解。非常感激。
简短的回答:
你需要这个代码或者您的第一个视图控制器的初始化或viewDidLoad方法:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
长的答案W /示例:
这是我的例子。和你一样,我从一个可以在后台播放音乐的应用程序开始,但在第一个剪辑结束之后无法继续播放。我制作了原始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,即使该应用程序是的背景。
只是为了确认哪些Squatch说,这也是雨燕的解决方案:
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
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();
};
你是最棒的!非常感谢。它工作完美。 – 2012-03-16 02:40:36
没问题!祝你好运。 – Squatch 2012-03-16 12:23:46
FYI ..你的链接是错误的...它应该是https://devforums.apple.com/message/264397 – 2013-12-02 06:00:05