You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Media3(ExoPlayer):如何设置Timeline中Window的defaultPositionUs?

给Media3播放列表项设置默认起始位置(恢复上次播放进度)

首先明确:Timeline.Window.defaultPositionUs是只读属性,无法直接设置,它是Player根据MediaItem的配置或存储的进度自动计算得出的。要实现播放列表项自动切换时从上次中断处恢复,有以下几种可行方案:

方案一:给每个MediaItem单独配置起始位置

在构建MediaItem时,直接通过MediaItem.Builder指定起始位置,Player加载该MediaItem时会自动从指定位置开始播放。

示例代码:

// 假设你已保存了每个媒体的上次播放位置(单位:毫秒)
val savedPositions = mapOf(
    "media_id_1" to 15000L, // 第一个MP3上次播放到15秒
    "media_id_2" to 30000L  // 第二个MP3上次播放到30秒
)

// 构建带起始位置的MediaItem列表
val mediaItems = listOf(
    MediaItem.Builder()
        .setUri("https://example.com/song1.mp3")
        .setMediaId("media_id_1")
        .setStartPositionMs(savedPositions["media_id_1"] ?: 0)
        .build(),
    MediaItem.Builder()
        .setUri("/storage/emulated/0/song2.mp3")
        .setMediaId("media_id_2")
        .setStartPositionMs(savedPositions["media_id_2"] ?: 0)
        .build()
)

// 设置播放列表
player.setMediaItems(mediaItems)
player.prepare()

方案二:利用Media3的进度存储机制(推荐)

Media3提供了MediaItemMetadataStore接口,可自动保存和读取每个MediaItem的播放进度,无需手动管理每个item的起始位置配置。

1. 实现简单的MetadataStore

用SharedPreferences实现自定义存储:

class SharedPrefMetadataStore(private val context: Context) : MediaItemMetadataStore {
    private val prefs = context.getSharedPreferences("media_progress", Context.MODE_PRIVATE)

    override fun getMetadata(mediaItem: MediaItem): MediaItemMetadata? {
        val position = prefs.getLong(mediaItem.mediaId, 0)
        return MediaItemMetadata.Builder()
            .setPlaybackPositionMs(position)
            .build()
    }

    override fun updateMetadata(mediaItem: MediaItem, metadata: MediaItemMetadata) {
        prefs.edit()
            .putLong(mediaItem.mediaId, metadata.playbackPositionMs)
            .apply()
    }
}

2. 给Player配置MetadataStore

初始化Player时传入自定义存储实例:

val player = ExoPlayer.Builder(context)
    .setMediaItemMetadataStore(SharedPrefMetadataStore(context))
    .build()

// 设置播放列表后,Player会自动读取每个item的保存进度
player.setMediaItems(mediaItems)
player.prepare()

这种方案下,Player会在播放暂停/切换时自动保存当前item的进度,下次加载该item时自动从上次位置恢复,完全适配播放列表自动切换的场景。

方案三:播放列表切换时手动设置位置

如果需要更精细的控制,可以监听Player的MediaItemTransitionListener,在切换到新的MediaItem时手动设置起始位置:

player.addMediaItemTransitionListener(object : MediaItemTransitionListener {
    override fun onMediaItemTransition(
        mediaItem: MediaItem?,
        reason: Int
    ) {
        mediaItem?.let {
            val savedPosition = getSavedPosition(it.mediaId) // 自定义方法获取保存的进度
            player.seekTo(savedPosition)
        }
    }
})

内容的提问来源于stack exchange,提问作者Akshdeep Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:25:14