2012-05-09 34 views
5

AVPlayer ile gerçekten çok tuhaf sorunlar yaşıyorum. Simülatörde (hem iPhone hem de iPad iOS 5.1 ile) çalışan çok basit bir müzik çalarım var (iTunes mağazasından örnek müzik akışı) ve gerçek bir cihazda anormal davranıyor.iOS AVPlayer müzik akışı sorunları

iOS 5.1.1 ile bir iPad 2'de, kulaklığımı cihaza bağlasam bile doğru şekilde oynatılıyor. Ama bağlantıyı keser bitirmez hoparlörler aracılığıyla bir ses çalmaz (tekrar bağlarsam şarkıyı dinleyebilirim).

iOS 5.1 yüklü bir iPhone 4'te, hoparlörlerden hiç çalmıyor gibi görünüyor, ancak kulaklıklarım aracılığıyla müzik dinleyebiliyorum. Konuşmacılar aracılığıyla çalınmıyor gibi görünse de, şimdi ve sonra çok kısa bir an için müzik çalabiliyorum (ve aslında bunu yaptığımı teyit edebilir, çünkü UI'm buna göre cevap veriyor) rasgele gibi görünse de.

AVPlayer kullanıyorum, çünkü gereksinimlere uyacak gibi görünüyor. Başka bir kütüphane kullanmalı mıyım? Sesi elle yönlendirmem gerekiyor mu? Neden bu tür problemlere sahibim? Ve Sesli Oturumları doğru kullanıyorum?

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: Doğru ses yönlendirme ile ilgili bir sorun var gibi

#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

Uzun bir çekim olduğunu biliyorum, ancak setCategory'i çağırdıktan sonra setActive'yi aramayı deneyin. – SteveB

+0

Evet, bunu yaptığından kesinlikle emin değilim çünkü aynı anda başka değişiklikler yaptım, fakat şimdi (şu ana kadar) normal olarak (şu ana kadar) ses çıkışı hariç her zaman hoparlörlerime yönlendirilmeyen ses hariç çalışıyor. kulaklıklar. Çok teşekkür ederim! – dvieira

+0

AVAudioSessionCategoryPlayback ile ses otomatik olarak hoparlörlere yönlendirilmelidir. Bunun olmasını durduran başka bir kod olmalı. Daha fazla kod gönderebilir veya projenizi bir yere yükleyebilirseniz bir göz atabilirim. – SteveB

cevap

0

görünüyor. Bir ses rotası değiştirme dinleyicisi geri aramayı eklemeyi öneririm.

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

Sonra init yönteminde bir geri arama ekleyin:: Her şeyden önce bir yöntem bildirmek

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

Ve nihayet, bir geri arama uygulaması ekleyin:

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.."); 
    } 
} 

Umut bu yardım! En azından diğer insanlar için yararlı bir ipucu olacaktır.