Android Audio 简述 简单点MediaPlayer,复杂点……不会啊T^T,怎么办! 一、 MediaPlayer

在package android.media包内,MediaPlayer的API说明得很详细了^^。摘张图过来:

另外,在其Valid and invalid states一节中列了张表格,详细的描述了MediaPlayer各方法在各状态下是否有效。(就不摘过来了^^) 二、音乐播放器 MediaPlayer控制音乐文件播放的简易实现,就是控制上图的流程^^。 1 )播放控制接口 定义了播放器基本模式、状态及控制操作方法。
        
  1. publicinterfaceIPlayer{
  2. //播放模式
  3. enumPlayMode{
  4. ONCE,CYCLE
  5. }
  6. //播放状态
  7. enumStatus{
  8. PLAYING,STOPPED,PAUSING
  9. };
  10. //获得当前播放模式
  11. PlayModegetMode();
  12. //设置当前播放模式
  13. voidsetMode(PlayModemode);
  14. //获得当前播放状态
  15. StatusgetStatus();
  16. //指向上一首音乐
  17. Fileprev();
  18. //指向下一首音乐
  19. Filenext();
  20. //播放当前音乐
  21. booleanplay();
  22. //暂停当前音乐
  23. booleanpause();
  24. //恢复播放音乐
  25. booleanresume();
  26. //停止当前音乐
  27. booleanstop();
  28. //释放资源
  29. voidrelease();
  30. }
2 )文件列表控件 自定义的ListView控件,主要实现功能如下: 1. 异步搜索/ mnt/ sdcard/music/目录下所有mp3文件 2. 以自定义适配器方式,使得选中的Item保持高亮背景色 3 )文件列表播放器 用MediaPlayer实现了IPlayer播放控制接口。
        
  1. publicclassFileListViewPlayerimplementsIPlayer,
  2. AdapterView.OnItemClickListener{
  3. privateMediaPlayermMediaPlayer;//MediaPlayer对象
  4. privateFileListViewmFileListView;//FileListView组件
  5. privateArrayList<File>musicFileList;//音乐文件列表
  6. privateintindex=0;//当前索引
  7. privatePlayModemPlayMode=PlayMode.CYCLE;//播放模式
  8. privateStatusmStatus=Status.STOPPED;//播放状态
  9. privateOnMusicClickListenerlistener;//音乐文件点击监听
  10. //音乐点击事件监听接口
  11. publicinterfaceOnMusicClickListener{
  12. //返回true及时播放,false则不及时播放
  13. booleanonMusicClick(FilemusicFile);
  14. }
  15. publicFileListViewPlayer(FileListViewfileListView){
  16. this.mFileListView=fileListView;
  17. fileListView.setOnItemClickListener(this);//设置Item点击时间监听
  18. mMediaPlayer=newMediaPlayer();//创建MediaPlayer对象
  19. }
  20. //是否有音乐
  21. privatebooleanhasMusic(){
  22. musicFileList=mFileListView.getMusicFileList();
  23. return(null!=musicFileList&&musicFileList.size()>=1);
  24. }
  25. //选中某项&设置索引
  26. privatevoidsetSelection(intposition){
  27. mFileListView.setSelectItem(position);//选中position
  28. index=position;//指向position
  29. }
  30. @Override
  31. publicPlayModegetMode(){
  32. returnmPlayMode;
  33. }
  34. @Override
  35. publicvoidsetMode(PlayModemode){
  36. this.mPlayMode=mode;
  37. }
  38. @Override
  39. publicStatusgetStatus(){
  40. returnmStatus;
  41. }
  42. @Override
  43. publicFileprev(){
  44. if(hasMusic()){
  45. intlocation=index-1>=0?index-1
  46. :musicFileList.size()-1;
  47. setSelection(location);
  48. returnmusicFileList.get(location);
  49. }
  50. returnnull;
  51. }
  52. @Override
  53. publicFilenext(){
  54. if(hasMusic()){
  55. intlocation=index+1<musicFileList.size()?index+1:0;
  56. setSelection(location);
  57. returnmusicFileList.get(location);
  58. }
  59. returnnull;
  60. }
  61. @Override
  62. publicbooleanplay(){
  63. if(mStatus!=Status.STOPPED||!hasMusic()){
  64. returnfalse;
  65. }
  66. try{
  67. mMediaPlayer.reset();
  68. mMediaPlayer.setDataSource(musicFileList.get(index).toString());
  69. mMediaPlayer.prepare();
  70. mMediaPlayer.start();
  71. //如果是顺序循环播放
  72. if(mPlayMode==PlayMode.CYCLE){
  73. mMediaPlayer
  74. .setOnCompletionListener(newOnCompletionListener(){
  75. @Override
  76. publicvoidonCompletion(MediaPlayermp){
  77. stop();//停止
  78. next();//下首
  79. play();//播放
  80. }
  81. });
  82. }
  83. mStatus=Status.PLAYING;
  84. returntrue;
  85. }catch(Exceptione){
  86. e.printStackTrace();
  87. }
  88. returnfalse;
  89. }
  90. @Override
  91. publicbooleanpause(){
  92. if(mStatus!=Status.PLAYING){
  93. returnfalse;
  94. }
  95. mMediaPlayer.pause();
  96. mStatus=Status.PAUSING;
  97. returntrue;
  98. }
  99. @Override
  100. publicbooleanresume(){
  101. if(mStatus!=Status.PAUSING){
  102. returnfalse;
  103. }
  104. mMediaPlayer.start();
  105. mStatus=Status.PLAYING;
  106. returntrue;
  107. }
  108. @Override
  109. publicbooleanstop(){
  110. if(mStatus!=Status.STOPPED){
  111. mMediaPlayer.stop();
  112. mStatus=Status.STOPPED;
  113. returntrue;
  114. }
  115. returnfalse;
  116. }
  117. @Override
  118. publicvoidrelease(){
  119. stop();
  120. mMediaPlayer.release();
  121. mMediaPlayer=null;
  122. }
  123. @Override
  124. publicvoidonItemClick(AdapterView<?>parent,Viewview,intposition,
  125. longid){
  126. setSelection(position);
  127. if(null!=listener&&hasMusic()){
  128. if(listener.onMusicClick(musicFileList.get(position))){
  129. stop();//停止
  130. play();//播放
  131. }
  132. }
  133. }
  134. publicvoidsetOnMusicClickListener(OnMusicClickListenerlistener){
  135. this.listener=listener;
  136. }
  137. }
