程序员

Android-使用MediaPlayer播放网络音频并且缓存

2020-07-12  本文已影响0人  Alex富贵

需求

实现

MediaPlayer mediaPlayer;
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);//设置播放来源
mediaPlayer.prepareAsync();//异步准备
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                //异步准备监听
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    LogUtils.debugLongInfo("Voice异步文件准备完成");
                    LogUtils.debugLongInfo("Voice异步文件时长", mediaPlayer.getDuration() / 1000 + "");
                    mediaPlayer.start();//播放
                }
            });
mediaPlayer.setScreenOnWhilePlaying(true);// 设置播放的时候一直让屏幕变亮
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
                //文件缓冲监听
                @Override
                public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
                    LogUtils.debugLongInfo("Voice进度", i + "%");
                    LogUtils.debugLongInfo("Voice文件长度", mediaPlayer.getDuration() / 1000 + "");
                }
            });

遇到的问题

解决思路

尝试

1.每个item的holder中加载一个MediaPlayer,提前异步加载,点击的时候再播放.
结果:会报错 MediaPlayer finalized without being released
2.列表页面不做提前加载操作.二级页面在onCreate中加载MediaPlayer,但是只有点击的时候才播放.
结果:可行,但是又回到原点,用户体验不好.
3.使用网络提前在holder中将url的File下载到本地文件夹中,播放的时候检查本地缓存中是否有这个文件,有的话播放本地声音文件,没有的话再播放网络文件.
结果:自己搭建一个网络下载缓存框架成本太高,而且如果用户加载到没有缓存的内容体验还是很差.而且MediaPlayer播放网络音频和本地音频方法不同,没必要写多余的判断走不同的代码逻辑.

最终思路

列表页面加载出item的时候就应该已经异步加载url中的文件.点击播放的时候使用直接播放本地文件.(我的业务场景中声音文件都很小,60s以内下载也比较快).简单参考Glide的加载缓存模式
发现了一个AndroidVoice缓存库
AndroidVideoCache
使用详解
视频缓存AndroidVideoCache攻略
参考文章
Android 使用MediaPlayer播放网络音频
AndroidVideoCache库使用了一种代理方式,如果文件缓存在了本地,仍然会提供一个url地址.此时页面中只需要使用播放url的方法就可以使用AndroidVideoCache的本地url进行播放.

需要注意的问题

1.AndroidVideoCache框架不支持边播边缓存
2.不支持m3u8格式(其他不支持格式未知,我使用.mp3文件没问题)
3.不支持HTTPS 解决办法:Android 9.0 使用AndroidVideoCache时不能缓存视频
其他问题详看issues

我这个需求比较简单,简单实现一个demo即可.现在音视频类APP越来越多,这类需求也越发复杂,有更好的解决方式还请留言告知,以便帮助更多人.

MediaPlayer常用方法,注意调用顺序错误会报异常

int getCurrentPosition();// 得到当前播放位置(ms)
int getDuration();// 得到文件的时间(ms)
void setLooping(boolean var1);// 设置是否循环播放
boolean isLooping();// 是否循环播放
boolean isPlaying();// 是否正在播放
void pause();// 暂停
void prepare();// 同步准备
void prepareAsync();// 异步准备
void release();// 释放MediaPlayer对象
void reset();// 重置MediaPlayer对象
void seekTo(int msec);// 指定播放位置(以毫秒为单位)
void setDataSource(String path);// 设置播放资源
void setScreenOnWhilePlaying(boolean screenOn);// 设置播放的时候一直让屏幕变亮
void setWakeMode(Context context, int mode);// 设置唤醒模式
void setVolume(float leftVolume, float rightVolume);// 设置音量,参数分别表示左右声道声音大小,取值范围为0~1
void start();// 开始播放
void stop();// 停止播放

void setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener);//文件缓冲监听
void setOnPreparedListener(MediaPlayer.OnPreparedListener listener);//异步准备监听
void setOnCompletionListener(MediaPlayer.OnCompletionListener listener);//播放完成监听
void setOnErrorListener(MediaPlayer.OnErrorListener listener);//播放异常监听

自己也维护了一个库,逐步完善中

VoicePlayer

欢迎使用

上一篇 下一篇

猜你喜欢

热点阅读