ndroid如何監聽藍牙耳機的按鍵事件java
寫在前面:android
直接想要代碼很簡單,你直接把滾動條拉到最底端就能夠看到。若是想要十分地瞭解爲何,那就按照我規劃的一步一步來理解。如下測試環境以手頭上有的「Bluedio + 紅米手機」。git
1.藍牙耳機的使用github
藍牙耳機的使用說明書中都會有相關的詳細使用說明,這裏揀重點說明一下。除了電源開關,耳機上通常有三個鍵。以下所示:shell
它們每一個都是多功能鍵,在不一樣的狀況下有不一樣的功能。1號鍵的功能包括:開始播放音樂/中止插入音樂/接聽電話/掛斷電話;2號鍵的功能有:增長音量/上一曲;3號鍵的功能有 減少音量/下一曲。app
注:暫不包括通話模式;其它型號藍牙耳機並不必定徹底相同。dom
2.藍牙耳機上的按鍵實現原理ide
試用後會明白,一個按鍵會有多個功能,那麼在Android系統中是如何表示的呢?其實對於Android系統,每次按鍵只會有一個惟一「鍵值」響應,使用起來感受會模模糊糊的,可是其實對於系統來講是很清晰的。測試
AVRCP全稱(Audio/Video Remote Control Profile),是藍牙協議中的一個profile。從名字上就能夠看出主要應用於Audio/Video控制。每一個按鍵並非獨立的,上-曲/下一曲是在正在播放音樂的時候纔會有效,即纔會向Android發送「鍵值」。google
基於按鍵從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"連接,打開後以下圖下載:
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._正常_播放音樂時按鍵
3.語音通話/以及語音通話時按鍵
注:對於單聲道耳機(默認只能接聽電話)經過某些軟件實現的播放音樂的原理是將「音樂的信號」經過「語音通話通道」傳輸給耳機的。耳機實質仍是工做在「語音通話」模式下。
說一千道一萬,對於第三種狀況下的非按鍵的按鍵如何檢測,且聽下回分解。;)
這裏簡單推測一下原理,第3種狀況下"按鍵"是被包括在通話語音信號中的,應該是直接被Phone應用解析並進行了相應操做。Android4.2以上的版本中會有一個內置的無界面的應用程序名字叫Bluetooth.apk,它是Android系統對中藍牙設備支持的核心,全部的規範(profile)都是經過它來解析的。因此要研究一下它和Phone應用之間作了什麼見不得人的勾當才能知道如何。 ;)
固然簡單一點,也能夠經過監聽音量變化也實現曲線監聽等等,不過這個不是我研究的重點。
另一點是 對於單聲道耳機按鍵研究 目前也只能是挖的一個坑。何時埋暫時很差說。
先寫到這裏 (語音通話時「按鍵」處理過程)
文字描述:已經找處處理過程,和推測的一致。Bluetooth解析出特定的「按鍵」後直接進行處理,沒有向外界通知什麼。根據高亮的英文也能猜想出含意。第一張圖是語音通話時的各類「按鍵」事件,第二張圖是對「撥號/重撥」鍵的處理。高亮出是重撥時獲取通話記錄中最後一個號碼。若是能夠訪問Google那麼你也能夠直接在線查看我截圖的這兩段代碼片斷。HeadsetStateMachine.java(另:我是基於4.2.2分析的),這是簡單的分析過程,對於如何在APP中監聽,下回再說。
語音通話相關參考文檔:
1.GSM 07.07_V5.0.pdf
2. Bluetooth.apk源碼 hfp