Android 音頻播放

來源:互聯網
上載者:User

標籤:

Android平台播放音訊方式一般有3種。1.利用系統內建的應用程式播放音頻    2.利用AudioTrack播放原始音頻   3.使用MediaPlayer播放。此3種音頻播放方式,以第三種MediaPlayer播放這種方式使用的最多,必須掌握!

一、使用系統內建的程式。

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 blocke.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);//設定播放完成
 //結束滑動時   @Overridepublic 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));  }
 //播放完成@Overridepublic void onCompletion(MediaPlayer mp) {start.setText("播放");seek.setProgress(0);mMediaPlayer.seekTo(0);}
Handler 更新SeekBar的狀態:
 private Handler handler=new Handler()    {@Overridepublic 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播放音頻)


Android 音頻播放

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.