Android MediaPlayer 播放音頻


本文鏈接: Android MediaPlayer 播放音頻

主要介紹使用MediaPlayer播放音頻的方式。關於MediaPlayer的基礎知識,比如狀態,可以參考Android MediaPlayer 基礎簡介

為了方便表達,定義變量名為mediaPlayer。

MediaPlayer的使用方式

創建MediaPlayer

可以直接 new MediaPlayer,也可以用MediaPlayer提供的create方法創建。

mediaPlayer = new MediaPlayer();

使用create方法創建成功后,mediaPlayer處於Prepared狀態。可以直接start播放。

    mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));
    mediaPlayer.start();

設置音源 - setDataSource

通過調用setDataSource來設置音源。setDataSource有多個重載方法,我們來看常用的幾種。

例如設置使用assets里的資源。實際情況可能需要try catch。

    AssetFileDescriptor fd = null;
    MediaPlayer mediaPlayer = new MediaPlayer();
    fd = context.getApplicationContext().getAssets().openFd(name);
    mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());

本地文件,需要文件的絕對路徑。

mediaPlayer.setDataSource(file.getAbsolutePath());

或者獲取文件的Uri來創建mediaPlayer。

mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));

設置網絡音頻,也是用setDataSource方法,設置url。

mediaPlayer.setDataSource("https://demo.com/sample.mp3"));

播放網絡音頻時,如果使用的是http,有可能會報錯

java.io.IOException: Cleartext HTTP traffic to demo.com not permitted

可以簡單地設置一下manifest,設置usesCleartextTraffic="true"

<application
        android:usesCleartextTraffic="true">

准備 - prepare

同步和異步准備音頻資源。prepareAsync()是異步的方式,prepare是同步的。注意線程調度問題,同時不要阻塞UI線程。

使用異步方式准備音頻,經常與MediaPlayer.OnPreparedListener監聽器配合使用。異步准備時,也可以進行其他的設置。

    mediaPlayer.prepareAsync();
    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mediaPlayer) {
            mediaPlayer.start(); // 准備好了就播放
        }
    });

循環播放 - Looping

設置循環播放setLooping。

mediaPlayer.setLooping(true);

播放完畢后,不會回調OnCompletionListener,而是從頭播放當前音頻。

播放 - start

播放音頻,調用start方法。

mediaPlayer.start();

處於Prepared,Pause和PlaybackComplete狀態時,可以調用start方法,進入Started狀態。

暫停 - pause

暫停播放,使用pause方法。在暫停前先判斷一下mediaPlayer的是否在播放。

    if (mediaPlayer.isPlaying()) {
        mediaPlayer.pause();
    }

暫停成功則處於Paused狀態。

停止 - stop

回顧一下MediaPlayer狀態切換的圖示,我們可以得知在播放中,暫停,播放完成這3個狀態下,可以調用stop方法,進入Stopped狀態。

mediaPlayer.stop();

調進度 - seekTo

調整播放進度。我們平時使用音樂播放軟件一般都會有這個功能。
seekTo方法接受一個毫秒參數。

    int targetMS = (int) (percent * mediaPlayer.getDuration());
    mediaPlayer.seekTo(targetMS);

seekTo並不會改變MediaPlayer的狀態。

重置 - reset

reset后的mediaPlayer進入Idle狀態。需要重新設置音源與准備。

釋放 - release

不再使用這個mediaPlayer時,應當盡快釋放掉,以釋放相關的資源。
調用release后,mediaPlayer進入End狀態。此時這個mediaPlayer就不能再使用了。

常用監聽器

緩沖監聽器 OnBufferingUpdateListener

比如我們加載網絡音頻的時候,常用這個監聽器來監聽緩沖進度。顯示緩沖進度,也可以提高用戶體驗。

    mMediaPlayer.prepareAsync();
    mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
        @Override
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
            // percent代表緩沖百分比
        }
    });

錯誤監聽器 OnErrorListener

mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
    @Override
    public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
        return true; // 返回true表示在此處理錯誤,不會回調onCompletion
    }
});

注意onError的返回值。可以選擇自己處理error。

         * @return True if the method handled the error, false if it didn't.
         * Returning false, or not having an OnErrorListener at all, will
         * cause the OnCompletionListener to be called.
         */
        boolean onError(MediaPlayer mp, int what, int extra);

播放完畢監聽器 OnCompletionListener

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        // 播放完畢
    }
});

使用示例

播放assets里的音頻

播放assets里的音頻文件,使用到AssetFileDescriptor類。使用后記得關閉AssetFileDescriptor。

    private void playAssetsAudio(final String name, Context context) {
        Log.d(TAG, "playAssetWordSound: try to play assets sound file. -> " + name);
        AssetFileDescriptor fd = null;
        try {
            MediaPlayer mediaPlayer;
            Log.v(TAG, "Looking in assets.");
            fd = context.getApplicationContext().getAssets().openFd(name);
            mediaPlayer = new MediaPlayer();
            mediaPlayer.reset();
            mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    Log.d(TAG, "onPrepared: " + name);
                    mediaPlayer.start();
                }
            });
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mp.release();
                    Log.d(TAG, "onCompletion: " + name);
                }
            });
            mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mp, int i, int i1) {
                    mp.release();
                    return true;
                }
            });
        } catch (Exception e) {
            try {
                if (fd != null) {
                    fd.close();
                }
            } catch (Exception e1) {
                Log.e(TAG, "Exception close fd: ", e1);
            }
        } finally {
            if (fd != null) {
                try {
                    fd.close();
                } catch (IOException e) {
                    Log.e(TAG, "Finally, close fd ", e);
                }
            }
        }
    }

播放本地音頻文件

嘗試播放音頻文件。僅播放一次。

    private void playAudioFile(final File file) {
        Log.d(TAG, "playAudioFile: " + file.getAbsolutePath());
        MediaPlayer mediaPlayer;
        try {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setLooping(false);
            mediaPlayer.setDataSource(file.getAbsolutePath());
            mediaPlayer.prepare();
            mediaPlayer.start();
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mp.release();
                }
            });
            mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
                    Log.d(TAG, "Play local sound onError: " + i + ", " + i1);
                    return true;
                }
            });
        } catch (Exception e) {
            Log.e(TAG, "playAudioFile: ", e);
        }
    }

播放在線音頻

設置url,播放在線音頻

    private void playOnlineSound(String soundUrlDict) {
        try {
            MediaPlayer mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(soundUrlDict);
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    mediaPlayer.start();
                }
            });
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    if (mp != null) {
                        mp.release();
                    }
                    Log.d(TAG, "onCompletion: play sound.");
                }
            });
            mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
                    Log.d(TAG, "Play online sound onError: " + i + ", " + i1);
                    return false;
                }
            });
        } catch (IOException e1) {
            Log.e(TAG, "url: ", e1);
        }
    }

代碼可以參考示例工程: https://github.com/RustFisher/android-MediaPlayer


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM