fix: pull active media session on start, icon centering, tap highlight, media card
This commit is contained in:
@@ -22,36 +22,21 @@ class MediaSessionSource(context: Context) {
|
||||
private var callback: ((MediaInfo?) -> Unit)? = null
|
||||
private var registered = false
|
||||
|
||||
// 具名监听器字段:回调通过 callback 字段转发,便于 start/stop 幂等管理
|
||||
// Named listener field: forwards via callback, enabling idempotent start/stop
|
||||
// 具名监听器字段:会话列表变化时回调
|
||||
// Named listener field: fires when the active-session list changes
|
||||
private val activeSessionsListener =
|
||||
MediaSessionManager.OnActiveSessionsChangedListener { controllers ->
|
||||
val cb = callback ?: return@OnActiveSessionsChangedListener
|
||||
val c = controllers?.firstOrNull()
|
||||
if (c == null) {
|
||||
Log.d(TAG, "no active media session")
|
||||
cb(null)
|
||||
return@OnActiveSessionsChangedListener
|
||||
}
|
||||
val meta = c.metadata
|
||||
val state = c.playbackState
|
||||
cb(
|
||||
MediaInfo(
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_TITLE) ?: "",
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_ARTIST) ?: "",
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_ALBUM) ?: "",
|
||||
state?.state == PlaybackState.STATE_PLAYING,
|
||||
state?.position ?: 0L,
|
||||
meta?.getLong(MediaMetadata.METADATA_KEY_DURATION) ?: 0L,
|
||||
c.packageName,
|
||||
)
|
||||
)
|
||||
Log.d(TAG, "media: ${c.packageName}")
|
||||
notifyMedia(controllers?.firstOrNull(), cb)
|
||||
}
|
||||
|
||||
// 注册监听:幂等——先移除旧监听再注册,避免重复 start 累积监听器
|
||||
// Register the listener: idempotent — remove the old listener first, avoiding
|
||||
// listener accumulation from repeated start() calls
|
||||
// 注册监听:幂等——先移除旧监听再注册,避免重复 start 累积监听器。
|
||||
// 注册后主动拉取一次当前活跃会话:注册前已开始的播放不会触发变化回调,
|
||||
// 主动拉取保证启动时媒体卡即可显示。
|
||||
// Register the listener: idempotent — remove the old one first to avoid accumulation.
|
||||
// After registering, actively pull the current sessions once: playback that started
|
||||
// before registration never fires the change callback, so the active pull makes the
|
||||
// media card show immediately on startup.
|
||||
fun start(cb: (MediaInfo?) -> Unit) {
|
||||
stop()
|
||||
callback = cb
|
||||
@@ -59,6 +44,8 @@ class MediaSessionSource(context: Context) {
|
||||
msm.addOnActiveSessionsChangedListener(activeSessionsListener, listenerComponent)
|
||||
registered = true
|
||||
Log.d(TAG, "start: media session listener registered")
|
||||
val current = msm.getActiveSessions(listenerComponent).firstOrNull()
|
||||
notifyMedia(current, cb)
|
||||
} catch (e: SecurityException) {
|
||||
// 未授权「通知使用权」时系统抛 SecurityException:媒体监听降级为不可用,不崩溃。
|
||||
// 用户在系统设置开启通知使用权后,重启 Hearth 才会恢复媒体卡。
|
||||
@@ -81,6 +68,30 @@ class MediaSessionSource(context: Context) {
|
||||
callback = null
|
||||
}
|
||||
|
||||
// 从 controller 提取 metadata + playbackState 构造 MediaInfo 并回调
|
||||
// Build MediaInfo from the controller's metadata + playbackState and invoke the callback
|
||||
private fun notifyMedia(controller: MediaController?, cb: (MediaInfo?) -> Unit) {
|
||||
if (controller == null) {
|
||||
Log.d(TAG, "no active media session")
|
||||
cb(null)
|
||||
return
|
||||
}
|
||||
val meta = controller.metadata
|
||||
val state = controller.playbackState
|
||||
cb(
|
||||
MediaInfo(
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_TITLE) ?: "",
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_ARTIST) ?: "",
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_ALBUM) ?: "",
|
||||
state?.state == PlaybackState.STATE_PLAYING,
|
||||
state?.position ?: 0L,
|
||||
meta?.getLong(MediaMetadata.METADATA_KEY_DURATION) ?: 0L,
|
||||
controller.packageName,
|
||||
)
|
||||
)
|
||||
Log.d(TAG, "media: ${controller.packageName}")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "HearthMedia"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user