iOS - AVAudioPlayer 在后台不会继续播放下一首歌曲 [英] iOS - AVAudioPlayer doesn't continue to next song while in background

查看:32
本文介绍了iOS - AVAudioPlayer 在后台不会继续播放下一首歌曲的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个应用程序可以播放一堆歌曲,而用户可以翻阅漫画书.我使用 AVAudioPlayer 并将其设置为按固定顺序播放歌曲.因此,当一首歌曲结束时,下一首歌曲将播放.当应用程序打开时,这可以完美运行.当应用程序在后台时会出现问题.我将应用程序设置为在后台播放,效果很好.因此,当用户按下主屏幕时,音乐会继续播放.歌曲结束时会出现问题,假设像打开应用程序时一样播放下一首歌曲.相反,什么也没有发生.根据我的 NSLog 语句,正在调用正确的方法,但没有任何反应.这是我的代码:

- (void)audioPlayerDidFinishPlaying: (AVAudioPlayer *)player 成功: (BOOL) flag {NSLog(@"歌曲完成");if ([songSelect isEqualToString: @"01icecapades"]) {isPlay = @"是";songSelect = @"02sugarcube";imageSelect = @"playbanner02";[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];}否则 if ([songSelect isEqualToString: @"02sugarcube"]) {isPlay = @"是";songSelect = @"03bullets";imageSelect = @"playbanner03";[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];}否则 if ([songSelect isEqualToString: @"03bullets"]) {isPlay = @"是";songSelect = @"04satanama";imageSelect = @"playbanner04";[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];}否则 if ([songSelect isEqualToString: @"04satanama"]) {isPlay = @"是";songSelect = @"05uglyjoke";imageSelect = @"playbanner05";[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];}否则 if ([songSelect isEqualToString: @"05uglyjoke"]) {isPlay = @"是";songSelect = @"01icecapades";imageSelect = @"playbanner01";[self performSelector:@selector(triggerSong) withObject:nil afterDelay:0];[self performSelector:@selector(triggerBanner) withObject:nil afterDelay:0];}}

上面是识别正在播放的歌曲并设置下一首正确歌曲的代码.然后它触发另一个设置播放器的方法.

- (void)triggerSong {NSLog(@"triggerSong 调用");NSString *路径;NSError *错误;//音频文件的路径path = [[NSBundle mainBundle] pathForResource:songSelect ofType:@"mp3"];//如果我们可以访问文件...if ([[NSFileManager defaultManager] fileExistsAtPath:path]){//设置播放器player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];//player = [initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];[玩家setDelegate:自我];//设置音量(范围是 0 到 1)player.volume = 1.0f;[播放器准备播放];[玩家 setNumberOfLoops:0];[播放器播放];NSLog(@"玩家播放");[错误发布];player.delegate = 自我;//每秒安排一个动作进行倒计时[NSTimer scheduleTimerWithTimeInterval:0.5 目标:self 选择器:@selector(updateTimeLeft) userInfo:nil repeats:YES];}}

现在我假设这不是最好的方法,但是当应用程序处于前台状态时它会很好.我一直在查看文档,但似乎无法找到导致此问题的原因.我希望有人能够看到我的方法有错误.就像我之前说的,正在调用 triggerSong 方法中的两个 NSLog,所以我看不出为什么没有调用 AVAudioPlayer(播放器).

我的 info.plist 中也有正确的设置,并且我的 viewDidLoad 中有这个:

//确保系统跟随我们的播放状态[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];[[AVAudioSession sharedInstance] setActive: YES error: nil];

感谢您的任何见解.非常感激.

解决方案

相关讨论p>

简短回答:

您需要在您的第一个视图控制器的 init 或 viewDidLoad 方法中使用此代码:

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

<小时>

带示例的长答案:

这是我的例子.和你一样,我开始使用一个可以在后台播放音乐但在第一个剪辑结束后无法继续播放的应用程序.我复制了原始 Music.mp3 并将其命名为 Music2.mp3.我的意图是在 Music.mp3 结束后立即播放 Music2.mp3 (audioPlayerDidFinishPlaying:).我玩弄了一段时间的后台任务,直到我在没有后台任务的情况下完成了这项工作:

-(id)init{self = [super initWithNibName:@"MediaPlayerViewController" bundle:nil];如果(自我){//播放后台播放列表需要这个[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];//音乐剪辑//设置第一首歌...NSString *musicPath = [[NSBundle mainBundle] pathForResource:@"Music" ofType:@"mp3"];如果(音乐路径){NSURL *musicURL = [NSURL fileURLWithPath:musicPath];audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL error:nil];[audioPlayer setDelegate:self];}}回归自我;}-(IBAction)playAudioFile:(id)sender{if([audioPlayer isPlaying]){//停止播放音频并更改按钮测试[音频播放器停止];[发送者 setTitle:@"播放音频文件" forState:UIControlStateNormal];}别的{//开始播放音频并更改按钮的文本//用户可以点击停止播放[音频播放器播放];[sender setTitle:@"Stop Audio File" forState:UIControlStateNormal];}}-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)播放成功:(BOOL)flag{[audioButton setTitle:@"播放音频文件" forState:UIControlStateNormal];[playRecordingButton setTitle:@"Play Rec File" forState:UIControlStateNormal];//播放第二首歌NSString *musicPath2 = [[NSBundle mainBundle] pathForResource:@"Music2" ofType:@"mp3"];如果(音乐路径2){NSURL *musicURL2 = [NSURL fileURLWithPath:musicPath2];audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL2 error:nil];[audioPlayer setDelegate:self];NSLog(@"再播放一遍:
%@", musicPath2);[音频播放器播放];}}

最终结果是我的应用现在正在连续循环播放 Music2.mp3,即使应用在后台也是如此.

So I have an app that plays a bunch of songs while the user can flip through a comic book. I use AVAudioPlayer and I have it set up to play the songs in a set order. So when one song finishes, the next one will play. This works flawlessly when the app is open. The problem occurs when the app is in the background. I set up the app to play in the background, and that works fine. So when the user presses the home screen the music continues to play. The problem occurs when the song ends, it is suppose to play the next song like it does when the app is open. Instead nothing happens. According to the my NSLog statements the correct methods are being called but nothing happens. Here is my code:

- (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];
}}

Above is the code that recognizes which song is playing, and sets the correct song next. Then it triggers another method that sets up the player.

- (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];
}}

Now I assuming this is not the best way to do this, but it works great when the app is in the foreground state. I've been looking through the documentation and I can't seem to find the cause of this problem. I was hoping somebody might be able to see an error to my approach. Like I said before, the two NSLogs in the triggerSong method are being called so I can't see why the AVAudioPlayer (player) is not being called.

Also I have the correct setting in my info.plist and I have this in my viewDidLoad:

//Make sure the system follows our playback status
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];

Thanks for any insight. Much appreciated.

解决方案

Relevant discussion

SHORT ANSWER:

You need this code in either your first view controller's init or viewDidLoad method:

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];


LONG ANSWER W/ SAMPLE:

Here is my example. Like you, I began with an app that would play music in the background but could never continue playing after the first clip ended. I made a copy of the original Music.mp3 and named it Music2.mp3. My intention was to play Music2.mp3 as soon as Music.mp3 ended (audioPlayerDidFinishPlaying:). I goofed around with the background tasks for awhile until I got this working WITHOUT the background task:

-(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: 
%@", musicPath2);
        [audioPlayer play];
    } 
}

The end result is that my app is now playing Music2.mp3 on a continuous loop, even if the app is in the background.

这篇关于iOS - AVAudioPlayer 在后台不会继续播放下一首歌曲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