Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android應用開發入門(五十八)MediaPlayer介紹及使用

Android應用開發入門(五十八)MediaPlayer介紹及使用

編輯:Android開發實例

前言

  Android提供了常見的音頻、視頻的編碼、解碼機制。借助於多媒體類MediaPlayer的支持,開發人員可以很方便在在應用中播放音頻、視頻。本文主要講解在Android平台下如何播放一個音頻文件。

  本文主要內容如下:

  • MediaPlayer
  • MediaPlayer的音頻源
  • 使用MediaPlayer播放音樂
  • MediaPlayer使用技巧
  • Demo--一個簡單的MP3播放器

  

MediaPlayer

  上面提到過,Android下對於音頻、視頻的支持均需要使用到MediaPlayer,它主要用來控制Android下播放文件或流的類。MediaPlayer處於Android多媒體包下"android.media.MediaPlayer",僅有一個無參的構造函數,雖然僅為我們提供了一個無參的構造函數,為了方便我們初始化,還為我們提供了幾個靜態的create()方法用於完成MediaPlayer初始化的工作。

  • static MediaPlayer create(Context context,int resid):通過音頻資源的Id來創建一個MediaPlayer實例。
  • static MediaPlayer create(Context context,Uri uri):通過一個音頻資源的Uri地址來創建一個MediaPlayer實例。

  MediaPlayer除了通過上面兩個create()方法在初始化的時候指定媒體資源,還可以通過MediaPlayer.setDataSource()方法為初始化後的MediaPlayer設置媒體資源,setDataSource()具有多個重載函數,適用於不同的媒體資源來源,以下講解幾個常用的,其他的可以查閱官方文檔。

  • void setDataSource(String path):通過一個媒體資源的地址指定MediaPlayer的數據源,這裡的path可以是一個本地路徑,也可以是網絡路徑。
  • void setDataSource(Context context,Uri uri):通過一個Uri指定MediaPlayer的數據源,這裡的Uri可以是網絡路徑或這一個內容提供者的Uri。
  • void setDataSource(FileDescriptor fd):通過一個FileDescriptor指定一個MediaPlayer的數據源。

 

MediaPlayer的音頻源

  通過上面介紹的初始化MediaPlayer的播放時媒體數據源的方法可以看出,MediaPlayer支持的數據源有:本地文件、內部的Uri(內容提供者)、外部Uri。

  如,設置一個本地SD卡的資源:

  1. mediaPlayer = new MediaPlayer();  
  2. mediaPlayer.setDataSource("/sdcarc/a.mp3"); 

  注意讀內存卡,還需要設定訪問內存卡的權限:

  1. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> 

  如,設置一個外部uri的網絡流媒體資源:

  1. mediaPlayer = new MediaPlayer();  
  2. mediaPlayer.setDataSource(http://192.168.1.102:1231/music/a.mp3); 

  如果訪問網絡流媒體資源,還需要設置訪問網絡的權限:

  1. <uses-permission android:name="android.permission.INTERNET"/> 

 

使用MediaPlayer播放音樂

  MediaPlayer其實是一個封裝的很好的音頻、視頻流媒體操作類,如果查看其源碼,會發現其內部是調用的native方法,所以它其實是有C++實現的。

  既然是一個流媒體操作類,那麼必然涉及到,播放、暫停、停止等操作,實際上MediaPlayer也為我們提供了相應的方法來直接操作流媒體。

  • void statr():開始或恢復播放。
  • void stop():停止播放。
  • void pause():暫停播放。  

  通過上面三個方法,只要設定好流媒體數據源,即可在應用中播放流媒體資源,為了更好的操作流媒體,MediaPlayer還為我們提供了一些其他的方法,這裡列出一些常用的,詳細內容參閱官方文檔。

  • int getDuration():獲取流媒體的總播放時長,單位是毫秒。
  • int getCurrentPosition():獲取當前流媒體的播放的位置,單位是毫秒。
  • void seekTo(int msec):設置當前MediaPlayer的播放位置,單位是毫秒。
  • void setLooping(boolean looping):設置是否循環播放。
  • boolean isLooping():判斷是否循環播放。
  • boolean  isPlaying():判斷是否正在播放。
  • void prepare():同步的方式裝載流媒體文件。
  • void prepareAsync():異步的方式裝載流媒體文件。
  • void release ():回收流媒體資源。 
  • void setAudioStreamType(int streamtype):設置播放流媒體類型。
  • void setWakeMode(Context context, int mode):設置CPU喚醒的狀態。
  • setNextMediaPlayer(MediaPlayer next):設置當前流媒體播放完畢,下一個播放的MediaPlayer。

  大部分方法的看方法名就可以理解,但是有幾個方法需要單獨說明一下。

  在使用MediaPlayer播放一段流媒體的時候,需要使用prepare()或prepareAsync()方法把流媒體裝載進MediaPlayer,才可以調用start()方法播放流媒體。                 

  setAudioStreamType()方法用於指定播放流媒體的類型,它傳遞的是一個int類型的數據,均以常量定義在AudioManager類中, 一般我們播放音頻文件,設置為AudioManager.STREAM_MUSIC即可。

  

  除了上面介紹的一些方法外,MediaPlayer還提供了一些事件的回調函數,這裡介紹幾個常用的:

  • setOnCompletionListener(MediaPlayer.OnCompletionListener listener):當流媒體播放完畢的時候回調。
  • setOnErrorListener(MediaPlayer.OnErrorListener listener):當播放中發生錯誤的時候回調。
  • setOnPreparedListener(MediaPlayer.OnPreparedListener listener):當裝載流媒體完畢的時候回調。
  • setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener):當使用seekTo()設置播放位置的時候回調。

