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

Android API23升级到API28后低码率音频MediaPlayer.getDuration()返回-1问题

解决API 28中MediaPlayer.getDuration()对低码率音频返回-1的问题

我之前也碰到过类似的升级问题,结合Android官方文档和实际测试,这个情况大概率是因为API 28及以上版本中,MediaPlayer对低码率音频的元数据解析逻辑变严格了——低码率音频的时长信息没法在setDataSource之后立即被解析出来,而旧版本API的处理逻辑更宽松,所以侥幸能拿到正确时长。

下面是几个经过验证的解决方案:

方案1:必须等MediaPlayer完全准备好再获取时长

MediaPlayer的很多核心操作(包括获取时长)都要求它进入Prepared状态才能正常工作。你之前的代码可能没等准备完成就调用getDuration(),在API 23中碰巧生效,但新版API对状态检查更严格,直接调用就会返回-1。

正确的写法应该用异步准备+监听回调:

MediaPlayer mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
    mp.setDataSource("你的低码率音频URL");
    // 设置准备完成监听器
    mp.setOnPreparedListener(mediaPlayer -> {
        // 此时MediaPlayer已就绪,安全获取时长
        int duration = mediaPlayer.getDuration();
        Log.d("MediaPlayer", "音频时长:" + duration + "ms");
        // 可以在这里开始播放
        mediaPlayer.start();
    });
    // 设置错误监听器,处理加载失败情况
    mp.setOnErrorListener((mediaPlayer, what, extra) -> {
        Log.e("MediaPlayer", "准备失败:错误码=" + what + ", 额外信息=" + extra);
        return false;
    });
    // 异步准备,避免阻塞主线程(网络音频尤其重要)
    mp.prepareAsync();
} catch (IOException e) {
    e.printStackTrace();
}

划重点:绝对不要在setDataSource之后直接调用getDuration(),一定要在OnPreparedListener的回调里执行这个操作。

方案2:改用ExoPlayer替代原生MediaPlayer

Google现在官方推荐用ExoPlayer作为媒体播放的首选方案,它对各种码率、格式的兼容性比原生MediaPlayer好太多,尤其是处理低码率、特殊编码的媒体文件时表现更稳定。

用ExoPlayer获取时长的简化示例:

// 初始化ExoPlayer
SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).build();
// 创建媒体源
MediaItem mediaItem = MediaItem.fromUri("你的低码率音频URL");
player.setMediaItem(mediaItem);
// 添加状态监听
player.addListener(new Player.Listener() {
    @Override
    public void onPlaybackStateChanged(int playbackState) {
        if (playbackState == Player.STATE_READY) {
            // 获取时长(单位:毫秒)
            long duration = player.getDuration();
            Log.d("ExoPlayer", "音频时长:" + duration + "ms");
        }
    }
});
// 开始准备
player.prepare();

ExoPlayer的解析逻辑更健壮,而且官方会持续更新维护,后续版本的兼容性更有保障,如果你经常处理各种媒体文件,建议直接切换到ExoPlayer。

方案3:手动解析音频元数据(仅复杂场景备用)

如果上面两个方案都不适用,你可以考虑手动解析音频文件的时长。比如MP3文件,可以读取ID3标签或者计算音频帧的总长度来推导时长,但这种方式需要处理文件IO,网络音频还得先下载部分数据,实现起来比较繁琐,一般不推荐作为首选方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:40:45