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的位置上,其值对应当前的系统音量。

iOS --- 音量调节视图MPVolumeView的使用_第1张图片

关于上边实现0.0的volumeLabel,大家可以不必关心,未将其与系统音量值绑定起来而已。
关于这句判断, Swift和Objective-C的方式不一样:

// Swift
if (NSStringFromClass(view.classForCoder) == "MPVolumeSlider") {
// Objective-C:
if ([view.class.description isEqualToString:@"MPVolumeSlider"]) {

使用系统音量键调节音量

经过以上步骤之后,通过系统音量键调节音量大小的时候,也能控制_volumeSlider的值。
但会有一个问题:

iOS --- 音量调节视图MPVolumeView的使用_第2张图片

即系统音量提示会出来干扰,那这种对屏幕的遮盖在一些场合是要去掉的,如拍照等。
其实,这里有两个场景:

  1. 设备后台有背景音乐正在播放(如QQ音乐等)
  2. 设备后台没有背景音乐播放

对于场景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);

Demo

Demo地址: DemoMPVolum

你可能感兴趣的:(iOS-移动开发,iOS移动开发)