開發過程中錄音和播放這塊碰到了一些問題,麻煩的主要有三個: 檢測是否有聲音輸入裝置 當有多個聲音輸出裝置時,指定聲音輸出裝置 檢測耳機的插入和拔出
第一個問題,對於iTouch和iPad等本身不帶麥克風的裝置,需要檢查是否插入了帶錄音功能的耳機;對於iphone,由於其本身已近內建麥克風,所以相對容易。第二個問題,當在本身帶有外放的裝置上插入耳機等輸出裝置時,就出現了多個輸出裝置,需要實現在程式中指定將聲音輸出到哪裡。第三個問題,插入/拔出耳機必然引起聲音輸出裝置的變化,而如果是在iTouch和iPad上插入/拔出了帶麥克風的耳機,則必然引起聲音輸入裝置的變化。
1. 檢測聲音輸入裝置
[plain] view plaincopyprint? - (BOOL)hasMicphone { return [[AVAudioSession sharedInstance] inputIsAvailable]; } 2. 檢測聲音輸出裝置
對於輸出裝置的 檢測,我們只考慮了2個情況,一種是裝置自身的外放(iTouch/iPad/iPhone都有),一種是當前是否 插入了帶外放的 耳機。iOS已經提供了相關方法用於擷取當前的所有聲音裝置,我們只需要檢查在這些裝置中是否存在我們所關注的那幾個就可以了。
擷取當前所有聲音裝置:
[plain] view plaincopyprint? CFStringRef route; UInt32 propertySize = sizeof(CFStringRef); AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route); 在iOS上所有可能的聲音裝置包括:
[cpp] view plaincopyprint? /* Known values of route: * "Headset" * "Headphone" * "Speaker" * "SpeakerAndMicrophone" * "HeadphonesAndMicrophone" * "HeadsetInOut" * "ReceiverAndMicrophone" * "Lineout" */ 每一項的具體代表的裝置請查考iOS文檔,此處我們關注的是是否有 耳機,所以只需要檢查在route中是否有Headphone或Headset存在,具體方法如下:
[plain] view plaincopyprint? - (BOOL)hasHeadset { #if TARGET_IPHONE_SIMULATOR #warning *** Simulator mode: audio session code works only on a device return NO; #else 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 = (NSString*)route; NSLog(@"AudioRoute: %@", routeStr); /* Known values of route: * "Headset" * "Headphone" * "Speaker" * "SpeakerAndMicrophone" * "HeadphonesAndMicrophone" * "HeadsetInOut" * "ReceiverAndMicrophone" * "Lineout" */ 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; #endif } 請注意,由於擷取AudioRoute的相關方法不能再simulator上運行(會直接crush),所以必須先行處理。
3. 設定聲音輸出裝置
在我們的項目中,存在當現正播放時使用者會插入或拔出耳機的情況。如果是播放時使用者插入了耳機,蘋果會自動將聲音輸出指向到耳機並自動將音量調整為合適大小;如果是在用耳機的播放過程中使用者拔出了耳機,聲音會自動從裝置自身的外放裡面播出,但是其音量並不會自動調大。
經過我們的測試,我們發現當播放時拔出耳機會有兩個問題(也許對你來說不是問題,但是會影響我們的app):
音樂播放自動停止
聲音音量大小不會自動變大,系統仍然以較小的聲音(在耳機上合適的聲音)來進行外放
對於第一個問題,實際上就是需要能夠檢測到耳機拔出的事件;而第二個問題則是需要當耳機拔出時強制設定系統輸出裝置修改為系統外放。
強制修改系統聲音輸出裝置:
[plain] view plaincopyprint? - (void)resetOutputTarget { BOOL hasHeadset = [self hasHeadset]; NSLog (@"Will Set output target is_headset = %@ .", hasHeadset ? @"YES" : @"NO"); UInt32 audioRouteOverride = hasHeadset ?