有时在项目中需要监听用户是否按下了物理声音键,然后来做某些操作,如:你自定义了一个照相功能,希望用户按下声音按键时也能进行拍照,苹果自带的照相机就有这种功能.

监听物理声音键是否按下的方法有很多中,我在这里只讲两种,也是我比较熟悉的

一、通过 NSNotificationCenter 观察一个叫做   @“AVSystemController_SystemVolumeDidChangeNotification”   的通知,

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(volumeChanged:)
name:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil]; - (void)volumeChanged:(NSNotification *)notification
{ float volume =
[[[notification userInfo]
objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"]
floatValue]; NSLog(@"current volume = %f", volume); }

二、通过为AudioSession添加一个监听者来实现,

-(BOOL)addHardKeyListener{
OSStatus s = AudioSessionAddPropertyListener(kAudioSessionProperty_CurrentHardwareOutputVolume, hardKeyListener, "kAudioSessionProperty_CurrentHardwareOutputVolume");
return s==kAudioSessionNoError;
} void hardKeyListener(
void *inClientData,
AudioSessionPropertyID inID,
UInt32 inDataSize,
const void *inData
){ if (inID != kAudioSessionProperty_CurrentHardwareOutputVolume) {
return;
}
NSLog(@"%s",inClientData);
}

对于上面这种方式,如果你直接这样,那当你按下物理音量键时不会有任何的反应,你必须在调用它之前,手动初始化audioSession

你可以

AudioSessionInitialize(NULL, kCFRunLoopDefaultMode, interruptionListenerCallback, "AudioSessionInitialize");

或者直接

AudioSessionInitialize(NULL, NULL, NULL, NULL);

当你完成了上面的任何一种方式后,你就可以很好的捕捉到音量键是否按下了,但此时你会发现,当你按下音量键时,系统自带的,反映音量设置的view会

出现,试想下,当你的用户通过物理音量键操作你的程序,比如拍照,你还给人家显示个系统的音量设置键,那用户体验可想而知了,

那怎么解决呢?

那个系统自带的音量设置view 其实就是个苹果自定义的MPVolumeView,没当音量键按下时,它都会出现,但如果当前显示的正好有一个这样的东西,那这个系统的音量设置view 就不会反客为主,自己显示出来了,而是显示你自己定义的

呵呵,我就是不需要这个,那好办,自定义一个,然后加到看不到的地方不就得了,

如下:

MPVolumeView *volumeView = [[MPVolumeView alloc]initWithFrame:CGRectMake(-, -, , )];
[self.view addSubview:volumeView];

但此时,你必须激活audioSession,不然得话它还是会自己显示得

加上代码:

AudioSessionSetActive(true);

三、完成上面得东西后,你基本上可以正常捕捉到音量键得按下,但有一点要注意:audioSession在你得程序进入后台后会变为不激活状态,当你再次回到前台后,你得程序得audioSession其实是没有激活得,此时,你按下音量键,那系统得那个音量设置view 就又出来了,所以你应该添加两个系统通知,当程序进入后台时

AudioSessionSetActive(false);  当程序进入前台时  AudioSessionSetActive(true);

而且,如果捕捉音量键得按下只在某个画面有效,那当该画面不再示但前显示得画面示应该移除捕捉动作

下面是一些测试用得代码,没有什么逻辑关联性

//
// ViewController.m
// AudioSessionDemo
//
// Created by PSH_Chen_Tao on 7/18/13.
// Copyright (c) 2013 wolfman. All rights reserved.
// #import "ViewController.h"
#import <MediaPlayer/MediaPlayer.h> @interface ViewController () @end @implementation ViewController @synthesize imagePickerController; - (void)viewDidLoad
{
[super viewDidLoad];
// 获得当前的音量,因为按物理音量键,声音会发生改变,我们可以在他每次按下音量键时都通过下面的初始音量值来还原它.
float initVolume = [MPMusicPlayerController applicationMusicPlayer].volume;
NSLog(@"%f ",initVolume);
// Do any additional setup after loading the view, typically from a nib. AudioSessionInitialize(NULL, kCFRunLoopDefaultMode, interruptionListenerCallback, "AudioSessionInitialize"); //通过捕捉物理音量键按下时产生的通知来对其进行监听
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(volumeChanged:)
name:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(enterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(enterForground:) name:UIApplicationDidBecomeActiveNotification object:nil]; //避免按下音量键时,其系统自带的音量设置画面会出现
MPVolumeView *volumeView = [[MPVolumeView alloc]initWithFrame:CGRectMake(-, -, , )];
[self.view addSubview:volumeView]; } //进入后台,释放AudioSession
-(void)enterBackground:(NSNotification *)n{
AudioSessionSetActive(false);
}
//进入前台,激活AudioSession
-(void)enterForground:(NSNotification *)n{
AudioSessionSetActive(true);
} - (void)volumeChanged:(NSNotification *)notification
{ float volume =
[[[notification userInfo]
objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"]
floatValue]; NSLog(@"current volume = %f", volume); } - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} void interruptionListenerCallback(
void *inClientData,
UInt32 inInterruptionState
){ if (inInterruptionState == kAudioSessionBeginInterruption) {
NSLog(@"begin interruption"); } if (inInterruptionState == kAudioSessionEndInterruption) {
NSLog(@"end interruption");
} NSLog(@"%s",inClientData); } -(BOOL)isMuted{
CFStringRef route;
UInt32 routeSize = sizeof(route);
OSStatus s = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &routeSize, &route);
if (s==kAudioSessionNoError) {
if (route==NULL || CFStringGetLength(route)==) {
return YES;
}
} return NO;
} -(BOOL)addMutedListener{
OSStatus s = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, mutedListener, "kAudioSessionProperty_AudioRouteChange"); return s==kAudioSessionNoError;
} void mutedListener(
void *inClientData,
AudioSessionPropertyID inID,
UInt32 inDataSize,
const void *inData
){ if (inID != kAudioSessionProperty_AudioRouteChange) {
NSLog(@"inID != kAudioSessionProperty_AudioRouteChange %s",inClientData);
return;
} NSLog(@"%s",inClientData);
} -(BOOL)addHardKeyListener{
OSStatus s = AudioSessionAddPropertyListener(kAudioSessionProperty_CurrentHardwareOutputVolume, hardKeyListener, "kAudioSessionProperty_CurrentHardwareOutputVolume");
return s==kAudioSessionNoError;
} void hardKeyListener(
void *inClientData,
AudioSessionPropertyID inID,
UInt32 inDataSize,
const void *inData
){ if (inID != kAudioSessionProperty_CurrentHardwareOutputVolume) {
return;
}
NSLog(@"%s",inClientData);
} - (IBAction)addListener:(id)sender { [self addMutedListener];
[self addHardKeyListener];
} - (IBAction)removeListener:(id)sender { AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_CurrentHardwareOutputVolume, hardKeyListener, "kAudioSessionProperty_CurrentHardwareOutputVolume");
} -(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionSetActive(true);
} -(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
AudioSessionSetActive(false);
}
@end

