feat: media card polish - per-index controls, cover jump, wrap, slide transition
This commit is contained in:
@@ -2,6 +2,7 @@ package top.yeij.hearth.media
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.media.MediaMetadata
|
||||
import android.media.session.MediaController
|
||||
@@ -13,11 +14,13 @@ import java.io.ByteArrayOutputStream
|
||||
|
||||
// 监听系统活跃媒体会话(支持多个:音乐/听书/视频同时在线),
|
||||
// 元数据/播放状态变化时实时回调(切歌、暂停/播放即时推送);
|
||||
// 提供播放控制(上一首/暂停播放/下一首)与封面提取。
|
||||
// 提供播放控制(上一首/暂停播放/下一首)、封面提取与跳转播放界面。
|
||||
// Watch active media sessions (supports multiple: music/audiobook/video at once),
|
||||
// push in real time on metadata/playback-state change (track switch, play/pause);
|
||||
// provide transport controls (previous/play-pause/next) and cover extraction.
|
||||
// provide transport controls (previous/play-pause/next), cover extraction and
|
||||
// jumping to the playback UI.
|
||||
class MediaSessionSource(context: Context) {
|
||||
private val appContext = context.applicationContext
|
||||
private val msm = context.getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager
|
||||
|
||||
// 通知监听组件作为授权凭据传入 addOnActiveSessionsChangedListener,
|
||||
@@ -99,23 +102,48 @@ class MediaSessionSource(context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// 播放控制:作用于第一个(当前展示)controller
|
||||
// Transport controls: act on the first (currently shown) controller
|
||||
fun previous() {
|
||||
controllers.firstOrNull()?.transportControls?.skipToPrevious()
|
||||
Log.d(TAG, "previous")
|
||||
// 播放控制:作用于指定索引的 controller(对应 H5 当前滑到的会话)
|
||||
// Transport controls: act on the controller at the given index (matching the
|
||||
// session the H5 card is currently showing)
|
||||
fun previous(index: Int) {
|
||||
controllers.getOrNull(index)?.transportControls?.skipToPrevious()
|
||||
Log.d(TAG, "previous: index=$index")
|
||||
}
|
||||
|
||||
fun next() {
|
||||
controllers.firstOrNull()?.transportControls?.skipToNext()
|
||||
Log.d(TAG, "next")
|
||||
fun next(index: Int) {
|
||||
controllers.getOrNull(index)?.transportControls?.skipToNext()
|
||||
Log.d(TAG, "next: index=$index")
|
||||
}
|
||||
|
||||
fun playPause() {
|
||||
val c = controllers.firstOrNull() ?: return
|
||||
fun playPause(index: Int) {
|
||||
val c = controllers.getOrNull(index) ?: return
|
||||
val playing = c.playbackState?.state == PlaybackState.STATE_PLAYING
|
||||
if (playing) c.transportControls.pause() else c.transportControls.play()
|
||||
Log.d(TAG, "playPause: playing=$playing")
|
||||
Log.d(TAG, "playPause: index=$index playing=$playing")
|
||||
}
|
||||
|
||||
// 跳转到指定会话的播放界面:优先 sessionActivity(PendingIntent),
|
||||
// 失败则回退到启动该 App
|
||||
// Jump to the session's playback UI: prefer sessionActivity (PendingIntent),
|
||||
// fall back to launching the app
|
||||
fun openMediaApp(index: Int) {
|
||||
val c = controllers.getOrNull(index) ?: return
|
||||
val sessionActivity = c.sessionActivity
|
||||
if (sessionActivity != null) {
|
||||
try {
|
||||
sessionActivity.send()
|
||||
Log.d(TAG, "openMediaApp: sessionActivity sent for ${c.packageName}")
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "openMediaApp: sessionActivity failed: ${e.message}")
|
||||
}
|
||||
}
|
||||
val launch = appContext.packageManager.getLaunchIntentForPackage(c.packageName)
|
||||
if (launch != null) {
|
||||
launch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
appContext.startActivity(launch)
|
||||
Log.d(TAG, "openMediaApp: launched ${c.packageName}")
|
||||
}
|
||||
}
|
||||
|
||||
// 更新 controller 列表:注销旧回调、注册新回调
|
||||
|
||||
Reference in New Issue
Block a user