Android如何监听蓝牙耳机的按键事件

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

相关文章
相关标签/搜索