2010-12-15 63 views
15

在測試過程中,客戶注意到拔下耳機時iPhone中的視頻播放暫停。他想要類似的音頻播放功能,也許可以彈出消息。耳機拔出時是否有事件發生?

是否有人知道是否有某種事件可以讓我做到這一點?

回答

18

請參閱音頻會話編程指南中的Responding to Route Changes

-Marc

+0

謝謝!此頁面從此鏈接,http://developer.apple.com/library/ios/#documentation/Audio/Conceptual/AudioSessionProgrammingGuide/Cookbook/Cookbook.html#//apple_ref/doc/uid/TP40007875-CH6-SW8。有'用戶插入或拔出耳機,或停靠或取消鎖定設備,從而添加或刪除音頻連接時調用回調'的示例代碼。還沒有嘗試過,但看起來很完美。歡呼的單挑。 – 2010-12-15 17:06:00

+0

真棒:)。沒有頭痛的回調 – iEinstein 2014-06-04 15:14:43

1

這裏是全面落實我最終用於當插入耳機(和不插電)發送事件。

我需要處理一些相當複雜的事情,以確保應用程序從後臺返回後仍能正常工作。

CVAudioSession.h文件

#import <Foundation/Foundation.h> 

#define kCVAudioInputChangedNotification @"kCVAudioInputChangedNotification" 
#define kCVAudioInterruptionEnded @"kCVAudioInterruptionEnded" 

@interface CVAudioSession : NSObject 
+(void) setup; 
+(void) destroy; 
+(NSString*) currentAudioRoute; 
+(BOOL) interrupted; 
@end 

CVAudioSession.m文件

#import "CVAudioSession.h" 
#import <AudioToolbox/AudioToolbox.h> 

@implementation CVAudioSession 

static BOOL _isInterrupted = NO; 

+(void) setup { 
    NSLog(@"CVAudioSession setup"); 

    // Set up the audio session for recording 
    OSStatus error = AudioSessionInitialize(NULL, NULL, interruptionListener, (__bridge void*)self); 

    if (error) NSLog(@"ERROR INITIALIZING AUDIO SESSION! %ld\n", error); 
    if (!error) { 
     UInt32 category = kAudioSessionCategory_RecordAudio; // NOTE CANT PLAY BACK WITH THIS 
     error = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category); 
     if (error) NSLog(@"couldn't set audio category!"); 

     error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, (__bridge void*) self); 
     if (error) NSLog(@"ERROR ADDING AUDIO SESSION PROP LISTENER! %ld\n", error); 
     UInt32 inputAvailable = 0; 
     UInt32 size = sizeof(inputAvailable); 

     // we do not want to allow recording if input is not available 
     error = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, &size, &inputAvailable); 
     if (error) NSLog(@"ERROR GETTING INPUT AVAILABILITY! %ld\n", error); 

     // we also need to listen to see if input availability changes 
     error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable, propListener, (__bridge void*) self); 
     if (error) NSLog(@"ERROR ADDING AUDIO SESSION PROP LISTENER! %ld\n", error); 

     error = AudioSessionSetActive(true); 
     if (error) NSLog(@"CVAudioSession: AudioSessionSetActive (true) failed"); 
    } 
} 

+ (NSString*) currentAudioRoute { 
    UInt32 routeSize = sizeof (CFStringRef); 
    CFStringRef route; 

    AudioSessionGetProperty (kAudioSessionProperty_AudioRoute, 
          &routeSize, 
          &route); 

    NSString* routeStr = (__bridge NSString*)route; 
    return routeStr; 
} 

+(void) destroy { 
    NSLog(@"CVAudioSession destroy"); 

    // Very important - remove the listeners, or we'll crash when audio routes etc change when we're no longer on screen 
    OSStatus stat = AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange, propListener, (__bridge void*)self); 
    NSLog(@".. AudioSessionRemovePropertyListener kAudioSessionProperty_AudioRouteChange returned %ld", stat); 

    stat = AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioInputAvailable, propListener, (__bridge void*)self); 
    NSLog(@".. AudioSessionRemovePropertyListener kAudioSessionProperty_AudioInputAvailable returned %ld", stat); 

    AudioSessionSetActive(false); // disable audio session. 
    NSLog(@"AudioSession is now inactive"); 
} 

