• iOS 监听声音按键


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

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

    一、通过 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(-100, -100, 100, 100)];
        [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(-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
  • 相关阅读:
    运用vue-awesome-swiper实现一个slide居中一个缩小显示
    IntersectionObserver
    leetcode 加一
    Cuda总结
    webrtc 视频数据 采集 发送 接收 显示
    webrtc ice代码流程走读
    webrtc sdp 组建 流程以及 sdp协议解析
    webrtc 视频参数配置
    webrtc 线程整理
    webrtc turn协议
  • 原文地址:https://www.cnblogs.com/ctaodream/p/3291680.html
Copyright © 2020-2023  润新知