4 )播放器活动 界面上各点击事件与播放控制接口结合。 5 )其他设置(样例中未写== 5.1)播放进度 使用MediaPlayer提供了如下3个方法即可:

1. getDuration():获得总持续时间(毫秒)

{Idle, Initialized, Error}状态时,该方法无效。

2. getCurrentPosition():获得当前播放位置(毫秒)

{Error}状态时,该方法无效。

3. seekTo(int msec):跳至指定的时间位置(毫秒)

{Idle, Initialized, Stopped, Error}状态时,该方法无效。

5.2)音量控制

使用AudioManager的setStreamVolume(int streamType, int index, int flags)方法。第一个参数设置为AudioManager.STREAM_MUSIC,即为音乐音量。

三、其他音频类

一样是在package android.media包内,还有好几个以Player后缀结束的类呢T^T。没用过,也不多作介绍了。

这节呢,主要是想介绍下SoundPool,以及它与MediaPlayer的利弊及使用场合。 1 )利弊及场合 MediaPlayer资源占用多、延迟长、不支持多个音频同时播放。在快速连续播放音效时,尤其会感受到。而SoundPool则不同,占用少、延迟短、支持多音频播放。因为其限制最大只能申请1M的内存,也就意味着是用于播放音频片断的。 总结就是,MediaPlayer播放长音乐,SoundPool播放短音效==。 2 )SoundPool 注意点 1. 音效文件不易过大(限制1M内存) 如果音效文件过大而没有载入完成,调用play()可能会产生严重的后果。当然可以用SoundPool.OnLoadCompleteListener来判断是否载入完成。 2. pause&stop方法建议不轻易使用 有时会使你程序莫名终止。也有反映不会立即终止,而是等缓冲区播放完,会多一秒。 3. 音频格式建议使用OGG格式。 说是WAV在音效播放间隔较短的情况下会出现异常关闭的情况。另外说是,目前只对16位的WAV支持较好。(目前不知道指什么时候==) 参考自网络,未亲自证实,尽量避免就行了^^。 3 )SoundPool 的使用 SoundPool基本的播放控制方法。方法的详细说明都在注释了^^。
        
  1. publicclassSoundPoolActivityextendsActivityimplements
  2. SoundPool.OnLoadCompleteListener{
  3. privatestaticfinalintSOUND_BASE=0;
  4. privatestaticfinalintSOUND_THUNDER=SOUND_BASE+1;
  5. privatestaticfinalintSOUND_NIGHTINGALE=SOUND_BASE+2;
  6. privateSoundPoolmSoundPool;//SoundPool对象
  7. privateHashMap<Integer,Integer>soundPoolMap;
  8. @Override
  9. protectedvoidonCreate(BundlesavedInstanceState){
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.audio_pool);
  12. initSounds();//初始化SoundPool
  13. }
  14. //初始化SoundPool
  15. privatevoidinitSounds(){
  16. /*
  17. *SoundPool(intmaxStreams,intstreamType,intsrcQuality)
  18. *
  19. *maxStreams:同时播放的流的最大数量
  20. *streamType:流的类型(AudioManager类中描述的)。例如:游戏应用一般使用STREAM_MUSIC
  21. *srcQuality:采样率转化质量。当前无效果,使用0作为默认值
  22. */
  23. mSoundPool=newSoundPool(4,AudioManager.STREAM_MUSIC,100);
  24. /*
  25. *Android2.2(API8及以上)才有这接口==
  26. */
  27. mSoundPool.setOnLoadCompleteListener(this);
  28. soundPoolMap=newHashMap<Integer,Integer>();
  29. /*
  30. *load()有四种方法,如下:
  31. *
  32. *1)intload(Contextcontext,intresId,intpriority)
  33. *从APK资源载入(一般在res/raw目录下)
  34. *2)intload(FileDescriptorfd,longoffset,longlength,intpriority)
  35. *从FileDescriptor对象载入
  36. *3)intload(AssetFileDescriptorafd,intpriority)
  37. *从Asset对象载入
  38. *4)intload(Stringpath,intpriority)
  39. *从完整文件路径名载入
  40. *
  41. *最后priority参数为优先级,播放多文件时处理用。
  42. */
  43. soundPoolMap
  44. .put(SOUND_THUNDER,mSoundPool.load(this,R.raw.thunder,1));
  45. soundPoolMap.put(SOUND_NIGHTINGALE,
  46. mSoundPool.load(this,R.raw.nightingale,2));
  47. }
  48. //雷声
  49. publicvoidbird(Viewv){
  50. /*
  51. *play(intsoundID,floatleftVolume,floatrightVolume,intpriority,intloop,floatrate)
  52. *
  53. *soundID:load()方法返回的int值
  54. *leftVolume:左音量。范围=[0.0,1.0]
  55. *rightVolume:右音量。范围=[0.0,1.0]
  56. *priority:优先级。最低=0
  57. *loop:循环次数。不循环=0;永远循环=-1
  58. *rate:速率。正常=1;范围=[0.5,2.0]
  59. */
  60. mSoundPool.play(soundPoolMap.get(SOUND_THUNDER),1,1,0,0,1);
  61. }
  62. //雷声+夜莺
  63. publicvoidmix(Viewv){
  64. mSoundPool.play(soundPoolMap.get(SOUND_THUNDER),1,1,0,0,1);
  65. mSoundPool.play(soundPoolMap.get(SOUND_NIGHTINGALE),1,1,0,0,1);
  66. }
  67. @Override
  68. publicvoidonBackPressed(){
  69. super.onBackPressed();
  70. mSoundPool.release();
  71. }
  72. @Override
  73. publicvoidonLoadComplete(SoundPoolsoundPool,intsampleId,intstatus){
  74. //Log.d("TAG","=="+sampleId+"==");
  75. }
  76. }
