From aa4fd8a1fddcbffd7866441b398dc3ef888c7854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adriel=20Caf=C3=A9?= Date: Thu, 18 Aug 2016 13:07:10 -0300 Subject: [PATCH] Playing recorded audio --- .../AndroidAudioRecorder.java | 2 +- .../AudioRecorderActivity.java | 231 ++++++++++++++---- .../adriel/androidaudiorecorder/Util.java | 11 +- .../res/layout/activity_audio_recorder.xml | 32 ++- lib/src/main/res/values-pt/strings.xml | 5 + lib/src/main/res/values/strings.xml | 4 +- 6 files changed, 221 insertions(+), 64 deletions(-) create mode 100644 lib/src/main/res/values-pt/strings.xml diff --git a/lib/src/main/java/cafe/adriel/androidaudiorecorder/AndroidAudioRecorder.java b/lib/src/main/java/cafe/adriel/androidaudiorecorder/AndroidAudioRecorder.java index 637ed24..82d7942 100644 --- a/lib/src/main/java/cafe/adriel/androidaudiorecorder/AndroidAudioRecorder.java +++ b/lib/src/main/java/cafe/adriel/androidaudiorecorder/AndroidAudioRecorder.java @@ -11,7 +11,7 @@ public class AndroidAudioRecorder { private Activity activity; - private String filePath = Environment.getExternalStorageDirectory() + "/audio.wav"; + private String filePath = Environment.getExternalStorageDirectory() + "/recorded_audio.wav"; private int color = Color.parseColor("#546E7A"); private int requestCode = 0; diff --git a/lib/src/main/java/cafe/adriel/androidaudiorecorder/AudioRecorderActivity.java b/lib/src/main/java/cafe/adriel/androidaudiorecorder/AudioRecorderActivity.java index 4949516..e5aee18 100644 --- a/lib/src/main/java/cafe/adriel/androidaudiorecorder/AudioRecorderActivity.java +++ b/lib/src/main/java/cafe/adriel/androidaudiorecorder/AudioRecorderActivity.java @@ -3,6 +3,7 @@ import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.drawable.ColorDrawable; +import android.media.MediaPlayer; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Menu; @@ -12,6 +13,7 @@ import android.widget.RelativeLayout; import android.widget.TextView; +import com.cleveroad.audiovisualization.DbmHandler; import com.cleveroad.audiovisualization.GLAudioVisualizationView; import java.io.File; @@ -23,20 +25,25 @@ import omrecorder.PullTransport; import omrecorder.Recorder; -public class AudioRecorderActivity extends AppCompatActivity implements PullTransport.OnAudioChunkPulledListener { +public class AudioRecorderActivity extends AppCompatActivity + implements PullTransport.OnAudioChunkPulledListener, + MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener { + private MediaPlayer player; private Recorder recorder; private VisualizerHandler visualizerHandler; - private Timer timer; - private MenuItem saveMenuItem; private String filePath; private int color; - private int secondsRecorded; + + private Timer timer; + private MenuItem saveMenuItem; + private int secondsElapsed; private boolean isRecording; private RelativeLayout contentLayout; - private GLAudioVisualizationView audioVisualizationView; + private GLAudioVisualizationView visualizerView; + private TextView statusView; private TextView timerView; private ImageButton restartView; private ImageButton recordView; @@ -47,8 +54,13 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_audio_recorder); - filePath = getIntent().getStringExtra(AndroidAudioRecorder.EXTRA_FILE_PATH); - color = getIntent().getIntExtra(AndroidAudioRecorder.EXTRA_COLOR, Color.BLACK); + if(savedInstanceState != null) { + filePath = savedInstanceState.getString(AndroidAudioRecorder.EXTRA_FILE_PATH); + color = savedInstanceState.getInt(AndroidAudioRecorder.EXTRA_COLOR); + } else { + filePath = getIntent().getStringExtra(AndroidAudioRecorder.EXTRA_FILE_PATH); + color = getIntent().getIntExtra(AndroidAudioRecorder.EXTRA_COLOR, Color.BLACK); + } if (getSupportActionBar() != null) { getSupportActionBar().setHomeButtonEnabled(true); @@ -61,7 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { getResources().getDrawable(R.drawable.ic_clear)); } - audioVisualizationView = new GLAudioVisualizationView.Builder(this) + visualizerView = new GLAudioVisualizationView.Builder(this) .setLayersCount(1) .setWavesCount(6) .setWavesHeight(R.dimen.wave_height) @@ -74,51 +86,63 @@ protected void onCreate(Bundle savedInstanceState) { .build(); contentLayout = (RelativeLayout) findViewById(R.id.content); + statusView = (TextView) findViewById(R.id.status); timerView = (TextView) findViewById(R.id.timer); restartView = (ImageButton) findViewById(R.id.restart); recordView = (ImageButton) findViewById(R.id.record); playView = (ImageButton) findViewById(R.id.play); contentLayout.setBackgroundColor(Util.getDarkerColor(color)); - contentLayout.addView(audioVisualizationView, 0); + contentLayout.addView(visualizerView, 0); restartView.setVisibility(View.INVISIBLE); playView.setVisibility(View.INVISIBLE); - visualizerHandler = new VisualizerHandler(); - audioVisualizationView.linkTo(visualizerHandler); - if(Util.isBrightColor(color)) { - restartView.setColorFilter(Color.BLACK); - recordView.setColorFilter(Color.BLACK); - playView.setColorFilter(Color.BLACK); - timerView.setTextColor(Color.BLACK); getResources().getDrawable(R.drawable.ic_clear) .setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP); getResources().getDrawable(R.drawable.ic_check) .setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP); + statusView.setTextColor(Color.BLACK); + timerView.setTextColor(Color.BLACK); + restartView.setColorFilter(Color.BLACK); + recordView.setColorFilter(Color.BLACK); + playView.setColorFilter(Color.BLACK); } } @Override public void onResume() { super.onResume(); - audioVisualizationView.onResume(); + try { + visualizerView.onResume(); + } catch (Exception e){ } } @Override protected void onPause() { stopRecording(); - audioVisualizationView.onPause(); + try { + visualizerView.onPause(); + } catch (Exception e){ } super.onPause(); } @Override protected void onDestroy() { setResult(RESULT_CANCELED); - audioVisualizationView.release(); + try { + visualizerView.release(); + } catch (Exception e){ } super.onDestroy(); } + @Override + protected void onSaveInstanceState(Bundle outState) { + outState.putString(AndroidAudioRecorder.EXTRA_FILE_PATH, filePath); + outState.putInt(AndroidAudioRecorder.EXTRA_COLOR, color); + super.onSaveInstanceState(outState); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.audio_recorder, menu); @@ -144,54 +168,82 @@ public void onAudioChunkPulled(AudioChunk audioChunk) { visualizerHandler.onDataReceived(amplitude); } - public void toggleRecording(View v) { - if (isRecording) { - stopRecording(); - } else { - startRecording(); + @Override + public void onPrepared(final MediaPlayer mediaPlayer) { + if(mediaPlayer != null){ + } } + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + stopPlaying(); + } + + private void selectAudio() { + setResult(RESULT_OK); + finish(); + } + + public void toggleRecording(View v) { + stopPlaying(); + Util.wait(100, new Runnable() { + @Override + public void run() { + if (isRecording) { + stopRecording(); + } else { + startRecording(); + } + } + }); + } + + public void togglePlaying(View v){ + stopRecording(); + Util.wait(100, new Runnable() { + @Override + public void run() { + if(isPlaying()){ + stopPlaying(); + } else { + startPlaying(); + } + } + }); + } + public void restartRecording(View v){ stopRecording(); + stopPlaying(); saveMenuItem.setVisible(false); restartView.setVisibility(View.INVISIBLE); playView.setVisibility(View.INVISIBLE); recordView.setImageResource(R.drawable.ic_rec); timerView.setText("00:00:00"); - secondsRecorded = 0; - } - - public void playRecording(View v){ - // TODO play recorded audio - } - - private void selectAudio() { - setResult(RESULT_OK); - finish(); + secondsElapsed = 0; } private void startRecording() { isRecording = true; saveMenuItem.setVisible(false); + timerView.setText("00:00:00"); + statusView.setText(R.string.recording); + statusView.setVisibility(View.VISIBLE); restartView.setVisibility(View.INVISIBLE); playView.setVisibility(View.INVISIBLE); recordView.setImageResource(R.drawable.ic_stop); - timerView.setText("00:00:00"); + playView.setImageResource(R.drawable.ic_play); + + visualizerHandler = new VisualizerHandler(); + visualizerView.linkTo(visualizerHandler); recorder = OmRecorder.wav( - new PullTransport.Default(Util.getMic(), this), + new PullTransport.Default(Util.getMic(), AudioRecorderActivity.this), new File(filePath)); recorder.startRecording(); - secondsRecorded = 0; - timer = new Timer(); - timer.schedule(new TimerTask() { - @Override - public void run() { - updateTimer(); - } - }, 0, 1000); + startTimer(); } private void stopRecording() { @@ -199,9 +251,15 @@ private void stopRecording() { if(!isFinishing()) { saveMenuItem.setVisible(true); } + statusView.setText(""); + statusView.setVisibility(View.INVISIBLE); + // TODO pause and restart recording before showing this button // restartView.setVisibility(View.VISIBLE); -// playView.setVisibility(View.VISIBLE); + playView.setVisibility(View.VISIBLE); recordView.setImageResource(R.drawable.ic_rec); + playView.setImageResource(R.drawable.ic_play); + + visualizerView.release(); if(visualizerHandler != null) { visualizerHandler.stop(); @@ -212,18 +270,87 @@ private void stopRecording() { recorder = null; } - if (timer != null) { - timer.cancel(); + stopTimer(); + } + + private void startPlaying(){ + try { + player = new MediaPlayer(); + player.setDataSource(filePath); + player.prepare(); + player.start(); + + visualizerView.linkTo(DbmHandler.Factory.newVisualizerHandler(this, player)); + visualizerView.post(new Runnable() { + @Override + public void run() { + player.setOnCompletionListener(AudioRecorderActivity.this); + } + }); + + timerView.setText("00:00:00"); + statusView.setText(R.string.playing); + statusView.setVisibility(View.VISIBLE); + playView.setImageResource(R.drawable.ic_pause); + + startTimer(); + } catch (Exception e){ + e.printStackTrace(); } } - private void updateTimer() { - runOnUiThread(new Runnable() { + private void stopPlaying(){ + statusView.setText(""); + statusView.setVisibility(View.INVISIBLE); + playView.setImageResource(R.drawable.ic_play); + + if(player != null){ + try { + player.stop(); + player.reset(); + player.release(); + } catch (Exception e){ } + } + + stopTimer(); + } + + private boolean isPlaying(){ + try { + return player != null && player.isPlaying(); + } catch (Exception e){ + return false; + } + } + + private void startTimer(){ + stopTimer(); + secondsElapsed = 0; + timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { - secondsRecorded++; - timerView.setText(Util.formatSeconds(secondsRecorded)); + updateTimer(); } - }); + }, 0, 1000); + } + + private void stopTimer(){ + if (timer != null) { + timer.cancel(); + timer.purge(); + } + } + + private void updateTimer() { + if(isRecording || isPlaying()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + secondsElapsed++; + timerView.setText(Util.formatSeconds(secondsElapsed)); + } + }); + } } } diff --git a/lib/src/main/java/cafe/adriel/androidaudiorecorder/Util.java b/lib/src/main/java/cafe/adriel/androidaudiorecorder/Util.java index f253832..fa9b95a 100644 --- a/lib/src/main/java/cafe/adriel/androidaudiorecorder/Util.java +++ b/lib/src/main/java/cafe/adriel/androidaudiorecorder/Util.java @@ -5,28 +5,35 @@ import android.graphics.Color; import android.media.AudioFormat; import android.media.MediaRecorder; +import android.os.Handler; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import omrecorder.AudioSource; public class Util { + private static final Handler HANDLER = new Handler(); private static final int AUDIO_FREQUENCY = 44100; private Util() { } public static void requestPermission(Activity activity, String permission) { - if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { + if (ContextCompat.checkSelfPermission(activity, permission) + != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(activity, new String[]{permission}, 0); } } + public static void wait(int millis, Runnable callback){ + HANDLER.postDelayed(callback, millis); + } + public static AudioSource getMic() { return new AudioSource.Smart( MediaRecorder.AudioSource.MIC, AudioFormat.ENCODING_PCM_16BIT, - AudioFormat.CHANNEL_IN_MONO, + AudioFormat.CHANNEL_IN_STEREO, AUDIO_FREQUENCY); } diff --git a/lib/src/main/res/layout/activity_audio_recorder.xml b/lib/src/main/res/layout/activity_audio_recorder.xml index 8f5e62a..fe7e712 100644 --- a/lib/src/main/res/layout/activity_audio_recorder.xml +++ b/lib/src/main/res/layout/activity_audio_recorder.xml @@ -7,17 +7,34 @@ android:orientation="vertical" android:gravity="center"> - + android:orientation="vertical"> + + + + + + diff --git a/lib/src/main/res/values-pt/strings.xml b/lib/src/main/res/values-pt/strings.xml new file mode 100644 index 0000000..efe5524 --- /dev/null +++ b/lib/src/main/res/values-pt/strings.xml @@ -0,0 +1,5 @@ + + Savar + Gravando + Reproduzindo + \ No newline at end of file diff --git a/lib/src/main/res/values/strings.xml b/lib/src/main/res/values/strings.xml index fe68eea..6a22cf0 100644 --- a/lib/src/main/res/values/strings.xml +++ b/lib/src/main/res/values/strings.xml @@ -1,4 +1,6 @@ - AndroidAudioRecorder + AndroidAudioRecorder Save + Recording + Playing \ No newline at end of file