天天看点

MediaPlayer之音频播放

一 前言

        android提供了简单的播放音频和视频的类MediaPlayer,它可以播放raw、assets、sdk、网络上的音视频资源,在前面已经介绍过MediaPlayer(点击查看)。

二 音频播放

      播放音频步骤:

(1)创建MediaPlayer对象实例;可以通过new创建该实例,也可以通过静态方法create创建。 (2)装载音频资源,如果在(1)中你使用create创建的MediaPlayer,此时该步骤可省略,否则你将调用setDataSource添加音频资源。 (3)调用prepare()或prepareAsync()方法来做播放前的准备工作,如果(2)省略的话,该步骤也要省略(即如果你掉用setDataSource方法添加音频资源了,就要调用prepare()或prepareAsync()方法做播放前的准备工作,否则就不需要了)。 (4)调用MediaPlayer的start、stop、pause等方法控制播放过程。

1 播放raw中的音频资源文件

           首先在res目录创建目录raw ,在raw添加你要播放的音频资源文件,然后就可以按照上述步骤就行了,创建MediaPlayer对象实例代码如下:

private MediaPlayer player;
    @AfterViews
    void initData(){
        player = new MediaPlayer();
//        loadRaw();
    }      

播放音频代码如下:

void loadRaw(){
         /*
         * 判断音频是否在正在播放,如果是正在播放,
         * 就要调用reset方法进行重置,此时player会处于空闲状态,
         * 如果不进行重置的话,再调用setDataSource设置资源时,会抛出异常 IllegalStateException
         */
        if (player.isPlaying()){
//            player.release();
            player.stop();
        }
        player.reset();
//        player = MediaPlayer.create(this, R.raw.hongyanjiu);
        AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.hongyanjiu);
        try {
            player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
            afd.close();
            player.prepare();
            player.start();
            //设置播放监听
            setListener();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }      

        说明,需要注意的是在装载资源之前,先要判断是否有资源正在播放,如果有的话就要调用stop停止播放,然后调用reset方法使MediaPlayer处于空闲状态,否则的将会出现非法状态异常。接下来看看是如何设置监听的,这里直接继承了监听类,如下:

public class MainActivity extends AppCompatActivity
        implements MediaPlayer.OnCompletionListener,MediaPlayer.OnErrorListener ,
        MediaPlayer.OnPreparedListener,MediaPlayer.OnSeekCompleteListener {
        ......
}      

然后

void setListener(){
    player.setOnCompletionListener(this);
    player.setOnErrorListener(this);
    player.setOnPreparedListener(this);
    player.setOnSeekCompleteListener(this);
}      

需要实现的方法,如下:

/**
 * 音频播放完成调用该方法
 * @param mp
 */
@Override
public void onCompletion(MediaPlayer mp) {
    Toast.makeText(this, "音频播放完毕", Toast.LENGTH_SHORT).show();
}

/**
 * 音频播放错误调用该方法
 * @param mp
 * @param what  错误类型
 * @param extra
 * @return
 */
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
    Toast.makeText(this, "音频播放发生错误", Toast.LENGTH_SHORT).show();
    return false;
}

/**
 * 当方法prepare被调用触发该方法
 * @param mp
 */
@Override
public void onPrepared(MediaPlayer mp) {
    Toast.makeText(this, "音频播放已就绪", Toast.LENGTH_SHORT).show();
}


/**
 * 当调用seek方法时触发该方法
 * @param mp
 */
@Override
public void onSeekComplete(MediaPlayer mp) {
    Toast.makeText(this, "音频播放已seek", Toast.LENGTH_SHORT).show();
}      

2 播放assets中的音频资源文件

           首先在src/main目录创建目录assets ,在assets添加你要播放的音频资源文件,然后就可以按照上述步骤就行了,实现fang发如下:

