1. 程式人生 > >Android如何監聽藍芽耳機的按鍵事件

Android如何監聽藍芽耳機的按鍵事件

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

Android如何監聽藍芽耳機的按鍵事件

寫在前面:

        直接想要程式碼很簡單,你直接把滾動條拉到最底端就可以看到。如果想要十分地瞭解為什麼,那就按照我規劃的一步一步來理解。以下測試環境以手頭上有的「Bluedio + 

紅米手機」

 

1.藍芽耳機的使用

        藍芽耳機的使用說明書中都會有相關的詳細使用說明,這裡揀重點說明一下。除了電源開關,耳機上一般有三個鍵。如下所示:

 

        它們每個都是多功能鍵,在不同的情況下有不同的功能。1號鍵的功能包括:開始播放音樂/停止插入音樂/接聽電話/結束通話電話;2號鍵的功能有:增加音量/上一曲;3號鍵的功能有 減小音量/下一曲。

注:暫不包括通話模式;其它型號藍芽耳機並不一定完全相同。

 

2.藍芽耳機上的按鍵實現原理

        試用後會明白,一個按鍵會有多個功能,那麼在Android系統中是如何表示的呢?其實對於Android系統,每次按鍵只會有一個唯一「鍵值」響應,使用起來感覺會模模糊糊的,但是其實對於系統來說是很清晰的。

        AVRCP全稱(Audio/Video Remote Control Profile),是藍芽協議中的一個profile

。從名字上就可以看出主要應用於Audio/Video控制。每個按鍵並不是獨立的,上-曲/下一曲是在正在播放音樂的時候才會有效,即才會向Android傳送「鍵值」。

        基於按鍵從LinuxAndroid分析具體對於的鍵值:

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_PAUSE2/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底層可以不可以得到鍵值。然後根據按鍵從LinuxAndroid來確定Android上層使用的鍵值碼到底是多少。(當然,如果你實在不知道如何監聽,把藍芽耳機寄給我,我給你確定也行。:))

注:其實上述文章完全是根據按鍵從LinuxAndroid測試確定下來的。那是篇文章是剝開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

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述