问题描述
背景信息:,我需要检测用户何时按下大多数耳机上的播放/暂停按钮(KEYCODE_MEDIA_PLAY_PAUSE).
Background Info: I need to detect whenever a user presses the play/pause button found on most headsets (KEYCODE_MEDIA_PLAY_PAUSE).
我大多数情况下都使用MediaSessions完成它们,但是当另一个应用程序开始播放音频时,我就停止了回调.
I have it all mostly working using MediaSessions, but when another app starts playing audio, I stop getting callbacks.
这似乎是因为正在播放音频的应用创建了自己的MediaSession,而Android仅将KeyEvent发送到最新的MediaSession.为了防止这种情况,我创建了一个OnActiveSessionsChangedListener,并在每次触发时创建了一个新的MediaSession.
It seems like this is because the app that's playing audio created its own MediaSession and Android sends KeyEvents only to the newest MediaSession. To prevent this I create an OnActiveSessionsChangedListener and create a new MediaSession every time it fires.
这确实有效,但是每次我创建一个新的MediaSession时,监听器都会再次触发,所以我发现自己陷入了inf循环中.
This does work, but every time I create a new MediaSession, the listener fires again, so I find myself stuck in an inf loop.
我的问题:有人知道我该怎么做吗?
My Question: does anyone know how I can do any of the following??:
- 防止其他应用窃取我的媒体按钮焦点
- 当我将媒体按钮的焦点丢失到另一个应用程序时进行检测,因此我只能在那时创建一个新的MediaSession,而不是在每次激活时创建一个新的MediaSession会话发生变化
- 检查我当前是否已经具有媒体按钮焦点,所以我不必要地创建一个新的MediaSession
什么不起作用:
- BroadcastReceiver已开启AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION无效因为应用必须手动触发该广播以及许多应用,像NPR One一样
- AudioManager.OnAudioFocusChangeListener无法正常工作,因为它需要我音频焦点
- 在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));
以下是触发的处理程序:
Here is the handler that gets triggered:
private final Handler mAudioFocusHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (mShouldBeEnabled) {
updateButtonReceiverEnabled(true);
}
}
};
最后是处理程序触发的方法:
And finally here is the method that the Handler triggers:
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
来获取Media Button的所有操作.时间 .
if you just want to capture MediaButton
you can register a BroadcastReceiver
to get Media Button action all the time .
MediaButtonIntentReceiver类:
MediaButtonIntentReceiver class :
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:
add this to manifest.xml:
<receiver android:name=".MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
并这样注册您的 BroadcastReceiver
(在主要活动中)
and register your BroadcastReceiver
like this ( in main activity)
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
MediaButtonIntentReceiver r = new MediaButtonIntentReceiver();
filter.setPriority(1000);
registerReceiver(r, filter);
另请参阅:
这篇关于始终接收所有Android媒体按钮事件的回调(即使其他应用正在播放音频)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!