Android平台播放音频的方式一般有3种。1.利用系统内置的应用程序播放音频    2.利用AudioTrack播放原始音频   3.使用MediaPlayer播放。此3种音频播放方式,以第三种MediaPlayer播放这种方式使用的最多,必须掌握!

一、使用系统内置的程序。

Google想的“周到”,一般都给我们提供了一些内置程序,然而这些内置程序的UI效果,那真是感人啊!一般内置程序,我们就是看看而已。

 

[java]  view plain  copy

 

1. Intent intent=new Intent(Intent.ACTION_VIEW);  
2. intent.setDataAndType(url,type); //eg:intent.setDataAndType(url,“audio/mp3”);  url音频文件路径  
3. startActivity(intent);



二、使用AudioTrack播放音频:只能播放原始的PCM数据,通过callback函数一直写入HW。实际上MediaPlayer也是通过AudioTrack来播放音频的

 在NuPlayer有一个mAudioSink,实际是AudioOutput类型,内部有一个AudioTrack,用来播放解码后的PCM数据

AudioTrack只能用来播放原始音频(PCM)

[java]  view plain  copy

 

1. //播放音频(PCM)  
2. public void play()  
3.     {     
4. null;  
5. try {  
6. //从音频文件中读取声音  
7. new DataInputStream(new BufferedInputStream(new FileInputStream(recordingFile)));  
8. catch (FileNotFoundException e) {  
9.               e.printStackTrace();  
10.             }  
11. //最小缓存区  
12. int bufferSizeInBytes=AudioTrack.getMinBufferSize(sampleRateInHz,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);  
13. //创建AudioTrack对象   依次传入 :流类型、采样率(与采集的要一致)、音频通道(采集是IN 播放时OUT)、量化位数、最小缓冲区、模式  
14. new AudioTrack(AudioManager.STREAM_MUSIC,sampleRateInHz,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes, AudioTrack.MODE_STREAM);  
15.           
16. byte[] data =new byte [bufferSizeInBytes];  
17. //开始播放  
18. while(true)  
19.         {  
20. int i=0;  
21. try {  
22. while(dis.available()>0&&i<data.length)  
23.                 {  
24. //录音时write Byte 那么读取时就该为readByte要相互对应  
25.                   i++;  
26.                 }  
27. catch (IOException e) {  
28. // TODO Auto-generated catch block  
29.                 e.printStackTrace();  
30.             }  
31. 0,data.length);  
32.               
33. if(i!=bufferSizeInBytes) //表示读取完了  
34.             {  
35. //停止播放  
36. //释放资源  
37. break;  
38.             }  
39.         }  
40.           
41.     }


这里是播放PCM的关键代码,完整Demo在本文的末尾会给出相应的链接!主要是从文件中读取数据到数组中,然后写到AudiotTrack之中,然后AudioTrack就会将其播放,利i!=bufferSizeInBytes 判断其读取完了(文件的末尾)。

 

三、使用MediaPlayer进行音频播放。——这个是播放多媒体的,包括audio和 video

MediaPlayer是很强大的一个Android系统内置的类,它不仅可以播放音频同时还可以播放视频。最常见的方法有:

start()开始播放        pause()暂停播放    stop()停止播放       prepareAsync() /prepare()  开始准备     

getCurrentPosition() 当前播放的位置         getDuration()文件总的时长      seekTo (int position)定位播放

示例代码 演示利用MediaPlayer和Seekbar进行音频 的播放 、暂停、拖动快进播放等 。效果如图:(具体完整代码在备注里面可下载MediaPlayerDemo)

android 如何查看pcm文件 android 播放pcm_android 如何查看pcm文件

布局文件:

[html]  view plain  copy

 

1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
2. xmlns:tools="http://schemas.android.com/tools"  
3. android:layout_width="match_parent"  
4. android:layout_height="match_parent"  
5. android:background="@drawable/background"  
6. tools:context="${relativePackage}.${activityClass}" >  
7.   
8. <TextView   
9. android:layout_width="wrap_content"  
10. android:layout_height="wrap_content"  
11. android:text="天空之城主题曲(宫崎骏)"  
12. android:textColor="#F8F8F8"  
13. android:textSize="18sp"  
14. android:ellipsize="marquee"  
15. android:layout_centerInParent="true"  
16. />  
17.       
18. <LinearLayout   
19. android:layout_width="match_parent"  
20. android:layout_height="wrap_content"  
21. android:layout_marginLeft="5dp"  
22. android:layout_marginRight="5dp"  
23. android:layout_marginBottom="5dp"  
24. android:layout_above="@+id/bottom"  
25. android:gravity="center_vertical"  
26. >  
27.      
28. <TextView  
29. android:id="@+id/left"  
30. android:layout_width="wrap_content"  
31. android:layout_height="wrap_content"  
32. android:text="00:00"  
33. android:textColor="#F8F8F8"  
34. />  
35.       
36. <SeekBar   
37. android:id="@+id/seek"  
38. android:layout_width="match_parent"  
39. android:layout_height="wrap_content"  
40. android:layout_weight="1"  
41. android:enabled="false"  
42. />  
43.      
44. <TextView  
45. android:id="@+id/right"  
46. android:layout_width="wrap_content"  
47. android:layout_height="wrap_content"  
48. android:text="00:00"  
49. android:textColor="#F8F8F8"  
50. />  
51.       
52. </LinearLayout>  
53.       
54. <LinearLayout  
55. android:id="@+id/bottom"  
56. android:layout_width="match_parent"  
57. android:layout_height="wrap_content"  
58. android:layout_alignParentBottom="true"  
59. android:layout_marginBottom="5dp"  
60. android:orientation="horizontal" >  
61.           
62. <Button  
63. android:id="@+id/start"   
64. android:layout_width="0dp"  
65. android:layout_height="wrap_content"  
66. android:layout_weight="1"  
67. android:text="播放"  
68. android:textColor="#F8F8F8"  
69. android:textSize="14sp"  
70. android:enabled="false"  
71. />  
72.           
73. <Button  
74. android:id="@+id/stop"   
75. android:layout_width="0dp"  
76. android:layout_height="wrap_content"  
77. android:layout_weight="1"  
78. android:text="暂停"  
79. android:textSize="14sp"  
80. android:textColor="#F8F8F8"  
81. android:enabled="false"  
82. />  
83.           
84. </LinearLayout>  
85.       
86. </RelativeLayout>


 

初始化MediaPlayer

 

[java]  view plain  copy

 

1.       mAssetManager=getAssets();  
2. try {  
3. "sky.mp3");// 创建天空之城的AssetFileDescriptor文件  
4. catch (IOException e) {  
5.     e.printStackTrace();  
6. "创建AssetFileDescriptor 异常 ,请查看根福是否存在");  
7. }  
8. mMediaPlayer=new MediaPlayer();  
9. try {  
10. //设置播放源 ,当然还有其他的重载方法 eg:setDataSource(String path) path可以使网络路径也可以是本地路径,网络的记得加权限  
11.     mMediaPlayer.setDataSource(afd.getFileDescriptor());   
12. } catch (Exception e) {  
13.     e.printStackTrace();  
14. "设置播放源异常" );  
15. }  
16. mMediaPlayer.prepareAsync(); //MediaPlayer 开始准备  异步的, 还有prepare()这个是同步的
  1.   

