Android 耳机按钮监听(2)

其实,AudioService.java文件中也存在这么一个MediaoButtonReceiver的广播类,它为系统广播接收器,即用来接收系统的MEDIA_BUTTON广播,当它接收到了这个MEDIA_BUTTON广播  ,它会对这个广播进行进一步处理,这个处理过程就是我们需要的弄清楚。

MediaButtonBroadcastReceiver 内部类如下:

private class MediaButtonBroadcastReceiver extends BroadcastReceiver { 

    @Override 

    public void onReceive(Context context, Intent intent) { 

        //获得action ,系统MEDIA_BUTTON广播来了 

        String action = intent.getAction(); 

        //action不正确 直接返回 

        if (!Intent.ACTION_MEDIA_BUTTON.equals(action)) { 

            return

        } 

      //获得KeyEvent对象 

        KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); 

        if (event != null) { 

            // if in a call or ringing, do not break the current phone app behavior 

            // TODO modify this to let the phone app specifically get the RC focus 

            //      add modify the phone app to take advantage of the new API 

            //来电或通话中,不做处理直接返回 

            if ((getMode() == AudioSystem.MODE_IN_CALL) ||(getMode() == AudioSystem.MODE_RINGTONE)) { 

                return

            } 

            synchronized(mRCStack) { 

                //栈不为空 

                if (!mRCStack.empty()) { 

                    // create a new intent specifically aimed at the current registered listener 

                    //构造一个Intent对象 ,并且赋予Action和KeyEvent 

                    Intent targetedIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 

                    targetedIntent.putExtras(intent.getExtras()); 

                    //指定该处理Intent的对象为栈顶ComponentName对象的广播类 

                        targetedIntent.setComponent(mRCStack.peek().mReceiverComponent); 

                    // trap the current broadcast 

                    // 终止系统广播 

                         abortBroadcast(); 

                    //Log.v(TAG, " Sending intent" + targetedIntent); 

                    //手动发送该广播至目标对象去处理,该广播不再是系统发送的了 

                        context.sendBroadcast(targetedIntent, null); 

                } 

                //假设栈为空,那么所有定义在AndroidManifest.xml的监听MEDIA_BUTTON的广播都会处理, 

                //在此过程中如果有任何应用程注册了registerMediaButton 该广播也会立即终止 

            } 

        } 

    } 

总结一下MEDIA_BUTTON广播:

AudioManager也就是AudioService服务端对象内部会利用一个栈来管理所有ComponentName对象,所有对象有且仅有一个,

新注册的ComponentName总是会位于栈顶。

当系统发送MEDIA_BUTTON,系统MediaButtonBroadcastReceiver 监听到系统广播,它会做如下处理:

1、 如果栈为空,则所有注册了该Action的广播都会接受到,因为它是由系统发送的。

2、 如果栈不为空,那么只有栈顶的那个广播能接受到MEDIA_BUTTON的广播,手动发送了MEDIA_BUTTON

广播,并且指定了目标对象(栈顶对象)去处理该MEDIA_BUTTON 。

下面分析一下KeyEvent对象里的KeyCode按键,可能的按键码有:

1、KeyEvent.KEYCODE_MEDIA_NEXT

2、KeyEvent.KEYCODE_HEADSETHOOK

3、KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE(已废除,等同于KEYCODE_HEADSETHOOK)

4、KeyEvent.KEYCODE_MEDIA_PREVIOUS

5、KeyEvent.KEYCODE_MEDIA_STOP

PS : 在我的真机测试中,按下MEDIA_BUTTON只有KEYCODE_HEADSETHOOK可以打印出来了。

下面给出一个小DEMO检验一下我们之前所做的一切,看看MEDIA_BUTTON是如何处理分发广播的。

编写两个MediaButtonReceiver类用来监听MEDIA_BUTTON广播:

1 、China_MBReceiver.java

package com.qin.mediabutton; 

 

import android.content.BroadcastReceiver; 

import android.content.Context; 

import android.content.Intent; 

import android.util.Log; 

import android.view.KeyEvent; 

 

public class China_MBReceiver extends BroadcastReceiver  { 

 

    private static String TAG = "China_MBReceiver" ; 

    @Override 

    public void onReceive(Context context, Intent intent) { 

        //获得Action  

        String intentAction = intent.getAction() ; 

        //获得KeyEvent对象 

        KeyEvent keyEvent = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); 

         

        Log.i(TAG, "Action ---->"+intentAction + "  KeyEvent----->"+keyEvent.toString()); 

         

        if(Intent.ACTION_MEDIA_BUTTON.equals(intentAction)){ 

            //获得按键字节码 

            int keyCode = keyEvent.getKeyCode() ; 

            //按下 / 松开 按钮 

            int keyAction = keyEvent.getAction() ; 

            //获得事件的时间 

            long downtime = keyEvent.getEventTime(); 

             

            //获取按键码 keyCode  

            StringBuilder sb = new StringBuilder(); 

            //这些都是可能的按键码 , 打印出来用户按下的键 

            if(KeyEvent.KEYCODE_MEDIA_NEXT == keyCode){ 

                sb.append("KEYCODE_MEDIA_NEXT"); 

            } 

            //说明:当我们按下MEDIA_BUTTON中间按钮时,实际出发的是 KEYCODE_HEADSETHOOK 而不是 KEYCODE_MEDIA_PLAY_PAUSE 

            if(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ==keyCode){ 

                sb.append("KEYCODE_MEDIA_PLAY_PAUSE"); 

            } 

            if(KeyEvent.KEYCODE_HEADSETHOOK == keyCode){ 

                sb.append("KEYCODE_HEADSETHOOK"); 

            } 

            if(KeyEvent.KEYCODE_MEDIA_PREVIOUS ==keyCode){ 

                sb.append("KEYCODE_MEDIA_PREVIOUS"); 

            } 

            if(KeyEvent.KEYCODE_MEDIA_STOP ==keyCode){ 

                sb.append("KEYCODE_MEDIA_STOP"); 

            } 

            //输出点击的按键码 

            Log.i(TAG, sb.toString()); 

             

        } 

         

    } 

 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/66f131a7e345c303ef8e58cda56f2abd.html