iOS 监听声音按键的更多相关文章

  1. JS监听组合按键

    有些时候,我们需要在网页上,增加一些快捷按键,方便用户使用一些常用的操作,比如:保存,撤销,复制.粘贴等等. 下面简单梳理一下思路: 我们所熟悉的按键有这么集中类型: 单独的按键操作,如:delete ...

  2. Dom监听组合按键

    JS监听组合按键   有些时候,我们需要在网页上,增加一些快捷按键,方便用户使用一些常用的操作,比如:保存,撤销,复制.粘贴等等. 下面简单梳理一下思路: 我们所熟悉的按键有这么集中类型: 单独的按键 ...

  3. 【转】keyCode对照表及JS监听组合按键

    原文: http://blog.csdn.net/qq_21386275/article/details/67640576 有一些需求,html 页面上的input 框只允许输入数字,  只允许输入小 ...

  4. 92. extjs specialkey监听回车按键

    转自:http://blog.sina.com.cn/s/blog_647a022e0101401n.html 1 监听表单字段事件: Ext使得对用户某个动作的监听特别简单,诸如单击某个元素或者按下 ...

  5. android监听虚拟按键的显示与隐藏【转】

    本文转载自:http://blog.csdn.net/u014583590/article/details/55263141 虚拟按键在华为手机中大量存在,而虚拟按键的存在无疑增加了屏幕适配的难度,往 ...

  6. Android通过Intent.ACTION_CLOSE_SYSTEM_DIALOGS监听Home按键消息

    Android对屏幕下方经常使用的四个按键消息处理是不一致的: 1.搜索按键的消息在onKeyDown或者onKeyUp中接收: 2.菜单按键的消息在onCreateOptionsMenu.onKey ...

  7. android 监听声音变化

    新的项目需要监听android声音的变化,再做出对应的操作,从网上找了个demo验证.记录于此. 参考链接 https://my.oschina.net/yuanxulong/blog/372268 ...

  8. iOS监听模式系列之通知中心

    补充--通知中心 对于很多初学者往往会把iOS中的本地通知.推送通知和iOS通知中心的概念弄混.其实二者之间并没有任何关系,事实上它们都不属于一个框架,前者属于UIKit框架,后者属于Foundati ...

  9. iOS监听模式系列之键值编码KVC、键值监听KVO的简单介绍和应用

    键值编码KVC 我们知道在C#中可以通过反射读写一个对象的属性,有时候这种方式特别方便,因为你可以利用字符串的方式去动态控制一个对象.其实由于ObjC的语言特性,你根部不必进行任何操作就可以进行属性的 ...