四、 MediaRecorder 在Camera摄像里,MediaRecorder用来录制视频了。这里是介绍录制音频了^^。好吧,再摘张图过来(真心觉着看看API就好了,可以把我忽视==):

五、简易录音机 简易的录音机,就是能录音和回放一下的那种==。 1 )录音机对象 录音机的简单实现。MediaRecorder控制录音、MediaPlayer用于播放,设置了其各个阶段状态。
        
  1. publicclassRecorderimplementsOnCompletionListener,OnErrorListener{
  2. //录音机状态
  3. publicenumStatus{
  4. IDLE,RECORDING,PLAYING
  5. }
  6. //当前状态
  7. privateStatusmStatus=Status.IDLE;
  8. //媒体录制对象
  9. privateMediaRecordermRecorder=null;
  10. //媒体播放对象
  11. privateMediaPlayermPlayer=null;
  12. //录制的文件
  13. FilemSampleFile=null;
  14. //录音或播放开始时间
  15. longmSampleStart=0;
  16. privateOnRecorderListenerlistener;//播放器接口
  17. publicinterfaceOnRecorderListener{
  18. voiderror();
  19. voidplayOver();
  20. }
  21. //返回录音机状态
  22. publicStatusgetStatus(){
  23. returnmStatus;
  24. }
  25. //是否录过音
  26. publicbooleanisRecorded(){
  27. returnmSampleFile!=null;
  28. }
  29. //返回时间进度(秒)
  30. publicintprogress(){
  31. if(mStatus==Status.RECORDING||mStatus==Status.PLAYING)
  32. return(int)((System.currentTimeMillis()-mSampleStart)/1000);
  33. return0;
  34. }
  35. //开始录音
  36. publicvoidstartRecording(){
  37. stop();//停止
  38. if(mSampleFile==null){
  39. //创建文件,以createTempFile方式避免覆盖
  40. try{
  41. Filedir=newFile(Environment.getExternalStorageDirectory()
  42. +"/AndroidMedia/");
  43. if(!dir.exists()){
  44. dir.mkdirs();
  45. }
  46. mSampleFile=File.createTempFile("join_",".3gpp",dir);
  47. }catch(IOExceptione){
  48. e.printStackTrace();
  49. return;
  50. }
  51. }
  52. mRecorder=newMediaRecorder();//创建MediaRecorder对象
  53. mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置音频信号源:麦克风
  54. mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//设置输出格式
  55. mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//设置音频编码器
  56. mRecorder.setOutputFile(mSampleFile.getAbsolutePath());//设置输出文件
  57. try{
  58. mRecorder.prepare();//准备录音
  59. }catch(Exceptione){
  60. mRecorder.reset();//重置空闲
  61. mRecorder.release();//释放资源
  62. mRecorder=null;//重置为null
  63. return;//返回
  64. }
  65. try{
  66. mRecorder.start();//开启录音
  67. }catch(RuntimeExceptione){
  68. //可能开启不了,如果是来电的话,可以如下判断:
  69. //AudioManager.getMode()==MODE_IN_CALL||MODE_IN_COMMUNICATION
  70. mRecorder.reset();//重置空闲
  71. mRecorder.release();//释放资源
  72. mRecorder=null;//重置为null
  73. return;//返回
  74. }
  75. mSampleStart=System.currentTimeMillis();//初始化开始时间
  76. mStatus=Status.RECORDING;//设置录音状态
  77. }
  78. //停止录音
  79. publicvoidstopRecording(){
  80. if(mRecorder==null)
  81. return;
  82. mRecorder.stop();//停止录音
  83. mRecorder.release();//释放资源
  84. mRecorder=null;//重置为null
  85. mStatus=Status.IDLE;//设为空闲状态
  86. }
  87. //开始录音
  88. publicvoidstartPlayback(){
  89. stop();//停止
  90. mPlayer=newMediaPlayer();//创建MediaPlayer对象
  91. try{
  92. mPlayer.setDataSource(mSampleFile.getAbsolutePath());//设置数据资源路径
  93. mPlayer.setOnCompletionListener(this);//设置完成监听接口
  94. mPlayer.setOnErrorListener(this);//设置错误监听接口
  95. mPlayer.prepare();//准备
  96. mPlayer.start();//播放
  97. }catch(Exceptione){
  98. mPlayer=null;//重置为null
  99. return;
  100. }
  101. mSampleStart=System.currentTimeMillis();//初始化开始时间
  102. mStatus=Status.PLAYING;//设置录音状态
  103. }
  104. //停止录音
  105. publicvoidstopPlayback(){
  106. if(mPlayer==null)
  107. return;
  108. mPlayer.stop();//停止播放
  109. mPlayer.release();//释放资源
  110. mPlayer=null;//重置为null
  111. mStatus=Status.IDLE;//设为空闲状态
  112. }
  113. //停止操作
  114. publicvoidstop(){
  115. stopRecording();
  116. stopPlayback();
  117. }
  118. @Override
  119. publicbooleanonError(MediaPlayermp,intwhat,intextra){
  120. stop();//停止
  121. if(null!=listener){
  122. listener.error();
  123. }
  124. returntrue;
  125. }
  126. @Override
  127. publicvoidonCompletion(MediaPlayermp){
  128. stop();//停止
  129. if(null!=listener){
  130. listener.playOver();
  131. }
  132. }
  133. //设置播放器接口
  134. publicvoidsetOnRecorderListener(OnRecorderListenerlistener){
  135. this.listener=listener;
  136. }
  137. }
