如何在不使用 MediaSessionConnector 的情况下以和平且兼容的方式手动处理 Media3 的媒体按钮操作?
以前,我曾经使用 MediaSessionConnector 和 MediaSessionCompat 处理媒体按钮命令,但由于 Android 13 的更改,我迁移到 Media3 并删除了 MediaSessionConnector,这是我之前的:
mediaSessionConnector.setMediaButtonEventHandler { player, mediaButtonEvent ->
val event: KeyEvent? = mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)
when (event?.keyCode) {
KeyEvent.KEYCODE_MEDIA_NEXT -> {
if (event.action == KeyEvent.ACTION_UP) {
nextSegment()
}
true
}
KeyEvent.KEYCODE_MEDIA_PREVIOUS -> {
if (event.action == KeyEvent.ACTION_UP) {
previousSegment()
}
true
}
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
if (event.action == KeyEvent.ACTION_UP) {
onPlayPause()
}
true
}
else -> false
}
}
如您所见,我有一些用于向后和向前操作的自定义行为来处理我们应用程序中的来回段。但最近由于 android 13 的变化,我浏览了迁移指南(从 exo 到 media3)并删除了媒体会话连接器,但我无法再手动处理媒体按钮接收器。
即使我尝试使用
android.intent.action.MEDIA_BUTTON
操作注册我自己的按钮接收器,但仍然没有触发它。然后我检查了 MediaSession (来自 media3)实现并发现它注册了一个
MediaButtonReceive本身与下面的实现具有相同的操作,它覆盖了我的,它仅适用于播放/暂停,(我正在寻找的是双击快进操作,而我需要自定义功能才能进入下一段), :
这里是谷歌 MediaButtonReceive:
private final class MediaButtonReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!Util.areEqual(intent.getAction(), Intent.ACTION_MEDIA_BUTTON)) {
return;
}
Uri sessionUri = intent.getData();
if (!Util.areEqual(sessionUri, sessionUri)) {
return;
}
KeyEvent keyEvent = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (keyEvent == null) {
return;
}
getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
}
}
据我所知,到目前为止,MediaSession 有一个内部包 private mediaSessionCompat,用于部分逻辑,如dispatchMediaEvent。
------ 一种不起作用的解决方法-----
我还尝试了一种解决方法,在实际 MediaSession 旁边再次定义 MediaSessionCompat 并为其设置回调并覆盖
onMediaButtonEvent
,但它没有触发该回调。
这是我的定义:
mediaSessionCompat = MediaSessionCompat(applicationContext, MEDIA_SESSION_TAG)
mediaSessionCompat?.setSessionActivity(mediaSession?.sessionActivity)
mediaSessionCompat?.setCallback{
override fun onMediaButtonEvent(mediaButtonEvent: Intent?): Boolean {..}
}
是否有其他和平且兼容的方式在media3中手动处理媒体按钮操作?任何见解或替代方法将不胜感激。
您尝试过最新版本吗? 您可以使用覆盖方法来实现这一点
onMediaButtonEvent
这是快速示例:
mediaSession =
MediaSession.Builder(context, player)
.setCallback(object :MediaSession.Callback{
override fun onConnect(
session: MediaSession,
controller: MediaSession.ControllerInfo
): MediaSession.ConnectionResult {
Log.d(TAG, "onConnect: ")
Toast.makeText(context, "onConnect: ", Toast.LENGTH_SHORT).show()
return super.onConnect(session, controller)
}
@OptIn(UnstableApi::class)
override fun onMediaButtonEvent(
session: MediaSession,
controllerInfo: MediaSession.ControllerInfo,
intent: Intent
): Boolean {
Toast.makeText(context, "onMediaButtonEvent: " + intent.action, Toast.LENGTH_SHORT).show()
return super.onMediaButtonEvent(session, controllerInfo, intent)
}
@OptIn(UnstableApi::class)
override fun onPlaybackResumption(
mediaSession: MediaSession,
controller: MediaSession.ControllerInfo
): ListenableFuture<MediaSession.MediaItemsWithStartPosition> {
Toast.makeText(context, "onPlaybackResumption: "+controller.connectionHints, Toast.LENGTH_SHORT).show()
Log.d(TAG, "onPlaybackResumption: ")
return super.onPlaybackResumption(mediaSession, controller)
}
})
.setSessionActivity(setSessionActivity(context))
.build()