随机推荐

  1. 宽客的人&amp;&amp;事件映射

    看完<宽客>这本书,叙事介绍20世纪华尔街对冲基金.股票.投资者依赖股市从直觉交易数学家的早期演化.物理学家用数学模型开发过程中的交易,这些进入金融数学家.物理学家依靠大数据分析.稍纵即逝 ...

  2. youcompleteme install and configure

    三四年前我配置vim插件的时候还都是手动配置,还没有听说vundle这个vim插件管理工具,现在配置vim插件的时候基本上都用vundle,这个插件也确实是方便快捷,只不过这东西时能话了就不清楚里面的 ...

  3. jquery自己主动旋转的登录界面的背景代码登录页背景图

    在其他网站上看到比较爽Web登录界面.背景图片可以自己主动旋转. 介绍给大家.有兴趣的可以改改下来作为自己的系统登录界面. 如图: watermark/2/text/aHR0cDovL2Jsb2cuY ...

  4. ASP.Net TextBox控件只允许输入数字

    原文:ASP.Net TextBox控件只允许输入数字 1.1.在Asp.Net TextBox 控件的 OnKeyPress 事件中指定输入键盘码必须为数字: <asp:TextBox ID= ...

  5. PHP文件上传后缀名与文件类型对照表

    ie 火狐 id 后缀名 php识别出的文件类型 0 gif image/gif 1 jpg image/jpeg 2 png image/png 3 bmp image/bmp 4 psd appl ...

  6. SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比

    原文:SQL点滴10-使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比 今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章 ...

  7. Mysql 使用CMD 登陆

    1. 将mysql 的bin 目录加到 系统环境变量中: 这样的目的是为了可以直接在cmd中使用mysql命令,而不用先CD到mysql的bin目录中. 3. 连接目标数据库 . Syntax:   ...

  8. sql 将datetime类型转化为指定格式的字符串

    ), ) -- 输出: 05 16 2006 10:57AM ), ) -- 输出: 05/16/06 ), ) -- 输出: 06.05.16 ), ) -- 输出: 16/05/06 ), ) - ...

  9. python进程池剖析(二)

    之前文章中介绍了python中multiprocessing模块中自带的进程池Pool,并对进程池中的数据结构和各个线程之间的合作关系进行了简单分析,这节来看下客户端如何对向进程池分配任务,并获取结果 ...

  10. Andy Williams 《Love Story》

    where do i beginto tell a story of how great a love can bethe sweet love story that is older than th ...