天天看點

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();
    }
}      

                                          完整示例代碼點選檢視

繼續閱讀