iOS 監聽聲音按鍵

  有時在項目中須要監聽用戶是否按下了物理聲音鍵,而後來作某些操做,如:你自定義了一個照相功能,但願用戶按下聲音按鍵時也能進行拍照,蘋果自帶的照相機就有這種功能.app

 監聽物理聲音鍵是否按下的方法有不少中,我在這裏只講兩種,也是我比較熟悉的ide

1、經過 NSNotificationCenter 觀察一個叫作   @「AVSystemController_SystemVolumeDidChangeNotification」   的通知,oop

[[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);
    
}

2、經過爲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);
}

對於上面這種方式,若是你直接這樣,那當你按下物理音量鍵時不會有任何的反應,你必須在調用它以前,手動初始化audioSessionspa

你能夠code

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

或者直接blog

AudioSessionInitialize(NULL, NULL, NULL, NULL);rem

 

當你完成了上面的任何一種方式後,你就能夠很好的捕捉到音量鍵是否按下了,但此時你會發現,當你按下音量鍵時,系統自帶的,反映音量設置的view會it

出現,試想下,當你的用戶經過物理音量鍵操做你的程序,好比拍照,你還給人家顯示個系統的音量設置鍵,那用戶體驗可想而知了,

那怎麼解決呢?

那個系統自帶的音量設置view 其實就是個蘋果自定義的MPVolumeView,沒當音量鍵按下時,它都會出現,但若是當前顯示的正好有一個這樣的東西,那這個系統的音量設置view 就不會反客爲主,本身顯示出來了,而是顯示你本身定義的

呵呵,我就是不須要這個,那好辦,自定義一個,而後加到看不到的地方不就得了,

以下:

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

但此時,你必須激活audioSession,否則得話它仍是會本身顯示得

加上代碼:

AudioSessionSetActive(true);

 

3、完成上面得東西后,你基本上能夠正常捕捉到音量鍵得按下,但有一點要注意: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(-100, -100, 100, 100)];
    [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)==0) {
            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
View Code
相關文章
相關標籤/搜索