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;

	@Override
	public 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的唯一接收器

你可能感兴趣的:(MEDIA_BUTTON,耳机按键监听,android,Android,知识解析)