標籤:前台 推斷 pre 實現原理 tps water font res 需求
Android怎樣監聽藍芽耳機的按鍵事件
寫在前面:
直接想要代碼非常easy,你直接把滾動欄拉到最底端就能夠看到。假設想要十分地瞭解為什麼,那就依照我規劃的一步一步來理解。下面測試環境以手頭上有的「Bluedio + 紅米手機」。
1.藍芽耳機的使用
藍芽耳機的使用說明書中都會有相關的具體使用說明,這裡揀重點說明一下。除了電源開關,耳機上一般有三個鍵。例如以下所看到的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2FuZ2Vhcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
它們每一個都是多功能鍵。在不同的情況下有不同的功能。1號鍵的功能包含:開始播放音樂/停止插入音樂/電話中/掛斷電話;2號鍵的功能有:添加音量/上一曲;3號鍵的功能有 減小音量/下一曲。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2FuZ2Vhcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
註:暫不包含通話模式;其他型號藍芽耳機並不一定全然同樣。
2.藍芽耳機上的按鍵實現原理
試用後會明確,一個按鍵會有多個功能。那麼在Android系統中是怎樣表示的呢?事實上對於Android系統,每次按鍵僅僅會有一個唯一「鍵值」響應。使用起來感覺會模模糊糊的,可是事實上對於系統來說是非常清晰的。
AVRCP全稱(Audio/Video Remote Control Profile)。是藍芽協議中的一個profile。從名字上就能夠看出主要應用於Audio/Video控制。每一個按鍵並非獨立的。上-曲/下一曲是在現正播放音樂的時候才會有效,即才會向Android發送「鍵值」。
基於按鍵從Linux到Android分析詳細對於的鍵值:
Linux掃描碼 功能 映射字串 Android鍵值
00c8 200 開始放音樂 MEDIA_PLAY KEYCODE_MEDIA_PLAY
00c9 201 停止放音樂 MEDIA_PAUSE KEYCODE_MEDIA_PAUSE
00a3 163 下一曲 MEDIA_NEXT KEYCODE_MEDIA_NEXT
00a5 165 上-曲 MEDIA_PREVIOUS KEYCODE_MEDIA_PREVIOUS
Android應用代碼,完整測試應用:TeskKey。
總結:1號鍵會交替發送KEYCODE_MEDIA_PLAY/KEYCODE_MEDIA_PAUSE;2/3號鍵會在播放音樂時分別發送KEYCODE_MEDIA_PREVIOUS/.KEYCODE_MEDIA_NEXT。假設想要把藍芽耳機上的按鍵利用起來。能夠在接收到KEYCODE_MEDIA_PLAY時播放 無聲音樂 以使能2/3號鍵。這樣就能完整接收3種鍵值了自行控制了。這個詳細自行設計(測試代碼已經更新包括了)。
註:這樣的實現並不一定通用,比方我在深度定製的MIUI中測試,雖然啟動的TestKey應用,系統內建的音樂播放器仍然能同一時候響應鍵值。
更新:
已經更新TestKey原始碼,加入對藍芽耳機按鍵的監聽。實現方法就是上述中猜測的方法,已經成功驗證過了。播放音樂參考《Android多媒體開發--資源檔播放》。:
須要說明一點的是,程式帶了兩個音樂檔案在/res/raw中,預設播放的是lapple.mp3一個有聲音的mp3音樂檔案,silence10sec.mp3是一個無聲音的10秒鐘音樂檔案,實際應用中能夠使用它。
問答
1.這個僅僅能在播放音樂的狀態下才幹監聽到嗎?
答:依據上述的原理,這些按鍵也不過應用在控制媒體時使用。且依據實際驗證沒有播放音樂時藍芽耳機的2/3號鍵是並沒有向Android裝置發送鍵值(從底層Linux來看)。綜上所述,須要通過播放音樂來實現啟用其向Android裝置發送鍵值,針對這樣的情況能夠播放一個「沒有聲音」的音樂檔案來實現,這樣既能夠監聽到2/3號鍵又能夠不影響其他聲音的輸出。能夠在前台時播放音樂,後台停止播放。
2.我如今主要是想監聽得到開關鍵(1號鍵)。 在做一個按下藍芽開關鍵後啟動一個語音辨識的功能?
答:在我的測試條件下,1號鍵是能夠正常監聽到的。1號鍵會交替發送KEYCODE_MEDIA_PLAY/KEYCODE_MEDIA_PAUSE鍵值。
這個鍵不須要類比播放音樂就能夠正常的監聽到。
3. 4號按鍵的監聽方法
答:所謂的4號按鍵,也就是指本文中的所測試型號的藍芽耳機上並沒有,但有可能其他型號的藍芽耳機上有。我沒有辦法測實驗證。所以這裡就簡單敘述一下「新按鍵」的鍵值確定思路:1.先使用TestKey測試應用測試按鍵,測試Android上層能否夠得到相應鍵值。
2.假設沒有得到,那麼就使用adb shell getevent來看Linux底層能夠不能夠得到鍵值。然後依據按鍵從Linux到Android來確定Android上層使用的鍵值碼究竟是多少。(當然。假設你實在不知道怎樣監聽,把藍芽耳機寄給我。我給你確定也行。
:))
註:事實上上述文章全然是依據按鍵從Linux到Android測試確定下來的。那是篇文章是剝開Android外殼來看「按鍵」事件的流程的。方法適用於全部輸入事件:各種按鍵/觸摸/物理鍵盤/滑鼠等待輸入裝置。沒有一定的Linux開發經驗非常難看懂和理解。
4. Android後台監聽按鍵怎麼實現
或:怎樣啟動一次應用後在後台一直監聽播放鍵 由於有這樣一個情境 在使用者開車的時候需按一下開關鍵就啟動語音辨識的功能。
這個問題事實上已經超出了本文討論的範圍,是Android系統相應用程式層的鍵盤事件(按鍵)的分發的問題了。正常情況下。按鍵僅僅會向當前最端的應用分發鍵盤事件。也就是說在後台你邊音量鍵都監聽不了。
可是既然這樣的情況(後台應用監聽按鍵)的需求存在,那麼就一定有它存在的道理。
比方「相機鍵」,按下後直接調出相機到最前台。從表面上看是相機響應了按鍵,可是從實現方法上來看,並非通過鍵值來操作。必須通過其他方法,比方廣播或者其他等等。
明確了當中的道理後。那麼想要實現就好辦了。先看這個按鍵有沒有廣播,如要有接聽系統中發出來的廣播;假設沒有那麼對於定製系統能夠自己在系統中加入一個廣播。總之,正常渠道是沒有辦法在後台監聽一些不應該是你監聽到的按鍵的。
更:查了一下。這個按鍵是有廣播的。這樣就能夠後台響應了(不須要C/不須要root)。範例我就不試了,見Android官方範例RandomMusicPlayer。
當中的重點是這個廣播android.intent.action.MEDIA_BUTTON。
20141029更:
本來不想再更新那個Testkey了,好吧,我還是更新了一下。關於後台監聽媒體相關按鍵的方法。沒有在介面上更新。通過LogCat查看資訊列印。
上述內容算「魚」,下邊把「漁」也提供了:
第一步先直接編譯執行RandomMusicPlayer,然後發現確實不能收到廣播。然後推斷是系統版本號碼問題,有可能是RandomMusicPlayer並沒有更新為適合4.0以上的。
在Capture media button on Android >=4.0 (works on 2.3)這裡找到了問題所在。加入之成功。然後整合到Testkey上。詳細改了哪些內容通過Github上的commit id查看。
20150108更:
關於測試程式的原始碼,是託管在Github上的。文中找到"TestKey"連結,開啟後例如以下載:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2FuZ2Vhcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
APK下載
更新原始碼,加入編譯好的APK檔案。
直接:https://github.com/kangear/TestKey/raw/master/apk/TestKey.apk
20150109更:
已經root的Android裝置擷取鍵值方法
假設裝置已經root過了,那麼能夠更底層地擷取鍵值。
1.下載終端模擬器http://shouji.baidu.com/soft/item?
docid=7309820
2.執行su -c getevent 然後按下須要測試的按鍵 注:su -c getevent中間有空格.
3.會有例如以下輸出,當中每次按下後輸出資料的倒數第二行 倒數第二個是該按鍵的原始鍵值
4.將此鍵值告知我,我來推斷怎樣實現對應功能
注:
1.該命令會監聽全部輸入事件 觸控螢幕/按鍵/藍芽耳機/滑鼠鍵盤 都會檢測到,所以輸出命令後不要再點擊觸控螢幕 不然會有大量輸出.
2.普通情況下每次按鍵會輸出4行資訊.
3.最後輸出4行是按下 Vol- 的輸出.假設你的測試沒有達到這個效果,要自行去對照哪裡出現了問題.
4.下面監聽藍芽按鍵的執行個體
20150112更:
哪些鍵值會是藍芽傳遞過來的
1. 串連藍芽後,假設直接按下藍芽耳機上的某個鍵,你的手機會自己主動播放音樂,那麼說明是該鍵值是從藍芽耳機傳遞過來的.
2. 播放音樂後,假設能夠只通過藍芽耳機上的某個鍵,你的手機會切換音樂,那麼說明是該鍵值是從藍芽耳機傳遞過來的.
3. 播放音樂時,假設能夠只通過藍芽耳機上的某個鍵,你的手機螢幕上顯示增大或者減小音量,那麼說明該鍵值是從藍芽耳機傳遞過來的.反之假設不過藍芽耳機內部音量進行了改變,Android沒有不論什麼的反應,那麼說明該按鍵唯獨控制藍芽耳機音量的功能,並沒有向Android上報鍵值.
4. 串連藍芽通話,假設通過按下某個鍵,能夠掛斷電話,那麼說明該按鍵是從藍芽耳機傳遞過來的.
案例:
a.某個4.0版本號碼協議的藍芽耳機更注重省電,在控制音量時僅僅是自身喇叭音量增大或者減小,並非向Android系統報告須要增大或者減小音量的,那麼說明這個按鍵根本從來就沒有向Android報告過鍵值.(無按鍵上傳)
b.某些型號的藍芽耳機,本身不控制音量,當按下按下音量鍵時,會將鍵值傳遞給Android裝置,要求Android進行增大或者減小音頻源的音量 來實現音量的控制.(有按鍵上傳)
以上兩種情況,儘管使用者體驗是並無太大區別,可是實現原理極為不同的.
補充知識:
播放音量/語音通話是藍芽耳機中兩個不同的規範,普通情況下都會同一時候支援,可是有時候會只支援後者(也稱 單聲道藍芽耳機),為的是更省電.當然也會進一步壓縮一些功能.
20150113更 單通道耳機不能使用上述方法檢測按鍵分析
藍芽標準規範列表:https://en.wikipedia.org/wiki/List_of_Bluetooth_profiles
這裡說明幾個經常使用的規範:(規範也能夠理解為通道)
1._正常_播放音樂
2._正常_播放音樂時按鍵
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2FuZ2Vhcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
3.語音通話/以及語音通話時按鍵
註:對於單聲道耳機(預設僅僅能電話中)通過某些軟體實現的播放音樂的原理是將「音樂的訊號」通過「語音通話通道」傳輸給耳機的。耳機實質還是工作在「語音通話」模式下。
說一千道一萬,對於第三種情況下的非按鍵的按鍵怎樣檢測,且聽下回分解。
;)
這裡簡單猜測一下原理。第3種情況下"按鍵"是被包含在通話語音訊號中的,應該是直接被Phone應用解析並進行了對應操作。Android4.2以上的版本號碼中會有一個內建的無介面的應用程式名稱字叫Bluetooth.apk,它是Android系統對中藍牙裝置支援的核心,全部的規範(profile)都是通過它來解析的。所以要研究一下它和Phone應用之間做了什麼見不得人的勾當才幹知道怎樣。 ;)
當然簡單一點,也能夠通過監聽音量變化也實現曲線監聽等等,只是這個不是我研究的重點。
另外一點是 對於單聲道耳機按鍵研究 眼下也僅僅能是挖的一個坑。什麼時候埋臨時不好說。
先寫到這裡 (語音通話時“按鍵”處理過程)
文字描寫敘述:已經找到處理過程。和猜測的一致。Bluetooth解析出特定的“按鍵”後直接進行處理。沒有向外界通知什麼。依據高亮的英文也能猜測出含意。第一張圖是語音通話時的各種“按鍵”事件。第二張圖是對“撥號/重撥”鍵的處理。高亮出是重撥時擷取通話記錄中最後一個號碼。
假設能夠訪問Google那麼你也能夠直接線上查看我的這兩段程式碼片段。HeadsetStateMachine.java(另:我是基於4.2.2分析的),這是簡單的分析過程,對於怎樣在APP中監聽,下回再說。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2FuZ2Vhcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
語音通話相關參考文檔:
1.GSM 07.07_V5.0.pdf
2. Bluetooth.apk原始碼 hfp
Android怎樣監聽藍芽耳機的按鍵事件