55import android .media .MediaRecorder ;
66import android .net .Uri ;
77import android .os .Bundle ;
8+ import android .os .SystemClock ;
9+ import android .support .design .widget .FloatingActionButton ;
10+ import android .support .v4 .content .ContextCompat ;
11+ import android .text .format .DateFormat ;
812import android .util .Log ;
913import android .view .View ;
10- import android .widget .Button ;
11- import android .widget .ImageButton ;
14+ import android .widget .Chronometer ;
1215import android .widget .LinearLayout ;
1316import android .widget .ProgressBar ;
14- import android .widget .SeekBar ;
1517import android .widget .TextView ;
1618
1719import java .io .FileDescriptor ;
@@ -30,21 +32,14 @@ public class SoundRecorderActivity extends Activity {
3032 Uri mOutputUri ;
3133 FileDescriptor mOutputFileDescriptor ;
3234
33- LinearLayout mSoundRecorderLayout ;
34-
3535 // Views for recording
3636 ProgressBar mRecordAudioProgressBar ;
37- ImageButton mPlaybackPlayPauseButton ;
38-
3937 // Views for playback
40- SeekBar mAudioSeekBar ;
41- Button mRecordAudioCancelButton ;
42- ImageButton mRecordAudioPlayButton ;
38+ Chronometer mAudioSeekBar ;
4339
4440 // Views for both
45- Button mRecordAudioControlButton ;
46- TextView mCurrentRecordTimeCurrentTextView ;
47- TextView mCurrentRecordTimeMaxTextView ;
41+ FloatingActionButton mRecordAudioControlButton ;
42+ TextView mRecordingStatus ;
4843 Timer mProgressTimer ;
4944
5045 // Recorder stuff
@@ -114,16 +109,12 @@ private void setup() {
114109
115110 private void setupViews () {
116111 Log .d (LOG_TAG , "setupViews" );
117- mSoundRecorderLayout = (LinearLayout ) findViewById (R .id .sound_recorder_layout );
118112
119113 mRecordAudioProgressBar = (ProgressBar ) findViewById (R .id .record_audio_progress );
120- mAudioSeekBar = (SeekBar ) findViewById (R .id .audio_seekbar );
121-
122- mRecordAudioControlButton = (Button ) findViewById (R .id .record_audio_control_button );
123- mRecordAudioCancelButton = (Button ) findViewById (R .id .record_audio_cancel_button );
124-
125- mCurrentRecordTimeCurrentTextView = (TextView ) findViewById (R .id .record_audio_time_current );
126- mCurrentRecordTimeMaxTextView = (TextView ) findViewById (R .id .record_audio_time_max );
114+ mRecordAudioProgressBar .setMax (MAX_DURATION_MS );
115+ mAudioSeekBar = (Chronometer ) findViewById (R .id .record_audio_seekbar );
116+ mRecordAudioControlButton = (FloatingActionButton ) findViewById (R .id .record_audio_control_button );
117+ mRecordingStatus = (TextView ) findViewById ((R .id .recording_status_text ));
127118
128119 mOnClickListener = new View .OnClickListener () {
129120 @ Override
@@ -138,101 +129,30 @@ public void onClick(View v) {
138129 tearDownRecording (false );
139130 break ;
140131 case STOPPED :
132+ setupRecorder ();
133+ startRecording ();
134+ break ;
135+ default :
141136 completeRecording ();
142137 break ;
143138 }
144139 break ;
145-
146- case R .id .record_audio_cancel_button :
147- onCancel ();
148- break ;
149140 }
150141 }
151142 };
152143
153144 mRecordAudioControlButton .setOnClickListener (mOnClickListener );
154- mRecordAudioCancelButton .setOnClickListener (mOnClickListener );
155-
156- mAudioSeekBar .setOnSeekBarChangeListener (new SeekBar .OnSeekBarChangeListener () {
157- @ Override
158- public void onProgressChanged (SeekBar seekBar , int progress , boolean fromUser ) {
159- mCurrentRecordTimeCurrentTextView .setText (getTimeString (progress ));
160- }
161-
162- @ Override
163- public void onStartTrackingTouch (SeekBar seekBar ) {
164-
165- }
166145
146+ mAudioSeekBar .setOnChronometerTickListener (new Chronometer .OnChronometerTickListener () {
167147 @ Override
168- public void onStopTrackingTouch (SeekBar seekBar ) {
148+ public void onChronometerTick (Chronometer chronometer ) {
149+ long t = SystemClock .elapsedRealtime () - chronometer .getBase ();
169150
151+ mRecordAudioProgressBar .setProgress ((int ) t );
152+ chronometer .setText (DateFormat .format ("mm:ss" , t ));
170153 }
171-
172154 });
173155
174- mRecordAudioProgressBar .setMax (MAX_DURATION_MS );
175- }
176-
177- private void setCurrentRecordingState (RecordingState recordingState ) {
178- Log .i (LOG_TAG , "setCurrentRecordingState: " + recordingState );
179-
180- mCurrentRecordingState = recordingState ;
181- }
182-
183- private void setupProgressTimer () {
184- mProgressTimer = new Timer ();
185- }
186-
187- private void startProgressTimer () {
188- if (mProgressTimer == null ) {
189- setupProgressTimer ();
190- }
191-
192- mProgressTimer .schedule (new TimerTask () {
193-
194- @ Override
195- public void run () {
196- runOnUiThread (new Runnable () {
197- @ Override
198- public void run () {
199- int nextMilliSeconds ;
200-
201- if (mCurrentRecordingState == RecordingState .STARTED ) {
202- if (mRecordAudioProgressBar .getProgress () < MAX_DURATION_MS ) {
203- nextMilliSeconds = mRecordAudioProgressBar .getProgress () + getProgressIncrement (mRecordAudioProgressBar .getProgress ());
204-
205- Log .i (LOG_TAG , "Recording progress " + nextMilliSeconds );
206-
207- mRecordAudioProgressBar .setProgress (nextMilliSeconds );
208- mCurrentRecordTimeCurrentTextView .setText (getTimeString (nextMilliSeconds ));
209- } else {
210- //Reached maximum duration. Stopping.
211- tearDownRecording (false );
212- }
213- } else if (mCurrentRecordingState == RecordingState .STOPPED ) {
214- if (mAudioSeekBar .getProgress () < MAX_DURATION_MS ) {
215- nextMilliSeconds = mAudioSeekBar .getProgress () + getProgressIncrement (mAudioSeekBar .getProgress ());
216-
217- Log .i (LOG_TAG , "Recording progress " + nextMilliSeconds );
218-
219- mAudioSeekBar .setProgress (nextMilliSeconds );
220- mCurrentRecordTimeCurrentTextView .setText (getTimeString (nextMilliSeconds ));
221- }
222- }
223- }
224- });
225- }
226- }, 0 , 1000 );
227- }
228-
229- private void stopProgressTimer () {
230- if (mProgressTimer != null ) {
231- mProgressTimer .cancel ();
232- mProgressTimer .purge ();
233- }
234-
235- mProgressTimer = null ;
236156 }
237157
238158 private void setupRecorder () {
@@ -247,70 +167,48 @@ private void setupRecorder() {
247167 mMediaRecorder .setMaxDuration (MAX_DURATION_MS );
248168 mMediaRecorder .setAudioEncoder (MediaRecorder .AudioEncoder .AMR_NB );
249169 mMediaRecorder .setOutputFile (mOutputFileDescriptor );
250-
251-
170+ mAudioSeekBar .setBase (SystemClock .elapsedRealtime ());
252171 try {
253172 mMediaRecorder .prepare ();
254-
255- onSetupRecorder ();
173+ mCurrentRecordingState = RecordingState .NOT_STARTED ;
256174 } catch (IOException exception ) {
257175 Log .e (LOG_TAG , "Recording preparation failed" , exception );
258176 finish ();
259177 }
260178 }
261179
262- private void onSetupRecorder () {
263- setCurrentRecordingState (RecordingState .NOT_STARTED );
264- }
265-
266180 private void startRecording () {
267181 try {
268182 mMediaRecorder .start ();
269-
270- onStartRecording ();
183+ mCurrentRecordingState = RecordingState .STARTED ;
184+ mRecordAudioControlButton .setImageDrawable (ContextCompat .getDrawable (SoundRecorderActivity .this .getApplication ().getBaseContext (), R .drawable .ic_stop ));
185+ mAudioSeekBar .start ();
186+ mRecordAudioProgressBar .setVisibility (View .VISIBLE );
271187 } catch (IllegalStateException exception ) {
272188 Log .e (LOG_TAG , "Bad state when starting recording" , exception );
273189 }
274190 }
275191
276- private void onStartRecording () {
277- Log .i (LOG_TAG , "Recording started" );
278-
279- setCurrentRecordingState (RecordingState .STARTED );
280-
281- mRecordAudioControlButton .setText (R .string .stop_dialog );
282- mRecordAudioProgressBar .setVisibility (View .VISIBLE );
283- startProgressTimer ();
284- }
285-
286192 private void stopRecording () {
287193 try {
288194 mMediaRecorder .stop ();
195+ mAudioSeekBar .stop ();
289196
290197 } catch (IllegalStateException exception ) {
291198 Log .e (LOG_TAG , "Bad state when stopping recording (ignoring)" , exception );
292199 } catch (RuntimeException exception ) {
293200 Log .e (LOG_TAG , "Exception when stopping recording (ignoring)" , exception );
294201 }
295202
296- onStopRecording ();
297- }
298-
299- private void onStopRecording () {
300203 Log .i (LOG_TAG , "Recording stopped" );
301-
302- setCurrentRecordingState (RecordingState .STOPPED );
303-
304- stopProgressTimer ();
204+ mCurrentRecordingState = RecordingState .STOPPED ;
205+ mRecordAudioControlButton .setImageDrawable (ContextCompat .getDrawable (SoundRecorderActivity .this .getApplication ().getBaseContext (), R .drawable .ic_mic_white_24dp ));
305206 }
306207
208+
307209 private void completeRecording () {
308210 Log .d (LOG_TAG , "completeRecording" );
309211 tearDownRecording (true );
310- onCompleteRecording ();
311- }
312-
313- private void onCompleteRecording () {
314212 Intent returnIntent = new Intent ();
315213 returnIntent .setData (mOutputUri );
316214 setResult (RESULT_OK , returnIntent );
@@ -335,59 +233,15 @@ private void tearDownRecording(boolean fromCancellation) {
335233 }
336234
337235 if (!fromCancellation ) {
338- mRecordAudioControlButton .setText (R .string .okay );
339- mRecordAudioProgressBar .setVisibility (View .INVISIBLE );
340- mAudioSeekBar .setVisibility (View .VISIBLE );
341- mAudioSeekBar .setProgress (0 );
236+ mRecordingStatus .setText (R .string .record_ready );
342237 }
343238 }
344239
345- private void onCancel () {
346- tearDownRecording (true );
347- finish ();
348- }
349-
350- private String getTimeString (int miliSeconds ) {
351- int minutes = (int ) Math .floor ((miliSeconds / 1000.0 ) / 60 );
352- int seconds = miliSeconds / 1000 - minutes * 60 ;
353-
354- return String .format ("%01d:%02d" , minutes , seconds );
355- }
356-
357- private int getNumIncrements (int durationMiliSeconds ) {
358- int numIncrements = (int ) Math .ceil (durationMiliSeconds / 1000.0 );
359-
360- if (numIncrements == 0 ) {
361- return 1 ;
362- }
363-
364- return numIncrements ;
365- }
366-
367- private int getMaxDuration (int durationMiliSeconds ) {
368- int numIncrements = getNumIncrements (durationMiliSeconds ) * 1000 ;
369-
370- if (numIncrements > MAX_DURATION_MS ) {
371- numIncrements = MAX_DURATION_MS ;
372- }
373-
374- return numIncrements ;
375- }
376-
377- private int getProgressIncrement (int durationMiliSeconds ) {
378- int numIncrements = getNumIncrements (durationMiliSeconds );
379-
380- if (numIncrements == 1 ) {
381- return 1000 ;
382- }
383-
384- return Math .round (durationMiliSeconds / numIncrements );
385- }
386-
387240 @ Override
388241 protected void onDestroy () {
389242 super .onDestroy ();
390243
391- onCancel ();
244+ tearDownRecording (true );
245+ finish ();
392246 }
393247}
0 commit comments