MediaPlayer使用技巧

  在使用MediaPlayer的使用過程中,有個小技巧需要說明一下:

  1、在使用start()播放流媒體之前,需要裝載流媒體資源。這裡最好使用prepareAsync()用異步的方式裝載流媒體資源。因為流媒體資源的裝載是會消耗系統資源的,在一些硬件不理想的設備上,如果使用prepare()同步的方式裝載資源,可能會造成UI界面的卡頓,這是非常影響用於體驗的。因為推薦使用異步裝載的方式,為了避免還沒有裝載完成就調用start()而報錯的問題,需要綁定MediaPlayer.setOnPreparedListener()事件,它將在異步裝載完成之後回調。異步裝載還有一個好處就是避免裝載超時引發ANR((Application Not Responding)錯誤。

  1. mediaPlayer = new MediaPlayer();  
  2.                 mediaPlayer.setDataSource(path);  
  3.                 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  
  4.                   
  5.                 // 通過異步的方式裝載媒體資源  
  6.                 mediaPlayer.prepareAsync();  
  7.                 mediaPlayer.setOnPreparedListener(new OnPreparedListener() {                      
  8.                     @Override 
  9.                     public void onPrepared(MediaPlayer mp) {  
  10.                         // 裝載完畢回調  
  11.                         mediaPlayer.start();  
  12.                     }  
  13.                 }); 

  2、使用完MediaPlayer需要回收資源。MediaPlayer是很消耗系統資源的,所以在使用完MediaPlayer,不要等待系統自動回收,最好是主動回收資源。

  1. if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  2.     mediaPlayer.stop();  
  3.     mediaPlayer.release();  
  4.     mediaPlayer = null;  
  5. }  

  3、使用MediaPlayer最好使用一個Service來使用,並且在Service的onDestory()方法中回收MediaPlayer資源,實際上,就算是直接使用Activity承載MediaPlayer,也最好在銷毀的時候判斷一下MediaPlayer是否被回收,如果未被回收,回收其資源,因為底層調用的native方法,如果不銷毀還是會在底層繼續播放,而承載的組件已經被銷毀了,這個時候就無法獲取到這個MediaPlayer進而控制它。

  1. @Override 
  2.     protected void onDestroy() {  
  3.         if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  4.             mediaPlayer.stop();  
  5.             mediaPlayer.release();  
  6.             mediaPlayer = null;  
  7.         }  
  8.         super.onDestroy();  
  9.     } 

  4、對於單曲循環之類的操作,除了可以使用setLooping()方法進行設置之外,還可以為MediaPlayer注冊回調函數,MediaPlayer.setOnCompletionListener(),它會在MediaPlayer播放完畢被回調。

  1. // 設置循環播放  
  2. //                mediaPlayer.setLooping(true);  
  3.                 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {  
  4.                       
  5.                     @Override 
  6.                     public void onCompletion(MediaPlayer mp) {  
  7.                         // 在播放完畢被回調  
  8.                         play();                          
  9.                     }  
  10.                 }); 

  5、因為MediaPlayer一直操作的是一個流媒體,所以無可避免的可能一段流媒體資源,前半段可以正常播放,而中間一段因為解析或者源文件錯誤等問題,造成中間一段無法播放問題,需要我們處理這個錯誤,否則會影響Ux(用戶體驗)。可以為MediaPlayer注冊回調函數setOnErrorListener()來設置出錯之後的解決辦法,一般重新播放或者播放下一個流媒體即可。 

  1. mediaPlayer.setOnErrorListener(new OnErrorListener() {  
  2.                       
  3.                     @Override 
  4.                     public boolean onError(MediaPlayer mp, int what, int extra) {  
  5.                         play();  
  6.                         return false;  
  7.                     }  
  8.                 }); 

 

Demo--一個簡單的MP3播放器

  上面已經介紹了MediaPlayer播放一段音頻文件的所有需要用到的內容。下面通過一個簡單的Demo來演示如何使用MediaPlayer播放一個SD卡上的MP3文件。操作MediaPlayer應該放在Service中完成,這裡為了簡單,使用Activity直接操作MediaPlayer。代碼注釋裡寫的很清楚裡,這裡不再累述。

  執行這個示例需要在/sdcard/目錄下存在xm.mp3的文件。 

  1. package cn.bgxt.mediaplayerdemo;  
  2.  
  3. import java.io.File;  
  4. import android.media.AudioManager;  
  5. import android.media.MediaPlayer;  
  6. import android.media.MediaPlayer.OnCompletionListener;  
  7. import android.media.MediaPlayer.OnErrorListener;  
  8. import android.media.MediaPlayer.OnPreparedListener;  
  9. import android.os.Bundle;  
  10. import android.app.Activity;  
  11. import android.view.View;  
  12. import android.widget.Button;  
  13. import android.widget.EditText;  
  14. import android.widget.Toast;  
  15.  
  16. public class MainActivity extends Activity {  
  17.     private EditText et_path;  
  18.     private Button btn_play, btn_pause, btn_replay, btn_stop;  
  19.     private MediaPlayer mediaPlayer;  
  20.  
  21.     @Override 
  22.     protected void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.activity_main);  
  25.  
  26.         et_path = (EditText) findViewById(R.id.et_path);  
  27.         btn_play = (Button) findViewById(R.id.btn_play);  
  28.         btn_pause = (Button) findViewById(R.id.btn_pause);  
  29.         btn_replay = (Button) findViewById(R.id.btn_replay);  
  30.         btn_stop = (Button) findViewById(R.id.btn_stop);  
  31.  
  32.         btn_play.setOnClickListener(click);  
  33.         btn_pause.setOnClickListener(click);  
  34.         btn_replay.setOnClickListener(click);  
  35.         btn_stop.setOnClickListener(click);  
  36.     }  
  37.  
  38.     private View.OnClickListener click = new View.OnClickListener() {  
  39.  
  40.         @Override 
  41.         public void onClick(View v) {  
  42.  
  43.             switch (v.getId()) {  
  44.             case R.id.btn_play:  
  45.                 play();  
  46.                 break;  
  47.             case R.id.btn_pause:  
  48.                 pause();  
  49.                 break;  
  50.             case R.id.btn_replay:  
  51.                 replay();  
  52.                 break;  
  53.             case R.id.btn_stop:  
  54.                 stop();  
  55.                 break;  
  56.             default:  
  57.                 break;  
  58.             }  
  59.         }  
  60.     };  
  61.     /**  
  62.      * 播放音樂  
  63.      */ 
  64.     protected void play() {  
  65.         String path = et_path.getText().toString().trim();  
  66.         File file = new File(path);  
  67.         if (file.exists() && file.length() > 0) {  
  68.             try {  
  69.                 mediaPlayer = new MediaPlayer();  
  70.                 // 設置指定的流媒體地址  
  71.                 mediaPlayer.setDataSource(path);  
  72.                 // 設置音頻流的類型  
  73.                 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  
  74.  
  75.                 // 通過異步的方式裝載媒體資源  
  76.                 mediaPlayer.prepareAsync();  
  77.                 mediaPlayer.setOnPreparedListener(new OnPreparedListener() {  
  78.                     @Override 
  79.                     public void onPrepared(MediaPlayer mp) {  
  80.                         // 裝載完畢 開始播放流媒體  
  81.                         mediaPlayer.start();  
  82.                         Toast.makeText(MainActivity.this, "開始播放", 0).show();  
  83.                         // 避免重復播放,把播放按鈕設置為不可用  
  84.                         btn_play.setEnabled(false);  
  85.                     }  
  86.                 });  
  87.                 // 設置循環播放  
  88.                 // mediaPlayer.setLooping(true);  
  89.                 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {  
  90.  
  91.                     @Override 
  92.                     public void onCompletion(MediaPlayer mp) {  
  93.                         // 在播放完畢被回調  
  94.                         btn_play.setEnabled(true);  
  95.                     }  
  96.                 });  
  97.  
  98.                 mediaPlayer.setOnErrorListener(new OnErrorListener() {  
  99.  
  100.                     @Override 
  101.                     public boolean onError(MediaPlayer mp, int what, int extra) {  
  102.                         // 如果發生錯誤,重新播放  
  103.                         replay();  
  104.                         return false;  
  105.                     }  
  106.                 });  
  107.             } catch (Exception e) {  
  108.                 e.printStackTrace();  
  109.                 Toast.makeText(this, "播放失敗", 0).show();  
  110.             }  
  111.         } else {  
  112.             Toast.makeText(this, "文件不存在", 0).show();  
  113.         }  
  114.  
  115.     }  
  116.     /**  
  117.      * 暫停  
  118.      */ 
  119.     protected void pause() {  
  120.         if (btn_pause.getText().toString().trim().equals("繼續")) {  
  121.             btn_pause.setText("暫停");  
  122.             mediaPlayer.start();  
  123.             Toast.makeText(this, "繼續播放", 0).show();  
  124.             return;  
  125.         }  
  126.         if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  127.             mediaPlayer.pause();  
  128.             btn_pause.setText("繼續");  
  129.             Toast.makeText(this, "暫停播放", 0).show();  
  130.         }  
  131.  
  132.     }  
  133.       
  134.     /**  
  135.      * 重新播放  
  136.      */ 
  137.     protected void replay() {  
  138.         if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  139.             mediaPlayer.seekTo(0);  
  140.             Toast.makeText(this, "重新播放", 0).show();  
  141.             btn_pause.setText("暫停");  
  142.             return;  
  143.         }          
  144.         play();  
  145.     }  
  146.       
  147.     /**  
  148.      * 停止播放  
  149.      */ 
  150.     protected void stop() {  
  151.         if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  152.             mediaPlayer.stop();  
  153.             mediaPlayer.release();  
  154.             mediaPlayer = null;  
  155.             btn_play.setEnabled(true);  
  156.             Toast.makeText(this, "停止播放", 0).show();  
  157.         }  
  158.  
  159.     }  
  160.  
  161.     @Override 
  162.     protected void onDestroy() {  
  163.         // 在activity結束的時候回收資源  
  164.         if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  165.             mediaPlayer.stop();  
  166.             mediaPlayer.release();  
  167.             mediaPlayer = null;  
  168.         }  
  169.         super.onDestroy();  
  170.     }  

 

  效果展示:

 

  源碼下載

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved