使用 MediaSessionCompat 来实现 Media Button 的监听

在 API21 之前,如果想实现线控,则只需要使用:

1
AudioManager.reregisterMediaButtonEventReceiver(ComponentName eventReceiver)

即可,但是最近更新 SDK 之后发现这个 API 已经废弃掉了,推荐使用 MediaSession 来代替。

API21 之前的实现可以参考这篇文章,但是 MediaSession 是在新的 api 中加入的,我们可以使用 android.support.v4.media.session.MediaSessionCompat:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Creates a new session.
*
* @param context The context.
* @param tag A short name for debugging purposes.
* @param mediaButtonEventReceiver The component name for your receiver.
* If null, this will attempt to find an appropriate
* {@link BroadcastReceiver} that handles
* {@link Intent#ACTION_MEDIA_BUTTON} from your manifest.
* A receiver is required to support platform versions earlier
* than {@link android.os.Build.VERSION_CODES#LOLLIPOP}.
* @param mbrIntent The PendingIntent for your receiver component that
* handles media button events. This is optional and will be used
* on {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} and
* later instead of the component name.
*/
public MediaSessionCompat(Context context, String tag, ComponentName mediaButtonEventReceiver,
PendingIntent mbrIntent) {

MediaSessionCompat 的构造函数一共有四个参数,我们这里简单实现 Media Button 的监听,只需要 context 和 mediaButtonEventReceiver 即可,tag 用于调试,mbrIntent 设置为 null 即可。首先和 API21 之前一样实现了一个 MediaButtonReceiver:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
}
}

接下来我们要做的就是 new 一个 MediaSessionCompat:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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();
}
}

其他的和 API21 之前一样,需要在 manifest 中注册这个 MediaButtonReceiver

1
2
3
4
5
<receiver android:name="com.coolerfall.managers.receivers.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON"/>
</intent-filter>
</receiver>

这样就可以实现和 API21 之前的监听效果了。

PS: API21 之前 MediaButtonReceiver 是必须的;API21 之后 MediaSessionCompat.setCallback 是必须的,因为 MediaSessionCompatAPI21 之后通过 callback 来处理 media button。