iOS --- 音量调节视图MPVolumeView的使用

来源:互联网 发布:mac mobi转pdf软件 编辑:程序博客网 时间:2024/04/30 09:23

在之前的一篇文章 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的方式不一样:

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

使用系统音量键调节音量

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

这里写图片描述

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

  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

0 0