Android 音频播放

来源:互联网 发布:淘宝妈妈装上衣 编辑:程序博客网 时间:2024/06/05 11:10
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播放音频)


2 2
原创粉丝点击