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

Android MediaPlayer 如何通过URL实现播放后可离线收听音频功能

基于Android MediaPlayer实现断网可播放的在线音频方案

原生MediaPlayer默认仅对在线音频做最小必要的流式缓存,不会全量存储完整音频文件,直接传入远程URL无法满足断网后继续播放完整音频的需求,你需要搭配本地缓存代理的方案实现,具体步骤如下:


实现步骤

  • 1. 初始化私有缓存目录

在应用私有缓存目录下创建专属的音频缓存文件夹,无需申请额外存储权限:

val audioCacheDir = File(context.cacheDir, "stream_audio_cache").apply {
    if (!exists()) mkdirs()
}
  • 2. 搭建本地HTTP代理服务做中转

这是实现边下边播、全量缓存的核心逻辑:

  1. 启动一个运行在本地的轻量HTTP代理服务,端口自行指定(建议用1024以上的非知名端口)
  2. 将原本传入MediaPlayer的远程音频URL,编码后拼接为本地代理地址,格式为 http://127.0.0.1:[代理端口]/?url=[编码后的远程URL]
  3. 代理服务收到MediaPlayer的请求后,先检查本地是否有对应音频的完整缓存:
    • 已存在完整缓存:直接读取本地缓存文件返回给MediaPlayer
    • 无完整缓存:向远程服务器发起音频资源请求,下载到的数据一边写入本地缓存文件,一边同步返回给MediaPlayer播放,全量下载完成后标记该缓存为已完成状态
  • 3. 配置MediaPlayer加载代理地址

直接将拼接好的本地代理地址作为数据源传给MediaPlayer即可,其他播放逻辑和常规在线播放一致:

val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    // 传入本地代理地址,而非直接传远程音频URL
    setDataSource(context, Uri.parse(localProxyUrl))
    prepareAsync()
    setOnPreparedListener {
        // 缓冲到足够数据后自动播放
        start()
    }
}
  • 4. 缓存清理逻辑(可选)

单音频体积可达50MB,建议配置缓存上限(比如设置总缓存上限为500MB),当缓存占用超出上限时按最近最少使用规则淘汰旧缓存,避免占用过多应用存储空间。


关键注意事项

  • 不要采用先全量下载再播放的方案,会大幅增加用户等待时长,本地代理的边下边播方案可以做到和直接播放远程URL一致的启动速度
  • 本地代理服务需要和应用生命周期绑定,应用退出时主动停止代理服务,避免资源泄漏
  • 如果远程音频需要鉴权,请求头中的Cookie、Token等认证参数需要在代理发起远程请求时原样携带,避免鉴权失败
  • 音频播放过程中如果出现断网,只要代理已经下载完完整的音频文件,后续播放会直接读取本地缓存,不会受到网络状态影响

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 20:15:07