背景信息:我需要检测用户何时按下大多数耳机上的播放/暂停按钮(KEYCODE_MEDIA_PLAY_PAUSE)。
我主要使用 MediaSessions 来工作,但是当另一个应用程序开始播放音频时,我停止收到回调。
这似乎是因为播放音频的应用程序创建了自己的 MediaSession,而 Android 仅将 KeyEvents 发送到最新的 MediaSession。为了防止这种情况,我创建了一个 OnActiveSessionsChangedListener 并在每次触发时创建一个新的 MediaSession。
这确实有效,但是每次我创建一个新的 MediaSession 时,监听器都会再次触发,所以我发现自己陷入了一个 inf 循环。
我的问题:有谁知道我可以如何做以下任何事情?:
- 防止其他应用窃取我的媒体按钮焦点
- 检测我何时失去了对另一个应用程序的媒体按钮焦点,因此我只能在那时创建一个新的 MediaSession,而不是在活动会话发生变化时创建一个新的 MediaSession
- 检查我当前是否已经拥有媒体按钮焦点,因此我不必要地创建了一个新的 MediaSession
什么不起作用:
- AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION 上的 BroadcastReceiver 不起作用,因为应用程序必须手动触发该广播,而许多应用程序,如 NPR One 则没有
- AudioManager.OnAudioFocusChangeListener 不起作用,因为它需要我有音频焦点
- 在 android.intent.action.MEDIA_BUTTON 上具有最高优先级的 BroadcastReceiver 并调用 abortBroadcast(),但是当其他应用程序正在播放音频时,我的接收器没有被触发。此外,其他应用程序也可以设置最高优先级。
我的代码:
mMediaSessionManager.addOnActiveSessionsChangedListener(controllers -> {
boolean updateButtonReceiver = false;
// recreate MediaSession if another app handles media buttons
for (MediaController mediaController : controllers) {
if (!TextUtils.equals(getPackageName(), mediaController.getPackageName())) {
if ((mediaController.getFlags() & (MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS)) != 0L) {
updateButtonReceiver = true;
}
}
}
if (updateButtonReceiver) {
// using a handler with a delay of about 2 seconds because this listener fires very often.
mAudioFocusHandler.removeCallbacksAndMessages(null);
mAudioFocusHandler.sendEmptyMessageDelayed(0, AUDIO_FOCUS_DELAY_MS);
}
}, ClickAppNotificationListener.getComponentName(this));
这是被触发的处理程序:
private final Handler mAudioFocusHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (mShouldBeEnabled) {
updateButtonReceiverEnabled(true);
}
}
};
最后是 Handler 触发的方法:
private void updateButtonReceiverEnabled(boolean shouldBeEnabled) {
// clear old session (not sure if this is necessary)
if (mMediaSession != null) {
mMediaSession.setActive(false);
mMediaSession.setFlags(0);
mMediaSession.setCallback(null);
mMediaSession.release();
mMediaSession = null;
}
mMediaSession = new MediaSessionCompat(this, MEDIA_SESSION_TAG);
mMediaSession.setCallback(mMediaButtonCallback);
mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mMediaSession.setPlaybackToLocal(AudioManager.STREAM_MUSIC);
mMediaSession.setActive(true);
mMediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE)
.setState(PlaybackStateCompat.STATE_CONNECTING, 0, 0f)
.build());
if (shouldBeEnabled != mShouldBeEnabled) {
getPackageManager().setComponentEnabledSetting(mMediaButtonComponent,
shouldBeEnabled
? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
mShouldBeEnabled = shouldBeEnabled;
}
谢谢!