Android 监听耳机按键事件
最近在做一个手动测试功能的MMI应用,应用主要是给到生产工厂来测试手机硬件是否组装完好,其中一项测试就是检测耳机组件是否OK,需要人工手动测试有线耳机上各个按键是否可以正常使用(按有线耳机上各按键有正常的反应),这就需要应用可以监听到有线耳机的按键事件,首先想到的是在onKeyDown中监听对应的keycode即可,
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
android.util.Log.i("androidos.net","keycode ="+keyCode);
Toast.makeText(this,""+keyCode,Toast.LENGTH_SHORT).show();
if (keyCode == KeyEvent.KEYCODE_BACK ){
//do somethings
}else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
//do somethings
}else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
//do somethings
}
return super.onKeyDown(keyCode, event);
}
但测试中发现当按手机上的音量+与音量-键与按有线耳机上的音量+与音量-检测到的keycode是一样的,直接这样keycode监听无法区分到底是手机还是耳机上的音量键事件,百度一圈,看了不下二十篇CSDN,51cto的文章都说Android5以后的有线耳机按键监听必须用到MediaSessionCompat 来实现 MediaButton 的监听,且必须要在service中的实现中监听,还得是静态注册android.intent.action.MEDIA_BUTTON广播..... ,
public class MediaButtonReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
return;
}
KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null || event.getAction() != KeyEvent.ACTION_UP) {
return;
}
// do something
}
}
public class PlayerService extends Service {
private MediaSessionCompat mMediaSession;
@Override
public void onCreate() {
super.onCreate();
ComponentName mbr = new ComponentName(getPackageName(), MediaButtonReceiver.class.getName());
mMediaSession = new MediaSessionCompat(this, "mbr", mbr, null);
/* set flags to handle media buttons */
mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
/* this is need after Lolipop */
mMediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public boolean onMediaButtonEvent(Intent intent) {
if (!Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
return super.onMediaButtonEvent(intent);
}
KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null || event.getAction() != KeyEvent.ACTION_UP) {
return super.onMediaButtonEvent(intent);
}
// do something
return true;
}
});
/* to make sure the media session is active */
if (!mMediaSession.isActive()) {
mMediaSession.setActive(true);
}
}
@Override
public void onDestroy() {
mMediaSession.release();
}
}
原本出处: 使用 MediaSessionCompat 来实现 Media Button 的监听,
跟着上文的方式敲了一遍,遗憾未能实现功能,由有同学按此方法能做到监听耳机的按键,请留言告知一下,谢谢!
同时也在Android源码中搜索了MediaSessionCompat的使用,搜索了android.intent.action.MEDIA_BUTTON广播的使用,因为按网上的说法监听有线耳机按键事件处理必须要用到这两者,那么只要在源码中找到了这两者的使用照着其实现即可,往往想法是美好的,但实现是残酷的,源码中的没有一个现成或是差不多可用的参考用例,且因系统API的隐藏等问题,在APP中无法使用.. 这问题折腾了一天,
在看KeyEvent.java类的源码时发现,这类有许多的get方法,索性就把该类的所有get方法都打印了,看看这些方法返回的都是些什么值,是否有通过值的差异来判断有线耳机的按键,
果不其然,通过测试发现KeyEvent的getDeviceId方法对手机音量键与有线耳机的音量键,及虚拟键,power键的返回值是各不相同的,不同的硬件是不同的device ID值,那么该值的差异就好判断了,首先我们可以测试下知道自己手里的手机按耳机按键时返回的getDeviceId的值是多少,同时判断必须是耳机的deviceID值与Keycode值即可,具体代码如下:
private final int HEADSET_DEIVCE_ID = X;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
android.util.Log.i("androidos.net","keycode ="+keyCode);
Toast.makeText(this,""+event.getDeviceId()+" | "+keyCode,Toast.LENGTH_SHORT).show();
if ( keyCode == KeyEvent.KEYCODE_BACK ){
//do somethings
}else if(HEADSET_DEIVCE_ID == event.getDeviceId() && keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
//do somethings
}else if(HEADSET_DEIVCE_ID == event.getDeviceId() && keyCode == KeyEvent.KEYCODE_VOLUME_UP){
//do somethings
}
return super.onKeyDown(keyCode, event);
}
这方法应该是全网最简单有效的监听有线耳机各按键事件的方法,且该方法在各Android版本中适用。
评论