void loadAsset(){
        /*
         * 判断音频是否在正在播放,如果是正在播放,
         * 就要调用reset方法进行重置,此时player会处于空闲状态,
         * 如果不进行重置的话,再调用setDataSource设置资源时,会抛出异常 IllegalStateException
         */
//        player.isLooping()
        if (player.isPlaying()){
//            player.release();
            player.stop();
        }
        player.reset();
        //AssetManage对象
        AssetManager am = getAssets();
        //打开指定音频文件
        try {
            AssetFileDescriptor afd = am.openFd("hongyanjiu.mp3");
            //给MediaPlayer添加资源文件
            player.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
            //做准备工作:装载音频  使用setDataSource()方法添加资源 必须再调用prepare()装载音频, 而后才能调用start方法开始播放
            afd.close();
            player.prepare();
            player.start();
            setListener();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }      

      说明获取assets资源文件需要用到AssetManage,而AssetManage可以通过Context.getAssets()获取,然后调用AssetManage的openFd方法获取音频资源。

3 播放手机内存中的音频资源文件

          在这里我的示例是先把assets中的音频资源copy到手机的sdk里,再来播放资源文件,copy实现代码如下:

public void  copyFileFromAssetToSDK(){
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ){
            path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + getPackageName();
        }else {
            path = Environment.getDataDirectory().getAbsolutePath() + File.separator + getPackageName();
        }

        File file = new File(path);
        if (!file.exists()){
            file.mkdirs();
        }
        //AssetManage对象
        AssetManager am = getAssets();
        try {
            AssetFileDescriptor afd = am.openFd("hongyanjiu.mp3");
            InputStream is = afd.createInputStream();
//            InputStreamReader reader  =  new InputStreamReader(afd.createInputStream());
//            OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(path,"hongyanjiu.mp3")));
            File  needFile = new File(path,"hongyanjiu.mp3");
//            if (!needFile.exists()){
//                needFile.mkdirs();
//            }
            path = needFile.getAbsolutePath();
            Log.e("音频文件路径====>", path);
            OutputStream os = new FileOutputStream(needFile);
            int hasRead = 0;
            byte[] buffer = new byte [1024];
            while ((hasRead = is.read(buffer)) != -1){
                os.write(buffer,0,hasRead);
            }
            os.flush();
            os.close();
            is.close();
            afd.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
      

然后播放该音频资源代码如下:

void loadSDK(){
      /*
         * 判断音频是否在正在播放,如果是正在播放,
         * 就要调用reset方法进行重置,此时player会处于空闲状态,
         * 如果不进行重置的话,再调用setDataSource设置资源时,会抛出异常 IllegalStateException
         */
        if (player.isPlaying()){
//            player.release();
            player.stop();
        }
        player.reset();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
            //动态判断手机储存空间的权限
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == -1 ||
                    ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE ) == -1){
                ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE},0x123);
            }else {
                try {
                    copyFileFromAssetToSDK();
                    if (TextUtils.isEmpty(path)){
                        return;
                    }
                    player.setDataSource(path);
                    player.prepare();
                    player.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }else {
            try {
                copyFileFromAssetToSDK();
                if (TextUtils.isEmpty(path)){
                    return;
                }
                player.setDataSource(path);
                player.prepare();
                player.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }      

4 播放网络音频资源

void loadNet(){
     /*
     * 判断音频是否在正在播放,如果是正在播放,
     * 就要调用reset方法进行重置,此时player会处于空闲状态,
     * 如果不进行重置的话,再调用setDataSource设置资源时,会抛出异常 IllegalStateException
     */
    if (player.isPlaying()){
        player.stop();
    }
    player.reset();
    Uri url =  Uri.parse(urlPath);
    try {
        player.setDataSource(this,url);
        player.prepare();
        player.start();
    } catch (IOException e) {
        e.printStackTrace();
    }

}      

说明,urlPath为网络音频资源地址。最后不要忘记在onDestroy方法释放资源:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (player.isPlaying()){
        player.stop();
        player.release();
    }
}      

                                          完整示例代码点击查看

继续阅读