廢話不多說說一下現狀 網上好多關於揚聲器的操作,但是問題多多,SDK7.X 和SDK7.X以上版本有點詫異 #import #import #import @interface AudioManager : NSObject { AVAudioPlayer *m_audioPlayer; } @property (atomic, readonly)BOOL _isSpeakerOn; @property (atomic, readonly)BOOL _isHeadsetOn; +(AudioManager*)shared; // 打開揚聲器 - (void)setSpeakerOn; // 關閉揚聲器 - (void)setSpeakerOff; @end // // AudioManager.m // AvconNetAndCallDemo // // Created by zjq on 14-7-21. // Copyright (c) 2014年 zjq. All rights reserved. // #import AudioManager.h #import #define IOSVersion [[UIDevice currentDevice].systemVersion floatValue] @implementation AudioManager @synthesize _isSpeakerOn; @synthesize _isHeadsetOn; - (id)init { self = [super init]; if (self) { _isSpeakerOn = NO; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; //默認情況下揚聲器播放 [audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil]; [audioSession setActive:YES error:nil]; UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback; AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory); UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride); AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, (__bridge void *)(self)); } return self; } static AudioManager *_audioManager = NULL; +(AudioManager*)shared { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _audioManager = [[AudioManager alloc] init]; }); return _audioManager; } - (void)setSpeakerOn { NSLog(@setSpeakerOn:%d,[NSThread isMainThread]); UInt32 doChangeDefaultRoute = kAudioSessionOverrideAudioRoute_Speaker; AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof (doChangeDefaultRoute), &doChangeDefaultRoute ); _isSpeakerOn = [self checkSpeakerOn]; _isHeadsetOn = NO; //[self resetOutputTarget]; } - (void)setSpeakerOff { UInt32 doChangeDefaultRoute = kAudioSessionOverrideAudioRoute_None; AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof (doChangeDefaultRoute), &doChangeDefaultRoute ); _isSpeakerOn = [self checkSpeakerOn]; } - (BOOL)checkSpeakerOn { CFStringRef route; UInt32 propertySize = sizeof(CFStringRef); AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route); if((route == NULL) || (CFStringGetLength(route) == 0)) { // Silent Mode NSLog(@AudioRoute: SILENT, do nothing!); } else { NSString* routeStr = (__bridge NSString*)route; NSRange speakerRange = [routeStr rangeOfString : @Speaker]; if (speakerRange.location != NSNotFound) return YES; } return NO; } - (BOOL)hasHeadset { CFStringRef route; UInt32 propertySize = sizeof(CFStringRef); AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route); if((route == NULL) || (CFStringGetLength(route) == 0)) { // Silent Mode NSLog(@AudioRoute: SILENT, do nothing!); } else { NSString* routeStr = (__bridge NSString*)route; NSLog(@AudioRoute: %@, routeStr); if ([routeStr isEqualToString:@ReceiverAndMicrophone]) { // static dispatch_once_t onceToken; // dispatch_once(&onceToken, ^{ // [self setSpeakerOn]; // }); [self setSpeakerOn]; } NSRange headphoneRange = [routeStr rangeOfString : @Headphone]; NSRange headsetRange = [routeStr rangeOfString : @Headset]; if (headphoneRange.location != NSNotFound) { return YES; } else if(headsetRange.location != NSNotFound) { return YES; } } return NO; } // 判斷麥克風是否有用 - (BOOL)hasMicphone { return [[AVAudioSession sharedInstance] isInputAvailable]; } - (void)erjiOutPutTarget { BOOL hasHeadset = [self hasHeadset]; if (hasHeadset) { _isHeadsetOn = YES; } NSLog (@Will Set output target is_headset = %@ ., hasHeadset?@YES:@NO); UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None; AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride); } - (void)resetOutputTarget { BOOL hasHeadset = [self hasHeadset]; NSLog (@Will Set output target is_headset = %@ ., hasHeadset?@YES:@NO); UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride); _isHeadsetOn = NO; } void audioRouteChangeListenerCallback (void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueS, const void *inPropertyValue) { if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return; // Determines the reason for the route change, to ensure that it is not // because of a category change. CFDictionaryRef routeChangeDictionary = (CFDictionaryRef)inPropertyValue; CFNumberRef routeChangeReasonRef = (CFNumberRef)CFDictionaryGetValue (routeChangeDictionary, CFSTR (kAudioSession_AudioRouteChangeKey_Reason)); SInt32 routeChangeReason; CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason); NSLog(@<< NSLog(@[=======%@,inUserData); AudioManager *pMgr = (__bridge AudioManager *)inUserData; //沒有耳機 if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) { [pMgr setSpeakerOn]; [pMgr resetOutputTarget]; } else if (routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable) { [pMgr erjiOutPutTarget]; }else if (routeChangeReason == kAudioSessionRouteChangeReason_Override){ [pMgr setSpeakerOn]; [pMgr resetOutputTarget]; } NSLog(@-------->%f,IOSVersion); //if (IOSVersion >= 8.0) { if (routeChangeReason==8) { [pMgr hasHeadset]; } //} } //- (BOOL)isAirplayActived //{ // CFDictionaryRef currentRouteDescriptionDictionary = nil; // UInt32 dataSize = sizeof(currentRouteDescriptionDictionary); // AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, ¤tRouteDescriptionDictionary); // // BOOL airplayActived = NO; // if (currentRouteDescriptionDictionary) // { // CFArrayRef outputs = CFDictionaryGetValue(currentRouteDescriptionDictionary, kAudioSession_AudioRouteKey_Outputs); // if(outputs != NULL && CFArrayGetCount(outputs) > 0) // { // CFDictionaryRef currentOutput = CFArrayGetValueAtIndex(outputs, 0); // //Get the output type (will show airplay / hdmi etc // CFStringRef outputType = CFDictionaryGetValue(currentOutput, kAudioSession_AudioRouteKey_Type); // // airplayActived = (CFStringCompare(outputType, kAudioSessionOutputRoute_AirPlay, 0) == kCFCompareEqualTo); // } // CFRelease(currentRouteDescriptionDictionary); // } // return airplayActived; //} /* - (void)openloudspeaker{ //初始化播放器的時候如下設置 UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback; AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory); UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride); AVAudioSession *audioSession = [AVAudioSession sharedInstance]; //默認情況下揚聲器播放 [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; [self handleNotification:YES]; } #pragma mark - 監聽聽筒or揚聲器 - (void) handleNotification:(BOOL)state { [[UIDevice currentDevice] setProximityMonitoringEnabled:state]; //建議在播放之前設置yes,播放結束設置NO,這個功能是開啟紅外感應 if(state)//添加監聽 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sensorStateChange:) name:@UIDeviceProximityStateDidChangeNotification object:nil]; else//移除監聽 [[NSNotificationCenter defaultCenter] removeObserver:self name:@UIDeviceProximityStateDidChangeNotification object:nil]; } //處理監聽觸發事件 -(void)sensorStateChange:(NSNotificationCenter *)notification; { //如果此時手機靠近面部放在耳朵旁,那麼聲音將通過聽筒輸出,並將屏幕變暗(省電啊) if ([[UIDevice currentDevice] proximityState] == YES) { NSLog(@Device is close to user); [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; } else { NSLog(@Device is not close to user); [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; } } */ @end