Android 音频播放

宝剑锋从磨砺出,梅花香自苦寒来。这篇文章主要讲述Android 音频播放相关的知识,希望能为你提供帮助。
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 =https://www.songbingjia.com/android/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)
Android 音频播放

文章图片


布局文件:
< 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状态及方法流程图:
Android 音频播放

文章图片







四、备注:
AudioTrack播放PCMDemo  如果对Demo中音频采集不熟悉,可以查阅  Android 音频采集

MediaPlayerDemo(利用MediaPlayer播放音频)



【Android 音频播放】










    推荐阅读