所以我有一个应用程序,它可以播放一堆歌曲,而用户可以翻阅一本漫画书。我使用AVAudioPlayer,并将其设置为按设定的顺序播放歌曲。所以当一首歌结束时,下一首就会播放。当应用程序打开时,它可以完美地工作。当应用程序在后台时,问题就会发生。我将应用程序设置为在后台播放,这可以很好地工作。因此,当用户按下主屏幕时,音乐会继续播放。问题发生在歌曲结束时,它应该像打开应用程序时一样播放下一首歌曲。相反,什么都不会发生。根据my 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方法中的两个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];谢谢你的见解。非常感谢。
发布于 2012-03-15 21:47:58
简短的回答:
您需要在第一个视图控制器的init或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,即使应用程序在后台。
发布于 2015-01-05 03:23:43
为了确认Squatch所说的,这也是Swift中的解决方案:
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()发布于 2015-11-19 08:31:33
OS在使用AVAudioPlayer时也出现了同样的问题,然而UIApplication是一个仅用于iOS的构造。OS需要使用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();
};https://stackoverflow.com/questions/9660488
复制相似问题