2012-05-09 34 views
5

Tôi đang gặp một số vấn đề thực sự lạ với AVPlayer. Tôi có một máy nghe nhạc rất đơn giản (mà dòng nhạc mẫu từ cửa hàng iTunes) làm việc với nó một cách chính xác trên giả lập (cả iPhone và iPad với iOS 5.1) nhưng nó hoạt động bất thường trên một thiết bị thực.Các sự cố phát nhạc trực tuyến trên iOS AVPlayer

Trên iPad 2 với iOS 5.1.1 nó phát chính xác ngay cả khi tôi kết nối tai nghe với thiết bị. Nhưng ngay sau khi tôi ngắt kết nối, nó sẽ không phát âm thanh qua loa (mặc dù nếu tôi kết nối lại với nhau, tôi có thể nghe bài hát).

Trên iPhone 4 có cài đặt iOS 5.1, nó dường như không phát ở tất cả qua loa nhưng tôi có thể nghe nhạc qua tai nghe. Mặc dù nó dường như không được chơi qua loa mà tôi có thể nghe ngay bây giờ và sau đó trong một thời điểm rất ngắn khi chơi nhạc (và có thể xác nhận rằng nó đang chơi vì giao diện người dùng của tôi phản ứng tương ứng) mặc dù nó có vẻ là ngẫu nhiên.

Tôi đang sử dụng AVPlayer vì nó có vẻ phù hợp với yêu cầu. Tôi có nên sử dụng thư viện khác không? Tôi có cần định tuyến âm thanh theo cách thủ công không? Tại sao tôi có những loại vấn đề này? Tôi có đang sử dụng Phiên âm thanh chính xác không?

Media.h:

#import <Foundation/Foundation.h> 
#import <AVFoundation/AVFoundation.h> 
#import <AudioToolbox/AudioToolbox.h> 

#define NOT_PLAYING -1 

@protocol MediaDelegate <NSObject> 
@optional 
- (void) didEndPlayingAtIndex:(int) index; 
- (void) startedToPlayAtIndex:(int) index; 
- (void) stoppedToPlayAtIndex:(int) index; 
- (void) startedToPlayAtIndex:(int) to fromIndex:(int) from; 
- (void) pausedAtIndex:(int) index; 
@end 

@interface Media : NSObject <AVAudioSessionDelegate> 

@property (nonatomic, assign) int currentItem; 
@property (nonatomic, strong) NSURL *url; 
@property (nonatomic, strong) AVPlayer *player; 
@property (nonatomic, assign) id<MediaDelegate> delegate; 

- (void) toggle:(int) index; 
- (void) stop; 

@end 

Media.m:

#import "Media.h" 

@implementation Media 

@synthesize currentItem; 
@synthesize player; 
@synthesize delegate; 
@synthesize url; 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     NSError *activationError = nil; 
     NSError *setCategoryError = nil; 
     AVAudioSession *session = [AVAudioSession sharedInstance]; 
     session.delegate = self; 
     [session setActive:YES error:&activationError]; 
     [session setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError]; 

     if(activationError || setCategoryError) 
      NSLog(@"ERROR: %@, %@",activationError,setCategoryError); 

     self.currentItem = NOT_PLAYING; 
    } 
    return self; 
} 

- (void)dealloc{ 
    NSError *activationError = nil; 
    [[AVAudioSession sharedInstance] setActive:NO error:&activationError]; 

    if(activationError) 
     NSLog(@"ERROR: %@",activationError); 

    [self.player removeObserver:self forKeyPath:@"status"]; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{  
    switch (player.status) { 
     case AVPlayerItemStatusReadyToPlay: 
      [self.player play]; 
      if([self.delegate respondsToSelector:@selector(startedToPlayAtIndex:)]) 
       [self.delegate startedToPlayAtIndex:self.currentItem]; 
      break; 
     default: 
      break; 
    } 
} 

- (void) toggle:(int) index{ 
    if (self.currentItem == NOT_PLAYING) { 
     self.player = [AVPlayer playerWithPlayerItem:[AVPlayerItem playerItemWithURL:self.url]]; 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(didEnd:) 
                name:AVPlayerItemDidPlayToEndTimeNotification 
                object:self.player]; 
     self.currentItem = index; 
     [self.player addObserver:self forKeyPath:@"status" options:0 context:nil]; 
    } 
    else { 
     if (self.currentItem == index) { 
      [self.player pause]; 
      if([self.delegate respondsToSelector:@selector(stoppedToPlayAtIndex:)]) 
       [self.delegate stoppedToPlayAtIndex:index]; 
      self.currentItem = NOT_PLAYING; 
      [self.player removeObserver:self forKeyPath:@"status"]; 
      self.player = nil; 
      [[NSNotificationCenter defaultCenter] removeObserver:self]; 
     } 
     else{ 
      [self.player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithURL:self.url]]; 
      if([self.delegate respondsToSelector:@selector(startedToPlayAtIndex:fromIndex:)]) 
       [self.delegate startedToPlayAtIndex:index fromIndex:self.currentItem]; 
      self.currentItem = index; 
     } 
    } 
} 