+(BOOL) interrupted { 
    return _isInterrupted; 
} 

// Called when audio is interrupted for whatever reason. NOTE: doesn't always call the END one.. 
void interruptionListener( void * inClientData, 
          UInt32 inInterruptionState) { 

    if (inInterruptionState == kAudioSessionBeginInterruption) 
    { 
     _isInterrupted = YES; 

     NSLog(@"CVAudioSession: interruptionListener kAudioSessionBeginInterruption. Disable audio session.."); 

     // Try just deactivating the audiosession.. 
     OSStatus rc = AudioSessionSetActive(false); 
     if (rc) { 
      NSLog(@"CVAudioSession: interruptionListener kAudioSessionBeginInterruption - AudioSessionSetActive(false) returned %.ld", rc); 
     } else { 
      NSLog(@"CVAudioSession: interruptionListener kAudioSessionBeginInterruption - AudioSessionSetActive(false) ok."); 
     } 



    } else if (inInterruptionState == kAudioSessionEndInterruption) { 

     _isInterrupted = NO; 

     // Reactivate the audiosession 
     OSStatus rc = AudioSessionSetActive(true); 
     if (rc) { 
      NSLog(@"CVAudioSession: interruptionListener kAudioSessionEndInterruption - AudioSessionSetActive(true) returned %.ld", rc); 
     } else { 
      NSLog(@"CVAudioSession: interruptionListener kAudioSessionEndInterruption - AudioSessionSetActive(true) ok."); 
     } 

     [[NSNotificationCenter defaultCenter] postNotificationName:kCVAudioInterruptionEnded object:(__bridge NSObject*)inClientData userInfo:nil]; 
    } 
} 

// This is called when microphone or other audio devices are plugged in and out. Is on the main thread 
void propListener( void *     inClientData, 
        AudioSessionPropertyID inID, 
        UInt32     inDataSize, 
        const void *   inData) 
{ 
    if (inID == kAudioSessionProperty_AudioRouteChange) 
    { 
     CFDictionaryRef routeDictionary = (CFDictionaryRef)inData; 
     CFNumberRef reason = (CFNumberRef)CFDictionaryGetValue(routeDictionary, CFSTR(kAudioSession_AudioRouteChangeKey_Reason)); 
     SInt32 reasonVal; 
     CFNumberGetValue(reason, kCFNumberSInt32Type, &reasonVal); 
     if (reasonVal != kAudioSessionRouteChangeReason_CategoryChange) 
     { 
      NSLog(@"CVAudioSession: input changed"); 
      [[NSNotificationCenter defaultCenter] postNotificationName:kCVAudioInputChangedNotification object:(__bridge NSObject*)inClientData userInfo:nil]; 
     } 
    } 
    else if (inID == kAudioSessionProperty_AudioInputAvailable) 
    { 
     if (inDataSize == sizeof(UInt32)) { 
      UInt32 isAvailable = *(UInt32*)inData; 

      if (isAvailable == 0) { 
       NSLog(@"AUDIO RECORDING IS NOT AVAILABLE"); 
      } 
     } 
    } 
} 

@end 
5

這改變與iOS 7,你只需要聽命名AVAudioSessionRouteChangeNotification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChanged:) name:AVAudioSessionRouteChangeNotification object:nil]; 
+0

這可以用於視頻播放器,但只有當你使用'AVAudioSession'。 – Legoless 2016-07-31 16:11:46

2

斯威夫特的通知3.0 @ snakeoil的解決方案:

NotificationCenter.default.addObserver(self, selector: #selector(YourViewController.yourMethodThatShouldBeCalledOnChange), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil) 
+0

太棒了!非常感謝! – 2017-04-18 01:25:31