MediaButtonReceiver,  其实Android中并没有这个类的定义,它是由于自身的注册方式与实现功能被大家所俗称。前阵子要实现一个蓝牙耳机按键播放音乐的功能,有幸了解了一下。

MediaButtonReceiver ,顾名思义,就是用于接收多媒体按钮广播的,常用于耳机等多媒体设备的按键监听。

由于耳机设备上的按键点击都会发送广播,所以在一开始去实现耳机按键事件监听的时候,我用的是普通的BroadcastReceiver。

经过测试发现,在这种情况下点击音乐按键,手机会第一时间调用系统默认的音乐播放器。然后再次点击 就会在系统默认播放器执行相应操作(播放/暂停,上一首,下一首),

开始,我认为是我的广播优先级不够,然后在系统播放器接到广播后就关闭的其向下的传递,于是在注册的广播属性上添加android:priority="2147483647"(2147483647是int型最大值),然后再次测试。  

结果在第一次点击耳机按键的时候,我自己的广播接收到这个按键的广播,与此同时,系统默认的音乐播放器也被调用,但是之后继续点击耳机按键,发现我自身的广播已经无法在接收广播了,系统默认播放器依然继续响应,推测系统默认器应该是在接收了按键广播之后,截断了其后续的传递。 于是我也尝试在自己第一次收到广播的同时,截断按键广播向下传递。 事实是- -  并没有什么luan用。  (原因不是很清楚,有知道的朋友麻烦在下方解惑,也可以QQ联系我。)

在这样的情况下,使用MediaButtonReceiver是很不错的选择。其实MediaButtonReceiver跟普通的广播最主要的差异之处,就是它需要通过AudioManager来注册。

下面是AudioManager类中注册MediaButtonReceiver的代码。

 /**     * Register a component to be the sole receiver of MEDIA_BUTTON intents.     * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}     *      that will receive the media button intent. This broadcast receiver must be declared     *      in the application manifest. The package of the component must match that of     *      the context you're registering from.     * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead.     */    @Deprecated    public void registerMediaButtonEventReceiver(ComponentName eventReceiver) {        if (eventReceiver == null) {            return;        }        if (!eventReceiver.getPackageName().equals(mContext.getPackageName())) {            Log.e(TAG, "registerMediaButtonEventReceiver() error: " +                    "receiver and context package names don't match");            return;        }        // construct a PendingIntent for the media button and register it        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);        //     the associated intent will be handled by the component being registered        mediaButtonIntent.setComponent(eventReceiver);        PendingIntent pi = PendingIntent.getBroadcast(mContext,                0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);        registerMediaButtonIntent(pi, eventReceiver);    }

方法前的注释上有以下几点

1.注册一个唯一的针对MEDUA_BUTTON intents的广播接收器。

2.该接收器必须在manifest文件中注册。

3.该组件的包必须与你注册时的上下文匹配

4.推荐使用MediaSession的setMediaButtonReceiver(PendingIntent)来代替(好吧,这点不重要)

其实主要就是1 、2点需要注意,唯一的广播接收器,就是说在这个应用里只有这个广播接收器能接收MEDUA_BUTTON 的广播。

使用它的话,之前遇到的问题就迎刃而解了,

首先,注册:

代码里注册:

import android.app.Activity;import android.content.ComponentName;import android.media.AudioManager;import android.os.Bundle;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ((AudioManager)getSystemService(AUDIO_SERVICE)).registerMediaButtonEventReceiver(new ComponentName(this,MusicIntentReceiver.class));    }}
manifest里面注册:
                                                     
广播接收类MusicIntentReceiver.class:
import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.util.Log;import android.view.KeyEvent;import android.widget.Toast;public class MusicIntentReceiver extends BroadcastReceiver {private static final String LOG_TAG = "MusicIntentReceiver";private Context mContext;@Overridepublic void onReceive(Context context, Intent intent) {mContext = context; if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) {Log.i(LOG_TAG, "ACTION_MEDIA_BUTTON!");KeyEvent keyEvent = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);switch (keyEvent.getKeyCode()) {case KeyEvent.KEYCODE_HEADSETHOOK:    Toast.makeText(context, "hook",Toast.LENGTH_SHORT).show();    break;    case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:    Toast.makeText(context, "PLAY_PAUSE",Toast.LENGTH_SHORT).show();break;case KeyEvent.KEYCODE_MEDIA_PLAY:    Toast.makeText(context, "PLAY",Toast.LENGTH_SHORT).show();    Log.d(LOG_TAG, "KEYCODE_MEDIA_PLAY!");break;case KeyEvent.KEYCODE_MEDIA_PAUSE:    Toast.makeText(context, "PAUSE", Toast.LENGTH_SHORT).show();    Log.d(LOG_TAG, "KEYCODE_MEDIA_PAUSE!");break;case KeyEvent.KEYCODE_MEDIA_STOP:    Toast.makeText(context, "STOP",Toast.LENGTH_SHORT).show();break;case KeyEvent.KEYCODE_MEDIA_NEXT:    Toast.makeText(context, "NEXT",Toast.LENGTH_SHORT).show();break;case KeyEvent.KEYCODE_MEDIA_PREVIOUS:     Toast.makeText(context, "PREVIOUS",Toast.LENGTH_SHORT).show();break;}} }}
ok,这样就实现了耳机按键事件的监听。

做到这里,可以看到,其实跟正常的广播接收器相比,MediaButtonEventReceiver的接收都是一样,只是在注册的时候,是通过AudioManger来注册的。

为什么通过AudioManager的registerMediaButtonEventReceiver方法注册,就能使之成为MEDIA_BUTTON的唯一接收器呢?

关于这个问题,博主自己看了下源码,也看了下网上一些牛人写的解析。  发现已经有人写的相当详细了。

这里贴一下地址:跟随源码,步步解析,MediaButtonReceiver如何成为MEDIA_BUTTON的唯一接收器

更多相关文章

  1. 实现Android监控任意控件或按键双击事件方法
  2. 在QQ通讯录之前拦截短信
  3. android2.2应用开发之IccCard(sim卡或USIM卡)(转至 http://www.2cto
  4. Android自学笔记-17-广播接收者(BroadcastReceiver)
  5. Android(安卓)LocalBroadcastReceiver本地广播
  6. Android(安卓)按键映射 驱动
  7. Android(安卓)4.0以上设备虚拟按键中显示Menu键
  8. Android键盘系统——改变按键功能(2)
  9. Android之SqliteDatabase(MVP模式)实现用户登录注册功能

随机推荐

  1. 微信系列研究之-----资源文件保护的小把
  2. Android自定义主题样式详解(结合自定义tit
  3. 八大Android土鳖设计
  4. 【从零单排】利用科大讯飞语音包实现Andr
  5. android高分段进阶攻略(1)传感器
  6. Unity 3D 读取android 本地相册打开相机
  7. 【Bugly干货分享】手把手教你逆向分析 An
  8. Android(安卓)API Guides---Drag and Dro
  9. 多图详解 “Android(安卓)UI”设计官方教
  10. Android中的引用传递和值传递分析(Java)