2 )录音机活动 录音机控制界面。进行录音&播放控制,并显示有时间。 3 )其他设置(样例中未写) MediaRecorder的getMaxAmplitude()可以获得音频资源的最大振幅,可以用于展示下录音时的波幅线条? 增加设置文件大小限制或物体空间限制,提示剩余时间。物理空间可以用package android.os包内的StatFs类。StatFs是Unix statfs()的一个包装,用于检索文件系统空间的整体信息。在之前Camera摄像的CameraVideoActivity内稍带用了下的^^。 当然,这些功能在系统自带的录音机里都有实现了的,直接可以用==。 六、后记 1 )扩展内容 1.1)android获取多媒体信息之音频文件 http://hi.baidu.com/shiwl111/blog/item/98b42ed041ea7c2d960a16d8.html 1.2)RandomMusicPlayer:Service方式如何进行音乐播放控制(官方例子) http://developer.android.com/resources/samples/RandomMusicPlayer/index.html 1.3)Jamendo:一款开源在线音乐播放器

Google Code:http://code.google.com/p/jamendo/

源码分析系列: http://blog.csdn.net/gaomatrix/article/category/900092 2 )模块概览 2.1)Audio MediaPlayer

2.2)Audio SoundPool

2.3)Audio MeidaRecorder

3 )运行效果 3.1)音乐播放器

3.2)SoundPool

3.3)简单录音机

更多相关文章

  1. android自定义view控件
  2. 自定义Dialog宽度设定
  3. android状态栏一体化(改变状态栏的背景颜色)
  4. Android(安卓)FrameLayout布局中的控件设置居中动态设置
  5. 关于Android主题splash全屏和主页面的沉浸式状态栏
  6. TextInputEditText样式设置
  7. Android(安卓)使用Visualizer获取播放音频的频率
  8. Android之EditText 属性汇总 +限定输入某些特殊字符
  9. Android(安卓)6.0新控件属性记录

随机推荐

  1. Android获取屏幕尺寸的方法
  2. android tabHost布局之一 不继承TabActiv
  3. 关于Android studio Logcat显示不全,不显
  4. [Android源码解析]蓝牙扫描结果反馈的分
  5. android传递图片和图片与byte转换
  6. Android ProgressDialog的示例
  7. 打包状态下百度的ak的获得
  8. Android The content of the adapter has
  9. android 单选(RadioGroup )复选(CheckBox)按
  10. adb shell input keyevent值所对应的字符