如何监听iOS设备静音按钮的状态

通过使用指定方式播放一段极小音频,比较播放的开始和完成时间,来判断当前静音按钮的状态。
我也针对常见的对音量方面的需求做了一个小工具,欢迎大家使用、指正。


2018年9月6日更新:
1.【修正】——App从后台切到前台时【AVPlayerItemDidPlayToEndTimeNotification】通知被无故调用的问题;
2.【修正】——在有其他音/视频播放时,初始化该工具会使正在播放的音/视频间断一下的问题。

解释下第一个bug:实际使用中发现,在使用原有AVPlayerItem的方式进行预播放音频后(用于本文最后说的那个小坑),使用AVPlayer正常播放音/视频,此时将App从后台切换到前台,用于预播放音频的AVPlayerItem会无故发出AVPlayerItemDidPlayToEndTimeNotification的通知,可能会影响到业务层。
为什么说是无故呢?因为App从后台切换到前台时,预播放音频早已经结束了很久,而且,当时结束时已经发出过AVPlayerItemDidPlayToEndTimeNotification通知了;也就是说,本已结束的音/视频,会由于从后台切到前台而反复发出AVPlayerItemDidPlayToEndTimeNotification通知(这也是很神奇,并没有想通是什么原理,也没有查到相关的资料,如有大神了解,希望您不吝赐教~)。


刚开始看到这个需求的时候,觉得这个应该会有相应的api,直接调用就可以了。但是实际一查才发现:并没有,准确的说是iOS5之后的版本相关api就不再支持了。细想下,其实这也挺符合Apple的行事作风的,app只要为用户提供服务就好了,用户的操作并不会让你知晓,极尽的保护用户的一切隐私

那么在iOS5之后,我们在没有直接api的情况下,应该如何检测设备静音按钮处于什么状态呢?曲线救国~

首先鸣谢下RBDMuteSwitch这个库。因为我所使用核心方法也是借鉴了这个库中的方式来实现。

  • 首先,这里我们要使用到一种平时不是很常用的播放音频的方式
-(void)monitorMute{

    CFURLRef soundFileURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("detection"), CFSTR("aiff"), NULL);
    SystemSoundID soundFileID;
    AudioServicesCreateSystemSoundID(soundFileURLRef, &soundFileID);
    AudioServicesAddSystemSoundCompletion(soundFileID, NULL, NULL, soundCompletionBlock, (__bridge void*) self);
    AudioServicesPlaySystemSound(soundFileID);
    
}

static void soundCompletionBlock(SystemSoundID SSID, void *mySelf){
    AudioServicesRemoveSystemSoundCompletion(SSID);
    [[XTVolumeMonitor defaultMonitor] playToEnd];
}

AudioServicesPlaySystemSound方法支持的格式少,而且还要求音频时长为30s以下,但是,他有一个对我们最有用的特性:如果静音按钮为静音状态,那么会《立即》执行预先植入的soundCompletionBlock。相信到这您就可以瞬间想通后面的一切问题了~

针对这一特性,我通过记录开始播放和完成播放的时间,计算二者的差值,来判断静音按钮的状态。
由此也可以发现,这里需要以回调的方式来向询问者返回值,这里我选择了block,具体方式下文详述。而且为了回调足够及时,所以使用了一个长度仅为0.1s的音频(该音频素材也取自RBDMuteSwitch,再次鸣谢!)。

还有一点想强调一下,就是这里的通过静音按钮置于静音将音量调小至0,是两种不同的状态,对于该种检测方式,只有通过静音按钮置于静音的方式,才会被判断为静音状态,完全满足我的要求。

  • 那么其他的静音状态或者音量状态,怎么办呢?
    根据我目前能够想象到的需求,我的这个工具主要提供了三个api:
  1. 判断当前静音按钮是否为静音状态
/**
 用于回调当前静音按钮是否为静音状态的block

 @param isMute 如果静音按钮当前为静音状态,则为YES,否则为NO
 */
typedef void(^MuteBlock)(BOOL isMute);

/**
 当前静音按钮是否为静音状态
 */
@property (nonatomic, copy) MuteBlock muteBlock;
  1. 获取当前的真实音量(静音按钮处于静音状态时音量为0)
/**
 用于回调当前真实音量的block
 
 @param currentRealVolume 当前的真实音量
 */
typedef void(^RealVolumeBlock)(CGFloat currentRealVolume);

/**
 当前的真实音量(静音按钮处于静音状态时音量为0)
 */
@property (nonatomic, copy) RealVolumeBlock realVolumeBlock;
  1. 监听音量变化(不考虑静音按钮处于静音状态的情况,该情况下仍正常返回实际的音量值,而不是0)
/**
 用于监听音量变化的block

 @param oldVolume 原始音量值
 @param newVolume 新的音量值
 */
typedef void(^VolumeChangeBlock)(CGFloat oldVolume, CGFloat newVolume);

/**
 监听音量变化(不考虑静音按钮处于静音状态的情况,该情况下仍正常返回实际的音量值,而不是0)
 */
@property (nonatomic, copy) VolumeChangeBlock volumeChangeBlock;
  • 这里有一个小坑需要强调下:
    常规的获取当前音量和监听音量变化的操作,相信大家都能瞬间实现,但是,如果你在执行这两个方法之前,没有过任何一次的音频播放,那么获取到的这两个值都是不准确的:
    获取当前音量一直为一个值,也就是说即使你调整了音量,获取的还是最初的值;
    对音量变化的监听则彻底不会触发-(void)observeValueForKeyPath:ofObject: change:context:方法。
    因此,我在工具的初始化方法中,执行了一次极小音频的播放,保证您在任何情况下获取的音量值及对音量变化的监听都是正确的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,113评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,644评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,340评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,449评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,445评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,166评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,442评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,105评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,601评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,066评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,161评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,792评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,351评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,352评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,584评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,618评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,916评论 2 344

推荐阅读更多精彩内容