2012-03-12 12 views
10

だから私は、ユーザーが漫画本をめくることができる間にたくさんの曲を演奏するアプリを持っている。私はAVAudioPlayerを使用しており、セットオーダーで曲を再生するように設定しています。だから1曲が終了すると、次の曲が再生されます。これは、アプリケーションが開いているときに完璧に動作します。この問題は、アプリがバックグラウンドにあるときに発生します。私はバックグラウンドで再生するためにアプリをセットアップし、それはうまく動作します。ユーザーがホーム画面を押すと、音楽は引き続き再生されます。この問題は、曲が終了したときに発生します。アプリが開いているときと同じように、次の曲を再生すると思われます。代わりに何も起こらない。私の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メソッドの2つの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]; 

感謝を。とても有難い。

答えて

26

Relevant discussion

短い答え:

あなたはあなたの最初のビューコントローラのinitまたはviewDidLoadメソッドのいずれかで、このコードが必要になります。

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 

LONG ANSWERのW/SAMPLE:

これは私の例です。あなたのように、私はバックグラウンドで音楽を演奏するアプリから始めましたが、最初のクリップが終了した後では再生を続けることはできませんでした。元のMusic.mp3のコピーを作成し、Music2.mp3という名前を付けました。私の意図は、Music.mp3が終了するとすぐにMusic2.mp3を再生することでした(audioPlayerDidFinishPlaying :)。最終結果は私のアプリは今アプリがであっても、連続ループにMusic2.mp3を再生しているということです

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

:私はバックグラウンドタスクなしでこの作業を得たまで、私はしばらくの間バックグラウンドタスクの周りgoofed背景。ただ、Squatchが言ったことを確認する

+0

あなたは最高です!どうもありがとうございます。それは完璧に働いた。 –

+0

問題ありません!あなたに最高の運があります。 – Squatch

+1

参考までにあなたのリンクは間違っています... https://devforums.apple.com/message/264397 –

4

、これはまたスウィフトでのソリューションです:

UIApplication.sharedApplication().beginReceivingRemoteControlEvents() 
0

OS Xは、AVAudioPlayerを使用して、同じ問題を示し、ただしのUIApplicationは、iOS専用の構築です。 OS Xでは代わりにNSApplicationを使用する必要がありますが、NSApplicationはアプリケーションが終了するまで戻りませんので、スレッドを使用する必要があります。ボーナスとして、メインスレッドを必要とするNSApplicationの深さのどこかにassert()があります。

このハイブリッドC++/Objective Cの機能は、このOS Xの問題のための1つの回避策です:

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(); 
}; 
関連する問題