iOS獲取設備靜音鍵的開關狀態 誤差優化 題記:檢測蘋果手機的物理靜音按鍵的開關狀態

題記:檢測蘋果手機的物理靜音按鍵的開關狀態

最近業務上有個需求就是以靜音鍵的狀態來做一些邏輯顯示,但是在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地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章