gpt4 book ai didi

android - 始终接收所有 Android 媒体按钮事件的回调(即使另一个应用程序正在播放音频)

转载 作者:塔克拉玛干 更新时间:2023-11-02 18:57:27 25 4
gpt4 key购买 nike

背景信息:我需要检测何时用户按下大多数耳机上的播放/暂停按钮 (KEYCODE_MEDIA_PLAY_PAUSE)。

大部分时间都在使用 MediaSessions,但当另一个应用程序开始播放音频时,我就停止接收回调了。

这似乎是因为正在播放音频的应用程序创建了自己的 MediaSession,而 Android 仅将 KeyEvents 发送到最新的 MediaSession。为防止这种情况,我创建了一个 OnActiveSessionsChangedListener 并在每次触发时创建一个新的 MediaSession。

这确实有效,但每次我创建一个新的 MediaSession 时,监听器都会再次触发,所以我发现自己陷入了一个 inf 循环。

我的问题:有谁知道我怎样才能做到以下任何一项??:

  • 防止其他应用窃取我的媒体按钮焦点
  • 检测我何时将媒体按钮焦点转移到另一个应用程序,这样我才能创建一个新的 MediaSession,而不是每当 Activity session 变化
  • 检查我目前是否已经拥有媒体按钮焦点,所以我不必要地创建一个新的 MediaSession

什么不起作用:

  • BroadcastReceiver 开启AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION 无效因为应用必须手动触发广播,还有很多应用,像 NPR One 一样不
  • AudioManager.OnAudioFocusChangeListener 没有工作,因为它需要我有音频焦点
  • BroadcastReceiver 在 android.intent.action.MEDIA_BUTTON 上具有最高优先级并调用 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;
}

谢谢!

最佳答案

如果您只想捕获 MediaButton,您可以注册一个 BroadcastReceiver 以始终获取媒体按钮操作。

MediaButtonIntentReceiver 类:

public class MediaButtonIntentReceiver extends BroadcastReceiver {

public MediaButtonIntentReceiver() {
super();
}

@Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
return;
}
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return;
}
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
// do something
Toast.makeText(context, "BUTTON PRESSED!", Toast.LENGTH_SHORT).show();
}
abortBroadcast();
}
}

将此添加到 manifest.xml 中:

<receiver android:name=".MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>

并像这样注册您的BroadcastReceiver(在主要 Activity 中)

IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
MediaButtonIntentReceiver r = new MediaButtonIntentReceiver();
filter.setPriority(1000);
registerReceiver(r, filter);

也看看:

How to capture key events from bluetooth headset with android

How do I intercept button presses on the headset in Android?

关于android - 始终接收所有 Android 媒体按钮事件的回调(即使另一个应用程序正在播放音频),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38289086/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com