文档章节

iOS调节系统音量

小春0618
 小春0618
发布于 2015/06/13 20:10
字数 1435
阅读 1538
收藏 8

iOS的AVFoundation框架提供了基本的音视频播放工具,我们基本上可以靠其中提供的类完成绝大部分的音视频播放任务。但是在音频播放的输出音量的处理上,苹果的策略比较保守。尽管AVPlayerAVPAudiolayerzhe这些类提供了音量调节功能,但这些音量控制属于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是做不到的,那么有没有什么方法可以绕过这限制呢?办法还是有的。

编程实现系统音量调节2

上一小节我们提到了MPVolumeView这个组件中,有一个subview来控制音量,即MPVolumeSlider。其实我们可以通过遍历MPVolumeView实例的subviews来得到MPVolumeSlider的实例,从而通过这个UI组件来操作系统音量。

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


本文转载自:http://segmentfault.com/a/1190000002401961

共有 人打赏支持
小春0618
粉丝 8
博文 40
码字总数 10552
作品 0
海淀
程序员
加载中

评论(1)

小沐植
小沐植
iOS8自适应布局教程 http://www.elsyy.com/course/6480 13
跨平台媒体播放器框架 - SGPlayer

SGPlayer SGPlayer 是一款基于 AVPlayer、FFmpeg 的媒体资源播放器框架。支持360°全景视频,VR视频,RTMP、RTSP 等直播流;同时支持 iOS、macOS、tvOS 三个平台。 功能特点 支持播放360°全...

libobjc
2017/04/21
0
1
10个帮程序员和站长减压放松的良心网站!

Calm 这是同类型中最火的网站了,站如其名,「平和」,通过自然的图像(阳光下的暖流、淙淙的小溪等)与缓缓的音乐,帮你在短时间内放松下来。 左侧有时间设定,从 2 分钟到 20 分钟,右底部...

程序袁_绪龙
2014/09/02
0
0
iOS/安卓全能视频播放器推荐

前言 前几天有朋友下载了些 ts 格式的高清电视剧,但是没法在 iPad(iOS) 上播放,只好先在电脑上转换成 MP4 格式,转换起来很花时间,结果也不如意。 其实现在各平台都有全格式支持的播放器,...

己立
07/22
0
0
苹果WWDC2018开发者大会总结,不错过任何一个重点,最后发布的新品你一定意想不到

前言: 北京时间2018年6月5日1点,苹果在美国圣何塞举行苹果全球开发者大会(WWDC)。在此次开发者大会中,推出全新iOS 12全新系统版本,以及全新watchOS 5,tvOS和macOS Mojave。 iOS 12:增...

马蹄上的茉莉清香i
06/06
0
0
关于IOS越狱和解锁必须知道的一些事情

1.什么是越狱? 苹果开发的每一款产品,包括iphone,ipad,i pod touch和Mac,想要安装软件都是需要从App Store上面购买的,其实购买的不是软件,而是苹果在软件中植入的一个认证,于是大家就...

eric_zhang
2012/12/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Python基础案例教程

一、超市买薯片 # 用户输入薯片的单价danjia = float(input("薯片的单价"))# 用户输入购买袋数daishu = int(input("购买的袋数"))# 计算总价zongjia = danjia * daishu# 输出结果...

linuxprobe16
49分钟前
0
0
采用CXF框架发布webservice

package cn.it.ws.cxf.a;import javax.jws.WebParam;import javax.jws.WebResult;import javax.jws.WebService;@WebService(serviceName="languageManager")public interface ......

江戸川
51分钟前
0
0
HashMap工作原理及实现

HashMap工作原理及实现 1. 概述 什么时候会使用HashMap?他有什么特点? 知道HashMap的工作原理吗? 知道get和put的原理吗? 知道hash的实现吗?为什么要这样实现? 如果HashMap的大小超过了...

傅小水water
58分钟前
1
0
swagger如何屏蔽某些接口,不对外公开--使用@ApiIgnore

@ApiIgnore@RestController@RequestMapping(value = "/i18nTest")public class I18nTestController {// @Resource// private LocaleMessageSourceService localeMessageSourceSe......

karma123
今天
1
0
大数据技术学习,大数据处理为何选择Spark,而不是Hadoop

大数据处理为何选择Spark,而不是Hadoop。 一.基础知识 1.Spark Spark是一个用来实现快速而通用的集群计算的平台。 在速度方面,Spark扩展了广泛使用的MapReduce计算模型,而且高效地支持更多...

董黎明
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部