美文网首页前端开发那些事儿
iOS获取设备静音键的开关状态 误差优化

iOS获取设备静音键的开关状态 误差优化

作者: 东方诗空 | 来源:发表于2020-12-10 18:06 被阅读0次

    题记:检测苹果手机的物理静音按键的开关状态

    最近业务上有个需求就是以静音键的状态来做一些逻辑显示,但是在iOS5以后,苹果就没有开放现成的api来获取静音键的状态。只要遇到这样的情况,基本都是“曲线救国”。

    目前网上基本获取静音键的状态大体有三种方式:

    第一种:使用对应的api获取

    CFStringRef state = nil;
    UInt32 propertySize = sizeof(CFStringRef);
    AudioSessionInitialize(NULL, NULL, NULL, NULL);
    OSStatus status = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
        
    if (status == kAudioSessionNoError){
         return (CFStringGetLength(state) == 0);   // YES = silent
    }
        return NO;
    

    试了试,但是获取状态不正确。

    第二种方式:

    通过播放一段短的白噪音,根据回调时间差来计数,然后根据计数的大小来判断是否静音。参考文献.
    但是这种方式的获取也存在一些误差,在某些情况下,由于runloop的时机,以及计数的误差,加上判断阀值的设定,总会有些误差导致有那么几次静音键的状态获取不对。

    第三种方式:

    国外大佬的解决方案,SoundSwitch.zip.但是此地址打开失败。

    综合以上情况,最后选择了第二种方式来获取静音键的开关状态。所以一直在查找那些为什么状态获取失败的原因。

    在我调试的时候,发现在静音键关闭的时候,获取状态为开的时候,获取音量的值始终为0.

    [[AVAudioSession sharedInstance] outputVolume]
    

    至此,可以知道有两个地方的影响,导致获取静音键按钮的开光状态的误差原因。
    1、在某些情况下,由于runloop的时机,以及计数的误差,加上判断阀值的设定,导致判断出错。
    2、当前获取音量的值为0影响了获取结果。

    优化方案:

    1、摒弃runloop技术策略,改用播放时间戳的判断。因为上面demo的思想就是播放一个短音效。所以根据前后播放时间差的判断,规避由于计数器的判断误差。

    2、针对获取音量的值为0情况,一般都是AVFoundation获取音量的时候,播放器没有激活。或者播放器声道资源被占用。所以在每一次播放白噪音时,提前设置AVAudioSession,并且播放一次音频,确保在获取前声道没有被第三方或者APP里面的其他播放业务打断。

    猜测,静音键按钮的状态 是根据声卡、获取音量的值有联系。如果获取音量的值为0(不管是获取正确的音量值是0,还是因为获取错误的音量值为0),那么默认就是静音的状态。

        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];//保证不会打断第三方app的音频播放 导致获取不准确
        NSString *itemVideoPath = [[NSBundle mainBundle] pathForResource:@"detection" ofType:@"aiff"];
        AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:itemVideoPath]];
        [player play];
    

    最终解决方案代码:你犀利的小手可以点个星星
    demo地址

    相关文章

      网友评论

        本文标题:iOS获取设备静音键的开关状态 误差优化

        本文链接:https://www.haomeiwen.com/subject/wwdrgktx.html