Android怎样监听蓝牙耳机的按键事件

Android怎样监听蓝牙耳机的按键事件

写在前面:

        直接想要代码非常easy,你直接把滚动栏拉到最底端就能够看到。假设想要十分地了解为什么,那就依照我规划的一步一步来理解。下面測试环境以手头上有的「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

原文地址:https://www.cnblogs.com/brucemengbm/p/7162351.html