[Android] 录音与播放录音实现

http://blog.csdn.net/cxf7394373/article/details/8313980

android开发文档中有一个关于录音的类MediaRecord,一张图介绍了基本的流程:

给出了一个常用的例子:
[java] view plain copy
 
  1. MediaRecorder recorder = new MediaRecorder();  
  2.  recorder.setAudioSource(MediaRecorder.AudioSource.MIC);  
  3.  recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);  
  4.  recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);  
  5.  recorder.setOutputFile(PATH_NAME);  
  6.  recorder.prepare();  
  7.  recorder.start();   // Recording is now started  
  8.  ...  
  9.  recorder.stop();  
  10.  recorder.reset();   // You can reuse the object by going back to setAudioSource() step  
  11.  recorder.release(); // Now the object cannot be reused  

我在这里实现了一个简单的程序,过程和上述类似,录音以及录音的播放。
1.基本界面如下:
 
2.工程中各文件内容如下:
  2.1 Activity——RecordActivity
[java] view plain copy
 
  1. package com.cxf;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import android.app.Activity;  
  6. import android.media.MediaPlayer;  
  7. import android.media.MediaRecorder;  
  8. import android.os.Bundle;  
  9. import android.os.Environment;  
  10. import android.util.Log;  
  11. import android.view.View;  
  12. import android.view.View.OnClickListener;  
  13. import android.widget.Button;  
  14.   
  15. public class RecordActivity extends Activity {  
  16.      
  17.     private static final String LOG_TAG = "AudioRecordTest";  
  18.     //语音文件保存路径  
  19.     private String FileName = null;  
  20.       
  21.     //界面控件  
  22.     private Button startRecord;   
  23.     private Button startPlay;  
  24.     private Button stopRecord;  
  25.     private Button stopPlay;  
  26.       
  27.     //语音操作对象  
  28.     private MediaPlayer mPlayer = null;  
  29.     private MediaRecorder mRecorder = null;  
  30.     /** Called when the activity is first created. */  
  31.     @Override  
  32.     public void onCreate(Bundle savedInstanceState) {  
  33.         super.onCreate(savedInstanceState);  
  34.         setContentView(R.layout.main);  
  35.           
  36.         //开始录音  
  37.         startRecord = (Button)findViewById(R.id.startRecord);  
  38.         startRecord.setText(R.string.startRecord);  
  39.         //绑定监听器  
  40.         startRecord.setOnClickListener(new startRecordListener());  
  41.           
  42.         //结束录音  
  43.         stopRecord = (Button)findViewById(R.id.stopRecord);  
  44.         stopRecord.setText(R.string.stopRecord);  
  45.         stopRecord.setOnClickListener(new stopRecordListener());  
  46.           
  47.         //开始播放  
  48.         startPlay = (Button)findViewById(R.id.startPlay);  
  49.         startPlay.setText(R.string.startPlay);  
  50.         //绑定监听器  
  51.         startPlay.setOnClickListener(new startPlayListener());  
  52.           
  53.         //结束播放  
  54.         stopPlay = (Button)findViewById(R.id.stopPlay);  
  55.         stopPlay.setText(R.string.stopPlay);  
  56.         stopPlay.setOnClickListener(new stopPlayListener());  
  57.           
  58.         //设置sdcard的路径  
  59.         FileName = Environment.getExternalStorageDirectory().getAbsolutePath();  
  60.         FileName += "/audiorecordtest.3gp";  
  61.     }  
  62.     //开始录音  
  63.     class startRecordListener implements OnClickListener{  
  64.   
  65.         @Override  
  66.         public void onClick(View v) {  
  67.             // TODO Auto-generated method stub  
  68.              mRecorder = new MediaRecorder();  
  69.              mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);  
  70.              mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);  
  71.              mRecorder.setOutputFile(FileName);  
  72.              mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);  
  73.              try {  
  74.                  mRecorder.prepare();  
  75.              } catch (IOException e) {  
  76.                  Log.e(LOG_TAG, "prepare() failed");  
  77.              }  
  78.              mRecorder.start();  
  79.         }  
  80.           
  81.     }  
  82.     //停止录音  
  83.     class stopRecordListener implements OnClickListener{  
  84.   
  85.         @Override  
  86.         public void onClick(View v) {  
  87.             // TODO Auto-generated method stub  
  88.              mRecorder.stop();  
  89.              mRecorder.release();  
  90.              mRecorder = null;  
  91.         }  
  92.           
  93.     }  
  94.     //播放录音  
  95.     class startPlayListener implements OnClickListener{  
  96.   
  97.         @Override  
  98.         public void onClick(View v) {  
  99.             // TODO Auto-generated method stub  
  100.             mPlayer = new MediaPlayer();  
  101.             try{  
  102.                 mPlayer.setDataSource(FileName);  
  103.                 mPlayer.prepare();  
  104.                 mPlayer.start();  
  105.             }catch(IOException e){  
  106.                 Log.e(LOG_TAG,"播放失败");  
  107.             }  
  108.         }  
  109.           
  110.     }  
  111.     //停止播放录音  
  112.     class stopPlayListener implements OnClickListener{  
  113.   
  114.         @Override  
  115.         public void onClick(View v) {  
  116.             // TODO Auto-generated method stub  
  117.             mPlayer.release();  
  118.             mPlayer = null;  
  119.         }  
  120.           
  121.     }  
  122. }  
 2.2 main.xml
[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="@string/hello" />  
  11.     <Button   
  12.         android:id="@+id/startRecord"  
  13.         android:layout_width="fill_parent"  
  14.         android:layout_height="wrap_content"  
  15.       />  
  16.     <Button   
  17.         android:id="@+id/stopRecord"  
  18.         android:layout_width="fill_parent"  
  19.         android:layout_height="wrap_content"  
  20.       />  
  21.     <Button   
  22.         android:id="@+id/startPlay"  
  23.         android:layout_width="fill_parent"  
  24.         android:layout_height="wrap_content"  
  25.       />  
  26.     <Button   
  27.         android:id="@+id/stopPlay"  
  28.         android:layout_width="fill_parent"  
  29.         android:layout_height="wrap_content"  
  30.       />  
  31. </LinearLayout>  
 2.3 Manifest.xml
[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.cxf"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk android:minSdkVersion="4" />  
  8.   
  9.     <application  
  10.         android:icon="@drawable/ic_launcher"  
  11.         android:label="@string/app_name" >  
  12.         <activity  
  13.             android:name=".RecordActivity"  
  14.             android:label="@string/app_name" >  
  15.             <intent-filter>  
  16.                 <action android:name="android.intent.action.MAIN" />  
  17.   
  18.                 <category android:name="android.intent.category.LAUNCHER" />  
  19.             </intent-filter>  
  20.               
  21.         </activity>  
  22.          
  23.     </application>  
  24.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
  25.     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  26.     <uses-permission android:name="android.permission.RECORD_AUDIO" />  
  27. </manifest>  
 2.4 string.xml
[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.   
  5.     <string name="hello"></string>  
  6.     <string name="app_name">Record</string>  
  7.     <string name="startRecord">开始录音</string>  
  8.     <string name="stopRecord">结束录音</string>  
  9.     <string name="startPlay">开始播放</string>  
  10.     <string name="stopPlay">结束播放</string>  
  11. </resources

今天在调用MediaRecorder.stop(),报错了,Java.lang.RuntimeException: stop failed.

[html] view plain copy
 
  1. E/AndroidRuntime(7698): Cause by: java.lang.RuntimeException: stop failed.  
  2. E/AndroidRuntime(7698):            at android.media.MediaRecorder.stop(Native Method)  
  3. E/AndroidRuntime(7698):            at com.tintele.sos.VideoRecordService.stopRecord(VideoRecordService.java:298)  



报错代码如下:

[java] view plain copy
 
  1. if (mediarecorder != null) {  
  2.         mediarecorder.stop();  
  3.         mediarecorder.release();  
  4.         mediarecorder = null;  
  5.         if (mCamera != null) {  
  6.             mCamera.release();  
  7.             mCamera = null;  
  8.         }  
  9.     }  

stop()方法源代码如下:

[java] view plain copy
 
  1. /** 
  2.      * Stops recording. Call this after start(). Once recording is stopped, 
  3.      * you will have to configure it again as if it has just been constructed. 
  4.      * Note that a RuntimeException is intentionally thrown to the 
  5.      * application, if no valid audio/video data has been received when stop() 
  6.      * is called. This happens if stop() is called immediately after 
  7.      * start(). The failure lets the application take action accordingly to 
  8.      * clean up the output file (delete the output file, for instance), since 
  9.      * the output file is not properly constructed when this happens. 
  10.      * 
  11.      * @throws IllegalStateException if it is called before start() 
  12.      */  
  13.     public native void stop() throws IllegalStateException;  


源代码中说了:Note that a RuntimeException is intentionally thrown to the application, if no valid audio/video data has been received when stop() is called. This happens if stop() is called immediately after start().The failure lets the application take action accordingly to clean up the output file (delete the output file, for instance), since the output file is not properly constructed when this happens.

现在,在mediarecorder.stop();这一句报错了,现在在mediarecorder.stop();这句之前加几句就不会报错了

mediarecorder.setOnErrorListener(null);
mediarecorder.setOnInfoListener(null);  
mediarecorder.setPreviewDisplay(null);

改后代码如下:

[java] view plain copy
 
    1. if (mediarecorder != null) {  
    2.             //added by ouyang start  
    3.             try {  
    4.                 //下面三个参数必须加,不加的话会奔溃,在mediarecorder.stop();  
    5.                 //报错为:RuntimeException:stop failed  
    6.                 mediarecorder.setOnErrorListener(null);  
    7.                 mediarecorder.setOnInfoListener(null);    
    8.                 mediarecorder.setPreviewDisplay(null);  
    9.                 mediarecorder.stop();  
    10.             } catch (IllegalStateException e) {  
    11.                 // TODO: handle exception  
    12.                 Log.i("Exception", Log.getStackTraceString(e));  
    13.             }catch (RuntimeException e) {  
    14.                 // TODO: handle exception  
    15.                 Log.i("Exception", Log.getStackTraceString(e));  
    16.             }catch (Exception e) {  
    17.                 // TODO: handle exception  
    18.                 Log.i("Exception", Log.getStackTraceString(e));  
    19.             }  
    20.             //added by ouyang end  
    21.               
    22.             mediarecorder.release();  
    23.             mediarecorder = null;  
    24.             if (mCamera != null) {  
    25.                 mCamera.release();  
    26.                 mCamera = null;  
    27.             }  
    28.         }  
原文地址:https://www.cnblogs.com/jukan/p/7204290.html