iOS监听音量调节

iOS的AVFoundation框架提供了基本的音视频播放工具,咱们基本上能够靠其中提供的类完成绝大部分的音视频播听任务。可是在音频播放的输出音量的处理上,苹果的策略比较保守。尽管AVPlayerAVPAudiolayerzhe这些类提供了音量调节功能,但这些音量控制属于App级别的控制。好处就是音量调节独立于系统音量,调节大小时不会影响系统音量。但有时候咱们可能但愿修改系统音量,以避免在调节声音的时候,若是系统音量太小,App调节音量效果不明显。通常来讲要调节系统音量会有如下方法:编程

请注意:修改系统音量没法在模拟器上看到效果,必须使用真机调试才能看到效果!session

使用MPVolumeView

这个方法是苹果官方推荐的方法。MPVolumeView是Media Player Framework中的一个UI组件,直接包含了对系统音量和Airplay设备的音频镜像路由的控制功能。其中包含一个MPVolumeSlider的subview用来控制音量。这个MPVolumeSlider是一个私有类,咱们没法手动建立此类,但这个类是UISlider的子类。MPVolumeView的使用很简单,只须要将其加入到一个父视图中,给予父视图合适的大小,再建立MPVolumeView示例,将其加入到父视图中便可,苹果官方的文档1中有示例代码能够参考。框架

这个方法的缺点以下:ide

  • UI可定制的的程度低。 MPVolumeView只提供了有限的几个方法来定制其中的Slider和Route Button的样式,并且基本上只能靠换图片解决。若是你想把Slider操做换成Button或者其余的UI组件,那是不可能的。工具

  • 没有额外的音量控制API。 目前为止没有发现iOS的公开API中有能够直接操做系统音量的,因此修改系统音量只能使用这个UI组件。ui

若是还想给UI加入手势操做来控制音量,这种直接使用MPVolumeView是作不到的,那么有没有什么方法能够绕过这限制呢?办法仍是有的。this

编程实现系统音量调节2

上一小节咱们提到了MPVolumeView这个组件中,有一个subview来控制音量,即MPVolumeSlider。其实咱们能够经过遍历MPVolumeView实例的subviews来获得MPVolumeSlider的实例,从而经过这个UI组件来操做系统音量。spa

经过MPVolumeSlider的实例来操做系统音量

咱们首先经过建立一个MPVolumeView,而后遍历找出MPVolumeSlider的实例。这个实例提供setValue:animated:方法来设置系统音量。咱们也能够经过volumeSlider.value这个属性来获取当前的系统音量。具体的代码以下:操作系统

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审核拒掉的风险。

相关文章
相关标签/搜索