iOS編程修改系統音量

來源:互聯網
上載者:User

標籤:

iOS的AVFoundation架構提供了基本的音視頻播放工具,我們基本上可以靠其中提供的類完成絕大部分的音視頻播放任務。但是在音頻播放的輸出音量的處理上,蘋果的策略比較保守。儘管AVPlayer和AVPAudiolayerzhe這些類提供了音量大小功能,但這些音量控制屬於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是做不到的,那麼有沒有什麼方法可以繞過這限制呢?辦法還是有的。 

編程實現系統音量大小 

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

通過MPVolumeSlider的執行個體來作業系統音量 

我們首先通過建立一個MPVolumeView,然後遍曆找出MPVolumeSlider的執行個體。這個執行個體提供setValue:animated:方法來設定系統音量。我們也可以通過volumeSlider.value這個屬性來擷取當前的系統音量。具體的代碼如下: 

 

?
1234567891011121314151617 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時,同樣會彈出提示。 
還有問題,我修改了系統音量但是不是通過我的UI 

另一個可能的情況就是使用者自己通過硬體的音量大小按鈕(位於裝置側邊)來調節音量,這種情況會使得你的商務邏輯出現問題,因為你只為自己的App UI寫了回調,那麼怎麼為硬體按鈕的事件添加回調呢?我們可以使用Notification Center來完成。
這裡只需要監聽AVSystemController_SystemVolumeDidChangeNotification事件即可。具體代碼如下: 

  • 首先在資源載入階段加入監聽事件的代碼 

 

?
1234567891011121314 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];

 

  • 然後實現事件回調方法 

 

?
1234 - (void)volumeChanged:(NSNotification *)notification{    // service logic here.}

 

  • 最後記得在資源回收時取消掉事件監聽 

 

?
1234 - (void)dealloc{    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];}

 

這樣,每次使用者使用硬體按鈕調節音量的時候也會執行你寫好的邏輯。 

以上除了第一個方案以外,所有的解決方案都屬於非官方的hack性質的方法,但是都沒有調用私人API,所以沒有被Apple審核拒掉的風險。

 

說法二:

在iOS裝置中音量分為耳機音量和手機音量,二者相互獨立:但是不管耳機還是 手機都是調用一種方法改變音量, 在裝置上有耳機的時候改變耳機音量,沒有耳機的時候改變手機音量。

在github中有一個開源項目:SystemVolumeNativeExtension . (點擊擷取連結)

 

在解壓後找到 SystemVolumeNativeExtension/IOSVolumeLib/IOSVolumeLib/IOSVolumeLib.m 這個檔案.

不用看太多,只需要關註:

 

float getVolumeLevel(){    MPVolumeView *slide = [MPVolumeView new];    UISlider *volumeViewSlider;        for (UIView *view in [slide subviews])    {        if ([[[view class] description] isEqualToString:@"MPVolumeSlider"])        {            volumeViewSlider = (UISlider *) view;        }    }        float val = [volumeViewSlider value];    [slide release];        return val;}


&

 

 

FREObject setVolume(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]){    double newVolume;    FREGetObjectAsDouble(argv[0], &newVolume);        [[MPMusicPlayerController applicationMusicPlayer] setVolume: newVolume];        return NULL;}


如個你覺得這也有些繁瑣: 那你直接使用:

 

 

[[MPMusicPlayerController applicationMusicPlayer] setVolume: newVolume];

newVolume的範圍是 0 ~ 1;

 

簡單說就是用這個即可設定耳機音量。

iOS編程修改系統音量

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.