iOS --- 音量調節檢視MPVolumeView的使用
在之前的一篇文章 iOS — 使用AVFoundation的AVAudioPlayer來播放音訊中,簡單介紹了AVAudioPlayer的使用。其中通過AVAudioPlayer物件例項的volume屬性可以調節該APP的音量大小。但不會影響到iOS系統音量。那如果要對系統音量進行調節呢?
MPVolumeView
MPVolumeView是MediaPlayer框架中的一個元件,包含了對系統音量和AirPlay裝置的音訊映象路由的控制功能。MPVolumeView有三個subview,其中私有類(無法手動建立,也無法使用isKindOfClass方法)MPVolumeSlider用來控制音量大小,繼承自UISlider。
另外還有UILabel和MPButton兩個subview,暫時沒有使用到。
將MPVolumeView物件例項當做一個subview,新增到父view中即可使用,但其UI可定製性很低。使用前要import MediaPlayer。
if (mpVolumeView == nil) {
volumeLabel = UILabel(frame: CGRectMake(0, 100, self.view.frame.width, 30))
volumeLabel.textAlignment = NSTextAlignment.Center
self.view.addSubview(volumeLabel)
mpVolumeView = MPVolumeView(frame: CGRectMake(20, 150, self.view.frame.width - 40, 30))
self.view .addSubview(mpVolumeView)
for var view: UIView in mpVolumeView.subviews {
print(view.description)
if (NSStringFromClass(view.classForCoder) == "MPVolumeSlider") {
volumeSlider = view as! UISlider;
volumeSlider.sendActionsForControlEvents(.TouchUpInside)
}
}
}
volumeSlider就呈現在MPVolumeView的位置上,其值對應當前的系統音量。
關於上邊實現0.0的volumeLabel,大家可以不必關心,未將其與系統音量值繫結起來而已。
關於這句判斷, Swift和Objective-C的方式不一樣:
// Swift
if (NSStringFromClass(view.classForCoder) == "MPVolumeSlider") {
// Objective-C:
if ([view.class.description isEqualToString:@"MPVolumeSlider"]) {
使用系統音量鍵調節音量
經過以上步驟之後,通過系統音量鍵調節音量大小的時候,也能控制_volumeSlider的值。
但會有一個問題:
即系統音量提示會出來干擾,那這種對螢幕的遮蓋在一些場合是要去掉的,如拍照等。
其實,這裡有兩個場景:
- 裝置後臺有背景音樂正在播放(如QQ音樂等)
- 裝置後臺沒有背景音樂播放
對於場景1,系統音量提示則會隱藏掉。但是對於場景2,系統音量提示會自動呈現出來。
如何去除該提示呢?嘗試了很久找到了下邊的方法:
if AVAudioSession.sharedInstance().otherAudioPlaying {
// 場景1
do {
try AVAudioSession.sharedInstance().setActive(false)
} catch {
}
} else {
// 場景2
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch {
}
}
使用AVAudioSession來判斷當前是否有背景音樂播放,然後對於場景2,設定當前AVAudioSession為active即可隱藏系統音量提示。
暫時不知道還有沒有其他更好的方法?
這裡提供了一種方法,但經過試驗,並不適用該場景。
對於Objective-C的寫法:
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error = nil;
if (audioSession.otherAudioPlaying) {
[audioSession setActive:NO error:&error];
} else {
[audioSession setActive:YES error:&error];
}
監聽系統音量變化
使用通知AVSystemController_SystemVolumeDidChangeNotification即可監控系統音量變換,
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("volumeChanged:"), name: "AVSystemController_SystemVolumeDidChangeNotification", object: nil)
記得用完取消監聽就好了。
AVAudioSession
AVAudioSession是AVFoundation框架引入的,常用其setCategory方法設定音訊屬性。
[audioSession setCategory:AVAudioSessionCategoryAmbient withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
可選屬性如下:
#pragma mark -- Values for the category property --
/* Use this category for background sounds such as rain, car engine noise, etc.
Mixes with other music. */
AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient;
/* Use this category for background sounds. Other music will stop playing. */
AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient;
/* Use this category for music tracks.*/
AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback;
/* Use this category when recording audio. */
AVF_EXPORT NSString *const AVAudioSessionCategoryRecord;
/* Use this category when recording and playing back audio. */
AVF_EXPORT NSString *const AVAudioSessionCategoryPlayAndRecord;
/* Use this category when using a hardware codec or signal processor while
not playing or recording audio. */
AVF_EXPORT NSString *const AVAudioSessionCategoryAudioProcessing;
AVF_EXPORT NSString *const AVAudioSessionCategoryMultiRoute NS_AVAILABLE_IOS(6_0);