Recorder.java revision cefd3e81da22167a56c89a8794c9b8dfe67a7673
1package com.android.soundrecorder; 2 3import java.io.File; 4import java.io.IOException; 5 6import android.media.MediaPlayer; 7import android.media.MediaRecorder; 8import android.media.MediaPlayer.OnCompletionListener; 9import android.media.MediaPlayer.OnErrorListener; 10import android.os.Bundle; 11import android.os.Environment; 12import android.util.Log; 13 14public class Recorder implements OnCompletionListener, OnErrorListener { 15 static final String SAMPLE_PREFIX = "recording"; 16 static final String SAMPLE_PATH_KEY = "sample_path"; 17 static final String SAMPLE_LENGTH_KEY = "sample_length"; 18 19 public static final int IDLE_STATE = 0; 20 public static final int RECORDING_STATE = 1; 21 public static final int PLAYING_STATE = 2; 22 23 int mState = IDLE_STATE; 24 25 public static final int NO_ERROR = 0; 26 public static final int SDCARD_ACCESS_ERROR = 1; 27 public static final int INTERNAL_ERROR = 2; 28 29 public interface OnStateChangedListener { 30 public void onStateChanged(int state); 31 public void onError(int error); 32 } 33 OnStateChangedListener mOnStateChangedListener = null; 34 35 long mSampleStart = 0; // time at which latest record or play operation started 36 int mSampleLength = 0; // length of current sample 37 File mSampleFile = null; 38 39 MediaRecorder mRecorder = null; 40 MediaPlayer mPlayer = null; 41 42 public Recorder() { 43 } 44 45 public void saveState(Bundle recorderState) { 46 recorderState.putString(SAMPLE_PATH_KEY, mSampleFile.getAbsolutePath()); 47 recorderState.putInt(SAMPLE_LENGTH_KEY, mSampleLength); 48 } 49 50 public int getMaxAmplitude() { 51 if (mState != RECORDING_STATE) 52 return 0; 53 return mRecorder.getMaxAmplitude(); 54 } 55 56 public void restoreState(Bundle recorderState) { 57 String samplePath = recorderState.getString(SAMPLE_PATH_KEY); 58 if (samplePath == null) 59 return; 60 int sampleLength = recorderState.getInt(SAMPLE_LENGTH_KEY, -1); 61 if (sampleLength == -1) 62 return; 63 64 File file = new File(samplePath); 65 if (!file.exists()) 66 return; 67 if (mSampleFile != null 68 && mSampleFile.getAbsolutePath().compareTo(file.getAbsolutePath()) == 0) 69 return; 70 71 delete(); 72 mSampleFile = file; 73 mSampleLength = sampleLength; 74 75 signalStateChanged(IDLE_STATE); 76 } 77 78 public void setOnStateChangedListener(OnStateChangedListener listener) { 79 mOnStateChangedListener = listener; 80 } 81 82 public int state() { 83 return mState; 84 } 85 86 public int progress() { 87 if (mState == RECORDING_STATE || mState == PLAYING_STATE) 88 return (int) ((System.currentTimeMillis() - mSampleStart)/1000); 89 return 0; 90 } 91 92 public int sampleLength() { 93 return mSampleLength; 94 } 95 96 public File sampleFile() { 97 return mSampleFile; 98 } 99 100 /** 101 * Resets the recorder state. If a sample was recorded, the file is deleted. 102 */ 103 public void delete() { 104 stop(); 105 106 if (mSampleFile != null) 107 mSampleFile.delete(); 108 109 mSampleFile = null; 110 mSampleLength = 0; 111 112 signalStateChanged(IDLE_STATE); 113 } 114 115 /** 116 * Resets the recorder state. If a sample was recorded, the file is left on disk and will 117 * be reused for a new recording. 118 */ 119 public void clear() { 120 stop(); 121 122 mSampleLength = 0; 123 124 signalStateChanged(IDLE_STATE); 125 } 126 127 public void startRecording(int outputfileformat, String extension) { 128 stop(); 129 130 if (mSampleFile == null) { 131 File sampleDir = Environment.getExternalStorageDirectory(); 132 if (!sampleDir.canWrite()) // Workaround for broken sdcard support on the device. 133 sampleDir = new File("/sdcard/sdcard"); 134 135 try { 136 mSampleFile = File.createTempFile(SAMPLE_PREFIX, extension, sampleDir); 137 } catch (IOException e) { 138 setError(SDCARD_ACCESS_ERROR); 139 return; 140 } 141 } 142 143 mRecorder = new MediaRecorder(); 144 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 145 mRecorder.setOutputFormat(outputfileformat); 146 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 147 mRecorder.setOutputFile(mSampleFile.getAbsolutePath()); 148 149 // Handle IOException 150 try { 151 mRecorder.prepare(); 152 } catch(IOException exception) { 153 setError(INTERNAL_ERROR); 154 mRecorder.reset(); 155 mRecorder.release(); 156 mRecorder = null; 157 return; 158 } 159 mRecorder.start(); 160 161 mSampleStart = System.currentTimeMillis(); 162 setState(RECORDING_STATE); 163 } 164 165 public void stopRecording() { 166 if (mRecorder == null) 167 return; 168 169 mRecorder.stop(); 170 mRecorder.release(); 171 mRecorder = null; 172 173 mSampleLength = (int)( (System.currentTimeMillis() - mSampleStart)/1000 ); 174 setState(IDLE_STATE); 175 } 176 177 public void startPlayback() { 178 stop(); 179 180 mPlayer = new MediaPlayer(); 181 try { 182 mPlayer.setDataSource(mSampleFile.getAbsolutePath()); 183 mPlayer.setOnCompletionListener(this); 184 mPlayer.setOnErrorListener(this); 185 mPlayer.prepare(); 186 mPlayer.start(); 187 } catch (IllegalArgumentException e) { 188 setError(INTERNAL_ERROR); 189 mPlayer = null; 190 return; 191 } catch (IOException e) { 192 setError(SDCARD_ACCESS_ERROR); 193 mPlayer = null; 194 return; 195 } 196 197 mSampleStart = System.currentTimeMillis(); 198 setState(PLAYING_STATE); 199 } 200 201 public void stopPlayback() { 202 if (mPlayer == null) // we were not in playback 203 return; 204 205 mPlayer.stop(); 206 mPlayer.release(); 207 mPlayer = null; 208 setState(IDLE_STATE); 209 } 210 211 public void stop() { 212 stopRecording(); 213 stopPlayback(); 214 } 215 216 public boolean onError(MediaPlayer mp, int what, int extra) { 217 stop(); 218 setError(SDCARD_ACCESS_ERROR); 219 return true; 220 } 221 222 public void onCompletion(MediaPlayer mp) { 223 stop(); 224 } 225 226 private void setState(int state) { 227 if (state == mState) 228 return; 229 230 mState = state; 231 signalStateChanged(mState); 232 } 233 234 private void signalStateChanged(int state) { 235 if (mOnStateChangedListener != null) 236 mOnStateChangedListener.onStateChanged(state); 237 } 238 239 private void setError(int error) { 240 if (mOnStateChangedListener != null) 241 mOnStateChangedListener.onError(error); 242 } 243} 244