在安卓中MediaPlayer的应用范围很广,主要用于播放音乐与视频。本文主要介绍如何使用MediaPlayer播放音频。

本文分为两个部分第一部分主要介绍播放本地音频,第二部分介绍播放网络音频。


使用MediaPlayer播放本地音频文件


首先准备一首歌曲,笔者使用的是ywasn.mp3,放在res/raw


最简单的用法,莫过于直接创建MediaPlayer对象然后调用start方法了:


MediaPlayer mediaPlayer=MediaPlayer.create(this, R.raw.ywasn);
        mediaPlayer.start();

MediaPlayer.create();有很多重载,其中笔者调用的是第一个参数传入context,第二个参数传进资源id。


除此之外还可以传进一个uri,还有更多用法可以参见官方文档。


这样的写法虽然简单但是也有不足之处,调用create方法每次都会创建一个MediaPlayer对象,那么如果用于类似音乐播放器这种情况就不太合适了。因为程序循环播放多个音频文件就不合适了。因为播放一次都要调用一次,每次都创建一个mediaplayer对象,这回消耗大量的内存资源。



我们还可以使用一下方法:


mediaPlayer.setDataSource(Environment.getExternalStorageDirectory()+"/ywasn.mp3");
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.prepare(); //准备播放
            mediaPlayer.start();//开始播放
            mediaPlayer.pause();//暂停播放,暂停播放之后想要恢复播放可以调用start
            mediaPlayer.stop();//停止播放,停止播放之后就算调用start也不能再次播放了。需要再次调用prepare再调用start才能再次播放
            mediaPlayer.reset();//使处于异常的MediaPlayer重置到空闲状态
            mediaPlayer.release();//释放MediaPlayer





使用MediaPlayer播放网络音频



除了能够播放本地音频之外还能够播放网络上的音频,与播放本地音频的用法大同小异。





MediaPlayer mediaPlayer=new MediaPlayer();
        try {
            mediaPlayer.setDataSource("http://5.595818.com/2015/ring/000/140/6731c71dfb5c4c09a80901b65528168b.mp3");
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.prepare(); //准备播放
            mediaPlayer.start();//开始播放

        } catch (IOException e) {
            e.printStackTrace();
        }



使用这样的方法就可以播放目标地址的mp3,但是会发现,打开程序之后并不会立刻播放,尤其是在网速慢的手机上更是明显会等待一段时间才会播放,跟我们平时使用的酷狗音乐有点不一样,酷狗是还没下载完就可以播放了,但是我们这样写的话是要等待下载完之后才能播放的。



那么为了优化用户体验我们可以把写法改一改。





MediaPlayer mediaPlayer=new MediaPlayer();
        try {
            mediaPlayer.setDataSource("http://5.595818.com/2015/ring/000/140/6731c71dfb5c4c09a80901b65528168b.mp3");
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.prepareAsync(); //异步准备播放
//            mediaPlayer.start();//开始播放

        } catch (IOException e) {
            e.printStackTrace();
        }



可以看到把上面的代码在prepare这一步的写法变了,变成prepareAsync,这是一个异步方法。在获取目标资源的同时还可以一边播放。但是我们并不能调用完mediaPlayer.prepareAsync之后就立刻调用start。因为网络延时是不可估计的,如果就这么直接调用了start,万一我们的播放器还没获取到目标资源就会播放出错。





因此我们需要使用mediaplay自带的一个监听器OnPreparedListener:





try {
            mediaPlayer.setDataSource("http://5.595818.com/2015/ring/000/140/6731c71dfb5c4c09a80901b65528168b.mp3");
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.prepareAsync(); //异步准备播放

            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.start();//开始播放
                }
            });

        } catch (IOException e) {
            e.printStackTrace();
        }

如上所示,把start操作放到onPrepared里面就可以了。那么程序就会在获取到资源之后回调onPrepare