MediaButtonReceiver---独特的媒体广播接收器
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的唯一接收器
更多相关文章
- 实现Android监控任意控件或按键双击事件方法
- 在QQ通讯录之前拦截短信
- android2.2应用开发之IccCard(sim卡或USIM卡)(转至 http://www.2cto
- Android自学笔记-17-广播接收者(BroadcastReceiver)
- Android(安卓)LocalBroadcastReceiver本地广播
- Android(安卓)按键映射 驱动
- Android(安卓)4.0以上设备虚拟按键中显示Menu键
- Android键盘系统——改变按键功能(2)
- Android之SqliteDatabase(MVP模式)实现用户登录注册功能