Android中MediaPlayer.getDuration()返回错误时长的解决方法咨询
我之前也踩过这个坑!这种情况大多是因为MediaPlayer的加载逻辑没处理对,或者音频格式在Android端有兼容性问题,给你几个实用的解决思路:
务必在MediaPlayer准备完成后再获取时长
Android的MediaPlayer是异步加载音频资源的,如果你刚调用setDataSource()就直接调用getDuration(),此时资源还没加载完成,返回的自然是错误值。正确的做法是通过setOnPreparedListener()监听准备完成事件,在回调里获取时长:MediaPlayer mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource(context, audioUri); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // 这里的时长才是准确的 int accurateDuration = mp.getDuration(); mp.start(); } }); // 用异步准备避免阻塞主线程,防止ANR mediaPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); }检查音频文件的编码兼容性
桌面播放器对音频格式的兼容性远强于Android原生MediaPlayer,比如一些小众的MP3编码变种、非标准的AAC profile,都可能导致MediaPlayer解析时长出错。建议把音频转成Android支持的标准格式,比如LAME编码的MP3、AAC-LC编码的文件再测试。换用ExoPlayer替代原生MediaPlayer
Google官方的ExoPlayer对各种音频格式的支持比原生MediaPlayer完善得多,解析时长的可靠性也更高。简单示例:SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).build(); MediaItem mediaItem = MediaItem.fromUri(audioUri); player.setMediaItem(mediaItem); player.addListener(new Player.Listener() { @Override public void onMediaMetadataChanged(MediaMetadata mediaMetadata) { long duration = mediaMetadata.extras.getLong(MediaMetadata.EXTRA_DURATION); // 在这里获取准确时长 } }); player.prepare();直接解析音频元数据(不依赖MediaPlayer)
如果不想更换播放器,可以用第三方库直接读取音频文件的元数据来获取时长,比如FFmpegMediaMetadataRetriever,它不需要等待MediaPlayer加载,直接解析文件信息:FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever(); try { retriever.setDataSource(context, audioUri); String durationStr = retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION); long accurateDuration = Long.parseLong(durationStr); } catch (Exception e) { e.printStackTrace(); } finally { retriever.release(); }
如果以上方法都不行,可以检查音频文件是否存在损坏,或者提供具体的音频编码信息,方便进一步排查。
内容的提问来源于stack exchange,提问作者karthiKeyan B

