2012-03-12 37 views
10

Vì vậy, tôi có một ứng dụng phát một loạt bài hát trong khi người dùng có thể lướt qua một cuốn truyện tranh. Tôi sử dụng AVAudioPlayer và tôi đã thiết lập để phát các bài hát theo thứ tự đã đặt. Vì vậy, khi một bài hát kết thúc, bài hát tiếp theo sẽ phát. Điều này hoạt động hoàn hảo khi ứng dụng được mở. Sự cố xảy ra khi ứng dụng ở chế độ nền. Tôi thiết lập ứng dụng để phát trong nền và hoạt động tốt. Vì vậy, khi người dùng nhấn vào màn hình chính, nhạc sẽ tiếp tục phát. Vấn đề xảy ra khi bài hát kết thúc, giả sử chơi bài hát tiếp theo như khi ứng dụng đang mở. Thay vào đó không có gì xảy ra. Theo báo cáo NSLog của tôi, các phương pháp chính xác đang được gọi nhưng không có gì xảy ra. Đây là mã của tôi:iOS - AVAudioPlayer không tiếp tục bài hát tiếp theo trong khi ở chế độ nền

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

Trên đây là đoạn code mà nhận ra bài hát nào đang phát, và đặt bài hát chính xác tới. Sau đó, nó kích hoạt một phương pháp khác để thiết lập trình phát.

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

Bây giờ tôi giả định đây không phải là cách tốt nhất để làm điều này, nhưng nó hoạt động tuyệt vời khi ứng dụng ở trạng thái tiền cảnh. Tôi đã xem qua tài liệu và tôi dường như không thể tìm ra nguyên nhân của vấn đề này. Tôi đã hy vọng ai đó có thể nhìn thấy một lỗi để tiếp cận của tôi. Như tôi đã nói trước đây, hai NSLogs trong phương thức triggerSong đang được gọi nên tôi không thể thấy tại sao AVAudioPlayer (trình phát) không được gọi.

Ngoài ra tôi có các thiết lập đúng trong info.plist của tôi và tôi có điều này trong viewDidLoad của tôi:

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

Thanks cho bất kỳ cái nhìn sâu sắc. Nhiều đánh giá cao.

Trả lời

26

Relevant discussion

trả lời ngắn gọn:

Bạn cần mã này trong phương pháp init hoặc viewDidLoad hoặc xem điều khiển đầu tiên của bạn:

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 

DÀI ĐÁP W/SAMPLE:

Đây là ví dụ của tôi. Giống như bạn, tôi bắt đầu với một ứng dụng có thể phát nhạc trong nền nhưng không bao giờ có thể tiếp tục phát sau khi clip đầu tiên kết thúc. Tôi đã tạo một bản sao của Music.mp3 gốc và đặt tên là Music2.mp3. Ý định của tôi là chơi Music2.mp3 ngay khi Music.mp3 kết thúc (audioPlayerDidFinishPlaying :). Tôi goofed xung quanh với các nhiệm vụ nền cho một lúc cho đến khi tôi đã làm việc này KHÔNG nhiệm vụ nền:

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

Kết quả cuối cùng là ứng dụng của tôi bây giờ đang chơi Music2.mp3 trên một vòng lặp liên tục, ngay cả khi ứng dụng được trong bối cảnh.

+0

của bạn là tốt nhất! Cảm ơn bạn rất nhiều. Nó hoạt động hoàn hảo. –

+0

Không sao cả! Nhưng điêu tôt đẹp nhât se đên vơi bạn. – Squatch

+1

FYI .. liên kết của bạn sai ... nó phải là https://devforums.apple.com/message/264397 –

4

Chỉ cần để xác nhận những gì Squatch nói, đây cũng là giải pháp trong Swift:

UIApplication.sharedApplication().beginReceivingRemoteControlEvents() 
0

OS X thể hiện cùng một vấn đề sử dụng AVAudioPlayer, tuy nhiên UIApplication là một iOS chỉ xây dựng. OS X yêu cầu sử dụng NSApplication thay vào đó, nhưng NSApplication không trả lại cho đến khi ứng dụng kết thúc, vì vậy chúng ta cần sử dụng các luồng. Là một phần thưởng, có một khẳng định() ở đâu đó trong chiều sâu của NSApplication yêu cầu chủ đề chính.

hybrid C này ++/Objective C chức năng là một trong những cách giải quyết cho vấn đề này 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(); 
}; 
Các vấn đề liên quan