MediaPlayer设置相应的监听器

 

[java]  view plain  copy

 

1. seek.setMax(100);//设置长度100  
2. seek.setOnSeekBarChangeListener(this);//设置Seekbar的滑动监听器  
3. mMediaPlayer.setOnPreparedListener(this);//设置准备就绪监听  
4. mMediaPlayer.setOnCompletionListener(this);//设置播放完成


[java]  view plain  copy

 

1. //结束滑动时     
2. @Override  
3. public void onStopTrackingTouch(SeekBar seekBar) {  
4. int a=(int)((sum/100.0)*(seekBar.getProgress()));  
5. //seekTo方法接收的单位是:毫秒  
6. //更新seekBar  
7. }


[java]  view plain  copy

 

1. @Override  
2. public void onPrepared(MediaPlayer mp) {  
3. //准备就绪完成  
4. true);  
5. true);  
6. true);  
7.         sum=mMediaPlayer.getDuration();  
8. 1000));  }


[java]  view plain  copy

 

1. //播放完成  
2. @Override  
3. public void onCompletion(MediaPlayer mp) {  
4. "播放");  
5. 0);  
6. 0);  
7. }


Handler 更新SeekBar的状态:

[java]  view plain  copy

 

1. private Handler handler=new Handler()  
2.    {  
3. @Override  
4. public void handleMessage(Message msg) {  
5. switch (msg.what) {  
6. case 1:{  
7. int current=mMediaPlayer.getCurrentPosition();// 得到数值的单位是毫秒  
8. int prass=(int)(current/(sum*1.0)*100);  
9. 1000));  
10.                 seek.setProgress(prass);  
11. if(!pause)  
12.                 {  
13. 1,1000);//1 秒后继续更新  
14.                 }  
15. break;  
16.             }  
17.               
18. case 0:{  
19. //停止更新  
20. true;  
21. break;  
22.             }  
23. default:  
24. break;  
25.         }  
26.     }  
27.       
28.    };


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 如何查看pcm文件 android 播放pcm_android_02

 

 

 

四、备注:

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

MediaPlayerDemo(利用MediaPlayer播放音频)