- (void) stop{ 
    [self.player pause]; 
    if([self.delegate respondsToSelector:@selector(stoppedToPlayAtIndex:)]) 
     [self.delegate stoppedToPlayAtIndex:self.currentItem]; 
} 

-(void) didEnd:(id)sender{ 
    if([self.delegate respondsToSelector:@selector(didEndPlayingAtIndex:)]) 
     [self.delegate didEndPlayingAtIndex:self.currentItem]; 
    self.currentItem = NOT_PLAYING; 
    [self.player removeObserver:self forKeyPath:@"status"]; 
    self.player = nil; 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

#pragma mark - AVAudioSession delegate 

-(void)beginInterruption{ 
    NSLog(@"Interruption"); 
    if(self.currentItem != NOT_PLAYING){ 
     [self.player pause]; 
     if([self.delegate respondsToSelector:@selector(pausedAtIndex:)]) 
      [self.delegate pausedAtIndex:self.currentItem]; 
    } 
} 

-(void)endInterruption{ 
    NSLog(@"Ended interruption"); 
    if(self.currentItem != NOT_PLAYING){ 
     [self.player play]; 
     if([self.delegate respondsToSelector:@selector(startedToPlayAtIndex:)]) 
      [self.delegate startedToPlayAtIndex:self.currentItem]; 
    } 
} 

@end 
+0

Tôi biết đó là một cảnh quay dài nhưng hãy thử gọi setActive sau khi bạn gọi setCategory. – SteveB

+0

Vâng, tôi không hoàn toàn chắc chắn rằng nó đã làm nó bởi vì tôi đã thực hiện một số thay đổi khác cùng một lúc, nhưng nó bây giờ làm việc bình thường (cho đến nay) với ngoại lệ của âm thanh không được chuyển đến loa bất cứ khi nào tôi ngắt kết nối tai nghe. Cảm ơn nhiều! – dvieira

+0

Với AVAudioSessionCategoryPlayback âm thanh sẽ tự động được chuyển đến loa. Phải có một số mã ở một nơi nào khác ngăn chặn điều đó xảy ra. Nếu bạn có thể đăng thêm một số mã hoặc tải lên dự án của bạn ở đâu đó, tôi có thể xem xét. – SteveB

Trả lời

0

Dường như bạn có một vấn đề với định tuyến âm thanh chính xác. Tôi đề nghị thêm một cuộc gọi lại người nghe thay đổi tuyến đường âm thanh. Trước hết khai báo một phương pháp:

void audioRouteChangeListenerCallback(void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueSize, const void *inPropertyValue); 

Sau đó, trong phương pháp init của bạn thêm một callback:

// Prevent from audio issues when you pull out earphone 
AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, (__bridge void *)(self)); 

Và cuối cùng, thêm một thực hiện gọi lại:

void audioRouteChangeListenerCallback(void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueSize, const void *inPropertyValue) { 
    if (inPropertyID != kAudioSessionProperty_AudioRouteChange) { 
     return; 
    } 

    CFDictionaryRef routeChangeDictionary = inPropertyValue; 
    CFNumberRef  routeChangeReasonRef = CFDictionaryGetValue(routeChangeDictionary, CFSTR(kAudioSession_AudioRouteChangeKey_Reason)); 
    SInt32   routeChangeReason; 
    CFNumberGetValue(routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason); 

    if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) { 
     // Headset is unplugged.. 
     NSLog(@"Headset is unplugged.."); 
     // Delayed play: 0.5 s. 
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 
      [CORE.player play]; // NOTE: change this line according your current player implementation 
      NSLog(@"resumed play"); 
     }); 
    } 
    if (routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable) { 
     // Headset is plugged in.. 
     NSLog(@"Headset is plugged in.."); 
    } 
} 

Hope trợ giúp này! Ít nhất là đối với những người khác, đó sẽ là mẹo hữu ích.

Các vấn đề liên quan