http://blog.csdn.net/java_android_c/article/details/52678265html
Android平臺播放音頻的方式通常有3種。1.利用系統內置的應用程序播放音頻 2.利用AudioTrack播放原始音頻 3.使用MediaPlayer播放。此3種音頻播放方式,以第三種MediaPlayer播放這種方式使用的最多,必須掌握!java
1、使用系統內置的程序。android
Google想的「周到」,通常都給咱們提供了一些內置程序,然而這些內置程序的UI效果,那真是感人啊!通常內置程序,咱們就是看看而已。數組
- Intent intent=new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(url,type);
- startActivity(intent);
2、使用AudioTrack播放音頻:只能播放原始的PCM數據,經過callback函數一直寫入HW。實際上MediaPlayer也是經過AudioTrack來播放音頻的緩存
在NuPlayer有一個mAudioSink,實際是AudioOutput類型,內部有一個AudioTrack,用來播放解碼後的PCM數據網絡
AudioTrack只能用來播放原始音頻(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);
-
- 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();
- i++;
- }
- } catch (IOException e) {
-
- e.printStackTrace();
- }
- player.write(data,0,data.length);
-
- if(i!=bufferSizeInBytes)
- {
- player.stop();
- player.release();
- break;
- }
- }
-
- }
這裏是播放PCM的關鍵代碼,完整Demo在本文的末尾會給出相應的連接!主要是從文件中讀取數據到數組中,而後寫到AudiotTrack之中,而後AudioTrack就會將其播放,利i!=bufferSizeInBytes 判斷其讀取完了(文件的末尾)。ide
3、使用MediaPlayer進行音頻播放。——這個是播放多媒體的,包括audio和 video函數
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");
- } catch (IOException e) {
- e.printStackTrace();
- Log.e(TAG,"建立AssetFileDescriptor 異常 ,請查看根福是否存在");
- }
- mMediaPlayer=new MediaPlayer();
- try {
-
- mMediaPlayer.setDataSource(afd.getFileDescriptor());
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG,"設置播放源異常" );
- }
- mMediaPlayer.prepareAsync();
MediaPlayer設置相應的監聽器
- seek.setMax(100);
- seek.setOnSeekBarChangeListener(this);
- mMediaPlayer.setOnPreparedListener(this);
- mMediaPlayer.setOnCompletionListener(this);
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- int a=(int)((sum/100.0)*(seekBar.getProgress()));
- mMediaPlayer.seekTo(a);
- handler.sendEmptyMessage(START);
- }
- @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);
- }
- 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狀態及方法流程圖:
4、備註:
AudioTrack播放PCMDemo 若是對Demo中音頻採集不熟悉,能夠查閱 Android 音頻採集
MediaPlayerDemo(利用MediaPlayer播放音頻)