iOS的AVFoundation框架提供了基本的音視頻播放工具,咱們基本上能夠靠其中提供的類完成絕大部分的音視頻播聽任務。可是在音頻播放的輸出音量的處理上,蘋果的策略比較保守。儘管AVPlayer
和AVPAudiolayer
zhe這些類提供了音量調節功能,但這些音量控制屬於App級別的控制。好處就是音量調節獨立於系統音量,調節大小時不會影響系統音量。但有時候咱們可能但願修改系統音量,以避免在調節聲音的時候,若是系統音量太小,App調節音量效果不明顯。通常來講要調節系統音量會有如下方法:編程
請注意:修改系統音量沒法在模擬器上看到效果,必須使用真機調試才能看到效果!session
MPVolumeView
這個方法是蘋果官方推薦的方法。MPVolumeView
是Media Player Framework中的一個UI組件,直接包含了對系統音量和Airplay設備的音頻鏡像路由的控制功能。其中包含一個MPVolumeSlider
的subview用來控制音量。這個MPVolumeSlider
是一個私有類,咱們沒法手動建立此類,但這個類是UISlider
的子類。MPVolumeView
的使用很簡單,只須要將其加入到一個父視圖中,給予父視圖合適的大小,再建立MPVolumeView
示例,將其加入到父視圖中便可,蘋果官方的文檔1中有示例代碼能夠參考。框架
這個方法的缺點以下:ide
UI可定製的的程度低。 MPVolumeView
只提供了有限的幾個方法來定製其中的Slider和Route Button的樣式,並且基本上只能靠換圖片解決。若是你想把Slider操做換成Button或者其餘的UI組件,那是不可能的。工具
沒有額外的音量控制API。 目前爲止沒有發現iOS的公開API中有能夠直接操做系統音量的,因此修改系統音量只能使用這個UI組件。ui
若是還想給UI加入手勢操做來控制音量,這種直接使用MPVolumeView
是作不到的,那麼有沒有什麼方法能夠繞過這限制呢?辦法仍是有的。this
上一小節咱們提到了MPVolumeView
這個組件中,有一個subview來控制音量,即MPVolumeSlider
。其實咱們能夠經過遍歷MPVolumeView
實例的subviews來獲得MPVolumeSlider
的實例,從而經過這個UI組件來操做系統音量。spa
MPVolumeSlider
的實例來操做系統音量咱們首先經過建立一個MPVolumeView
,而後遍歷找出MPVolumeSlider
的實例。這個實例提供setValue:animated:
方法來設置系統音量。咱們也能夠經過volumeSlider.value
這個屬性來獲取當前的系統音量。具體的代碼以下:操作系統
MPVolumeView *volumeView = [[MPVolumeView alloc] init]; UISlider* volumeViewSlider = nil;for (UIView *view in [_instance.volumeView subviews]){ if ([view.class.description isEqualToString:@"MPVolumeSlider"]){ volumeViewSlider = (UISlider*)view; break; } }// retrieve system volumefloat systemVolume = volumeViewSlider.value;// change system volume, the value is between 0.0f and 1.0f[volumeViewSlider setValue:1.0f animated:NO];// send UI control event to make the change effect right now.[volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
上面的代碼演示如何獲取和修改系統音量,注意音量取值爲0到1之間的浮點數。調試
上面經過編程的方法能夠很完美的調節系統音量,可是每次修改都會彈出系統提示框告知:
有時候這種提示咱們未必會須要,那麼怎麼取消掉這個提示呢?實際上MPVolumeView
沒有提供任何接口來調節是否須要顯示系統音量提示。可是咱們發現一點:當MPVolumeView
處在當前視圖的層級之中時,系統就不會顯示音量提示。那麼事情好辦了,咱們只要確保兩點:
MPVolumeView
視圖處在屏幕上看不見的地方,好比某個不透明視圖的下方,或者本視圖的非可見區域,一個常見的作法就是把該視圖的frame設置爲區域之外的地方,好比volumeView.frame = CGRectMake(-1000, -100, 100, 100);
確保MPVolumeView
視圖的hidden屬性值爲NO
。由於當hidden爲YES
時,一樣會彈出提示。
另外一個可能的狀況就是用戶本身經過硬件的音量調節按鈕(位於設備側邊)來調節音量,這種狀況會使得你的業務邏輯出現問題,由於你只爲本身的App UI寫了回調,那麼怎麼爲硬件按鈕的事件添加回調呢?咱們可使用Notification Center來完成。
這裏只須要監聽AVSystemController_SystemVolumeDidChangeNotification
事件便可。具體代碼以下:
首先在資源載入階段加入監聽事件的代碼
NSError *error;// Active audio session before you listen to the volume change event.// It must be called first.// The old style code equivalent to the line below is://// AudioSessionInitialize(NULL, NULL, NULL, NULL);// AudioSessionSetActive(YES);//// Now the code above is deprecated in iOS 7.0, you should use the new// code here.[[AVAudioSession sharedInstance] setActive:YES error:&error];// add event handler, for this example, it is `volumeChange:` method[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChanged:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
而後實現事件回調方法
- (void)volumeChanged:(NSNotification *)notification { // service logic here.}
最後記得在資源回收時取消掉事件監聽
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; }
這樣,每次用戶使用硬件按鈕調節音量的時候也會執行你寫好的邏輯。
以上除了第一個方案之外,全部的解決方案都屬於非官方的hack性質的方法,可是都沒有調用私有API,因此沒有被Apple審覈拒掉的風險。