Android 监听耳机按键事件

sancaiodm Android应用 2022-05-16 1715 0

   最近在做一个手动测试功能的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版本中适用。

评论