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