iOS調節系統音量


目錄[-]

iOS的AVFoundation框架提供了基本的音視頻播放工具,我們基本上可以靠其中提供的類完成絕大部分的音視頻播放任務。但是在音頻播放的輸出音量的處理上,蘋果的策略比較保守。盡管AVPlayerAVPAudiolayerzhe這些類提供了音量調節功能,但這些音量控制屬於App級別的控制。好處就是音量調節獨立於系統音量,調節大小時不會影響系統音量。但有時候我們可能希望修改系統音量,以免在調節聲音的時候,如果系統音量過小,App調節音量效果不明顯。一般來說要調節系統音量會有以下方法:

請注意:修改系統音量無法在模擬器上看到效果,必須使用真機調試才能看到效果!

使用MPVolumeView

這個方法是蘋果官方推薦的方法。MPVolumeView是Media Player Framework中的一個UI組件,直接包含了對系統音量和Airplay設備的音頻鏡像路由的控制功能。其中包含一個MPVolumeSlider的subview用來控制音量。這個MPVolumeSlider是一個私有類,我們無法手動創建此類,但這個類是UISlider的子類。MPVolumeView的使用很簡單,只需要將其加入到一個父視圖中,給予父視圖合適的大小,再創建MPVolumeView示例,將其加入到父視圖中即可,蘋果官方的文檔1中有示例代碼可以參考。

這個方法的缺點如下:

  • UI可定制的的程度低。  MPVolumeView只提供了有限的幾個方法來定制其中的Slider和Route Button的樣式,而且基本上只能靠換圖片解決。如果你想把Slider操作換成Button或者其他的UI組件,那是不可能的。

  • 沒有額外的音量控制API。 目前為止沒有發現iOS的公開API中有可以直接操作系統音量的,所以修改系統音量只能使用這個UI組件。

如果還想給UI加入手勢操作來控制音量,這種直接使用MPVolumeView是做不到的,那么有沒有什么方法可以繞過這限制呢?辦法還是有的。

編程實現系統音量調節2

上一小節我們提到了MPVolumeView這個組件中,有一個subview來控制音量,即MPVolumeSlider。其實我們可以通過遍歷MPVolumeView實例的subviews來得到MPVolumeSlider的實例,從而通過這個UI組件來操作系統音量。

通過MPVolumeSlider的實例來操作系統音量

我們首先通過創建一個MPVolumeView,然后遍歷找出MPVolumeSlider的實例。這個實例提供setValue:animated:方法來設置系統音量。我們也可以通過volumeSlider.value這個屬性來獲取當前的系統音量。具體的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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之間的浮點數。

有問題!我不喜歡系統彈出音量提示

上面通過編程的方法可以很完美的調節系統音量,但是每次修改都會彈出系統提示框告知:
iOS音量提示
有時候這種提示我們未必會需要,那么怎么取消掉這個提示呢?實際上MPVolumeView沒有提供任何接口來調節是否需要顯示系統音量提示。但是我們發現一點:MPVolumeView處在當前視圖的層級之中時,系統就不會顯示音量提示。那么事情好辦了,我們只要確保兩點:

  • MPVolumeView視圖處在屏幕上看不見的地方,比如某個不透明視圖的下方,或者本視圖的非可見區域,一個常見的做法就是把該視圖的frame設置為區域以外的地方,比如volumeView.frame = CGRectMake(-1000, -100, 100, 100);

  • 確保MPVolumeView視圖的hidden屬性值為NO。因為當hidden為YES時,同樣會彈出提示。

還有問題,我修改了系統音量但是不是通過我的UI

另一個可能的情況就是用戶自己通過硬件的音量調節按鈕(位於設備側邊)來調節音量,這種情況會使得你的業務邏輯出現問題,因為你只為自己的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審核拒掉的風險。

 原文地址:http://segmentfault.com/a/1190000002401961


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM