一、使用系統內置的程序。
Google想的“周到”,一般都給我們提供了一些內置程序,然而這些內置程序的UI效果,那真是感人啊!一般內置程序,我們就是看看而已。
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(url,type); //eg:intent.setDataAndType(url,“audio/mp3”); url音頻文件路徑
startActivity(intent);
二、使用AudioTrack播放音頻
AudioTrack只能用來播放原始音頻(PCM)
//播放音頻(PCM)
public void play()
{
DataInputStream dis=null;
try {
//從音頻文件中讀取聲音
dis=new DataInputStream(new BufferedInputStream(new FileInputStream(recordingFile)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//最小緩存區
int bufferSizeInBytes=AudioTrack.getMinBufferSize(sampleRateInHz,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);
//創建AudioTrack對象 依次傳入 :流類型、採樣率(與採集的要一致)、音頻通道(採集是IN 播放時OUT)、量化位數、最小緩衝區、模式
player=new AudioTrack(AudioManager.STREAM_MUSIC,sampleRateInHz,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes, AudioTrack.MODE_STREAM);
byte[] data =new byte [bufferSizeInBytes];
player.play();//開始播放
while(true)
{
int i=0;
try {
while(dis.available()>0&&i<data.length)
{
data[i]=dis.readByte();//錄音時write Byte 那麼讀取時就該爲readByte要相互對應
i++;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
player.write(data,0,data.length);
if(i!=bufferSizeInBytes) //表示讀取完了
{
player.stop();//停止播放
player.release();//釋放資源
break;
}
}
}
這裏是播放PCM的關鍵代碼,完整Demo在本文的末尾會給出相應的鏈接!主要是從文件中讀取數據到數組中,然後寫到AudiotTrack之中,然後AudioTrack就會將其播放,利i!=bufferSizeInBytes 判斷其讀取完了(文件的末尾)。
三、使用MediaPlayer進行音頻播放。
MediaPlayer是很強大的一個android系統內置的類,它不僅可以播放音頻同時還可以播放視頻。最常見的方法有:
start()開始播放 pause()暫停播放 stop()停止播放 prepareAsync() /prepare() 開始準備
getCurrentPosition() 當前播放的位置 getDuration()文件總的時長 seekTo (int position)定位播放
示例代碼 演示利用MediaPlayer和Seekbar進行音頻 的播放 、暫停、拖動快進播放等 。效果如圖:(具體完整代碼在備註裏面可下載MediaPlayerDemo)
佈局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
tools:context="${relativePackage}.${activityClass}" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="天空之城主題曲(宮崎駿)"
android:textColor="#F8F8F8"
android:textSize="18sp"
android:ellipsize="marquee"
android:layout_centerInParent="true"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:layout_above="@+id/bottom"
android:gravity="center_vertical"
>
<TextView
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="#F8F8F8"
/>
<SeekBar
android:id="@+id/seek"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false"
/>
<TextView
android:id="@+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="#F8F8F8"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="5dp"
android:orientation="horizontal" >
<Button
android:id="@+id/start"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="播放"
android:textColor="#F8F8F8"
android:textSize="14sp"
android:enabled="false"
/>
<Button
android:id="@+id/stop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="暫停"
android:textSize="14sp"
android:textColor="#F8F8F8"
android:enabled="false"
/>
</LinearLayout>
</RelativeLayout>
初始化MediaPlayer
mAssetManager=getAssets();
try {
afd=mAssetManager.openFd("sky.mp3");// 創建天空之城的AssetFileDescriptor文件
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,"創建AssetFileDescriptor 異常 ,請查看根福是否存在");
}
mMediaPlayer=new MediaPlayer();
try {
//設置播放源 ,當然還有其他的重載方法 eg:setDataSource(String path) path可以使網絡路徑也可以是本地路徑,網絡的記得加權限
mMediaPlayer.setDataSource(afd.getFileDescriptor());
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG,"設置播放源異常" );
}
mMediaPlayer.prepareAsync(); //MediaPlayer 開始準備 異步的, 還有prepare()這個是同步的
MediaPlayer設置相應的監聽器
seek.setMax(100);//設置長度100
seek.setOnSeekBarChangeListener(this);//設置Seekbar的滑動監聽器
mMediaPlayer.setOnPreparedListener(this);//設置準備就緒監聽
mMediaPlayer.setOnCompletionListener(this);//設置播放完成
//結束滑動時
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int a=(int)((sum/100.0)*(seekBar.getProgress()));
mMediaPlayer.seekTo(a); //seekTo方法接收的單位是:毫秒
handler.sendEmptyMessage(START); //更新seekBar
}
@Override
public void onPrepared(MediaPlayer mp) {
//準備就緒完成
start.setEnabled(true);
stop.setEnabled(true);
seek.setEnabled(true);
sum=mMediaPlayer.getDuration();
right.setText(FormatTime(sum/1000)); }
//播放完成
@Override
public void onCompletion(MediaPlayer mp) {
start.setText("播放");
seek.setProgress(0);
mMediaPlayer.seekTo(0);
}
Handler 更新SeekBar的狀態: private Handler handler=new Handler()
{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:{
int current=mMediaPlayer.getCurrentPosition();// 得到數值的單位是毫秒
int prass=(int)(current/(sum*1.0)*100);
left.setText(FormatTime(current/1000));
seek.setProgress(prass);
if(!pause)
{
handler.sendEmptyMessageDelayed(1,1000);//1 秒後繼續更新
}
break;
}
case 0:{
//停止更新
pause=true;
break;
}
default:
break;
}
}
};
1.比較容易讓人混淆的是pause方法和stop方法的區別:2個方法都可以讓音頻停止。
調用Pause方法後想再次聽見聲音直接調用start方法之後即可。調用stop方法停止音頻之後,再次調用start方法之後不會播放,要先調用prepareAsync或者prepare方法,之後在public void onPrepared(MediaPlayer mp)回調方法裏面調用start方法纔會播放。
2.start方法要在準備就緒,即在public void onPrepared(MediaPlayer mp)裏面回調。
3.不使用MediaPlayer時記得stop,然後release 釋放相關的資源。(本例在Activity的OnDestroy方法中調用的)
下圖是MediaPlayer狀態及方法流程圖:
四、備註:
AudioTrack播放PCMDemo 如果對Demo中音頻採集不熟悉,可以查閱 Android
音頻採集
MediaPlayerDemo(利用MediaPlayer播放音頻)