I have a soundboard like app. I don't want the sound to stop even if the user clicks another sound. But, after a while, like 30 clicks (sound players), it stops. I think it runs out of memory or Android is not letting it make more than 30 instances.
How can I implement this better so that when a sound has finished, the media player instance is destroyed?
import java.io.IOException;
public class AudioRecordTest {
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private MediaRecorder mRecorder = null;
private MediaPlayer mPlayer = null;
public void startPlaying(int fileName) {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName + fileName + ".3gp");
mPlayer.prepare();
mPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopPlaying() {
try {
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public MediaPlayer getPlayer() {
return mPlayer;
}
public void startRecording(int fileName) {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName + fileName + ".3gp");
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
e.printStackTrace();
}
try {
mRecorder.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopRecording() {
try {
if (mRecorder != null) {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public AudioRecordTest() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/aaa";
}
}
Try this
voicePlayer.getMediaPlayer().setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.stop();
if (mediaPlayer != null) {
mediaPlayer.killMediaPlayer();
}
}
});
Try this:
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
Or:
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
mediaPlayer = null;
}
});
You can use release() of medeiaplayer
if(!mediaPlayerObject.isPlaying())
mediaPlayerObject.release();
Related
I have a button that starts playing a recorded audio when pressed. Also it's icon changes. I want to change the icon again when the playing ends. Can somebody give me an example or something? Thank you :)
Here is my audio class:
public class Audio {
private MediaPlayer mPlayer;
private MediaRecorder mRecorder;
public String path;
public void setPath(String path) {
this.path = path;
}
public void stopPlayRecorded() {
if (mPlayer != null) {
mPlayer.stop();
}
}
public void playRecorded() throws IllegalArgumentException,
SecurityException, IllegalStateException, IOException {
ditchMediaPlayer();
File f = new File(path);
if(!recordingExists(f)) {
return;
}
mPlayer = new MediaPlayer();
mPlayer.setDataSource(path);
mPlayer.prepare();
mPlayer.start();
}
private void ditchMediaPlayer() {
if (mPlayer != null) {
try {
mPlayer.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void stopRecording() {
if (mRecorder != null) {
mRecorder.stop();
ditchMediaRecorder();
}
}
public void beginRecording() throws IllegalStateException, IOException {
File f = new File(path.substring(0, path.lastIndexOf("/")));
if (!recordingExists(f)) {
f.mkdirs();
}
ditchMediaRecorder();
File outFile = new File(path);
Log.d("R_PATH", path);
if (outFile.exists()) {
outFile.delete();
}
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setOutputFile(path);
mRecorder.prepare();
mRecorder.start();
}
public boolean recordingExists(File f) {
if (f.exists())
return true;
else
return false;
}
private void ditchMediaRecorder() {
if (mRecorder != null) {
mRecorder.release();
}
}
}
Yes you can do that with OnCompletionListener:
mPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// do something when the end of a media source
// has been reached during playback.
}
});
I have an application that has a few buttons that have sounds (soundPool) I need to write them down on a flash card I make it through the MediaRecorder but when I run the app and then turn on the record playing and click stop recording application crashes you do not tell me what the problem is?
I expect that in the method recordStop
public class MainActivity extends Activity {
int kickSound;
SoundPool mSoundPool;
AssetManager assets;
private MediaRecorder mediaRecorder;
private MediaPlayer mediaPlayer;
private String fileName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSoundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
assets = getAssets();
kickSound = loadSound("snare_trap.ogg");
ImageButton kick = (ImageButton)this.findViewById(R.id.imageButton1);
kick.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
playSound(kickSound);
}
return false;
}
});
fileName = Environment.getExternalStorageDirectory() + "/record.3gpp";
}
protected void playSound(int sound) {
if (sound > 0)
mSoundPool.play(sound, 1, 1, 1, 0, 1);
}
private int loadSound(String fileName) {
AssetFileDescriptor afd = null;
try {
afd = assets.openFd(fileName);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Couldn't load file '" + fileName + "'", Toast.LENGTH_SHORT).show();
return -1;
}
return mSoundPool.load(afd, 1);
}
public void recordStart(View v) {
try {
releaseRecorder();
File outFile = new File(fileName);
if (outFile.exists()) {
outFile.delete();
}
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(AudioManager.STREAM_MUSIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setOutputFile(fileName);
mediaRecorder.prepare();
mediaRecorder.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void recordStop(View v) {
mediaRecorder.stop();
}
public void playStart(View v) {
try {
releasePlayer();
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(fileName);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void playStop(View v) {
if (mediaPlayer != null) {
mediaPlayer.stop();
}
}
private void releaseRecorder() {
if (mediaRecorder != null) {
mediaRecorder.release();
mediaRecorder = null;
}
}
private void releasePlayer() {
mediaPlayer.release();
mediaPlayer = null;
}
#Override
protected void onDestroy() {
super.onDestroy();
releasePlayer();
releaseRecorder();
}
}
Why are you releasing the recorder to start out with? Releasing should only be used if you don't want to access the recorder anymore. Try moving the release to the end.
I have a simple class to record voice and playing it after record play file:
public class MainActivity extends Activity
{
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private MediaRecorder mRecorder = null;
private Button startRecord, startPlaying, stopPlaying;
private MediaPlayer mPlayer = null;
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
//stopPlaying();
pausePlaying();
}
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
}
private void pausePlaying(){
mPlayer.stop();
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
public MainActivity() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
startPlaying = (Button) findViewById(R.id.buttonStartPlay);
stopPlaying = (Button) findViewById(R.id.buttonStopPlaying);
startRecord = (Button) findViewById(R.id.buttonStartRecord);
startRecord.setOnClickListener(new OnClickListener() {
boolean mStartRecording = true;
#Override
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
startRecord.setText("Stop recording");
} else {
startRecord.setText("Start recording");
}
mStartRecording = !mStartRecording;
}
});
startPlaying.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onPlay(true);
}
});
stopPlaying.setOnClickListener(new OnClickListener() {
boolean mStartPlaying = true;
#Override
public void onClick(View v) {
onPlay(false);
}
});
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
}
I know how can I pause, but I don't know how can I run file again but from moment where I pause my file. Any ideas?
Change this :
private void pausePlaying(){
mPlayer.stop();
}
To:
private void pausePlaying(){
if(mPlayer.isPlaying()){
mPlayer.pause();
} else {
mPlayer.start();
}
}
Don't use .stop() to pause. In the MediaPlayer API you can see that .pause() would be the best option. If you reorganized
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
To happen in your onCreate method you can avoid it resetting every time.
Check out their diagram http://i.stack.imgur.com/svHrq.gif
is there anyway I can send an email when I press the save button with OUTPUT_FILE path from sdcard. (I didn't implement the save button yet)
Should I change String to Uri instead to send an email?
I don't know how I should implement the save button making it to send an email with the audio file attached. Any suggestions? Thanks in advance!
public class FulfillAudioTaskActivity extends Activity {
private MediaPlayer mediaPlayer;
private MediaRecorder recorder;
private String OUTPUT_FILE;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fulfill_audio_task);
OUTPUT_FILE = Environment.getExternalStorageDirectory()+"/audiorecorder.3gpp";
}
public void buttonTapped(View view){
switch(view.getId()) {
case R.id.startBtn:
try {
beginRecording();
}catch (Exception e){
e.printStackTrace();
}
break;
case R.id.finishBtn:
try {
stopRecording();
} catch (Exception e){
e.printStackTrace();
}
break;
case R.id.playBtn:
try {
playRecording();
} catch (Exception e){
e.printStackTrace();
}
break;
case R.id.stopBtn:
try {
stopPlayback();
} catch (Exception e){
e.printStackTrace();
}
break;
}
}
private void stopPlayback() {
if(mediaPlayer != null)
mediaPlayer.stop();
}
private void playRecording() throws Exception{
ditchMediaPlayer();
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(OUTPUT_FILE);
mediaPlayer.prepare();
mediaPlayer.start();
}
private void ditchMediaPlayer() {
if(mediaPlayer != null)
{
try {
mediaPlayer.release();
}catch(Exception e){
e.printStackTrace();
}
}
}
// stop recording if there's a recorder running
private void stopRecording() {
if (recorder != null)
recorder.stop();
}
private void beginRecording() throws Exception {
ditchMediaRecorder();
File outFile = new File(OUTPUT_FILE);
//check if there's a file already recorded, and if it is we want to get rid of it.
if(outFile.exists())
outFile.delete();
//create a new MediaRecorder object.
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
recorder.setOutputFile(OUTPUT_FILE);
recorder.prepare();
recorder.start();
}
private void ditchMediaRecorder() {
// TODO Auto-generated method stub
if(recorder != null)
recorder.release();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_fulfill_audio_task, menu);
return true;
}
}
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("audio/rfc822");
i.putExtra(Intent.EXTRA_EMAIL, new String[] {"someone#gmail.com"} );
i.putExtra(Intent.EXTRA_SUBJECT, "MySubject");
i.putExtra(Intent.EXTRA_STREAM, Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "audiorecorder.3gpp");
startActivity(i);
Hope this helps!
EDIT: When I click the record button a second time ( to stop recording ) it force closes the app. The specific code for that event:
else if(isrec) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
isrec = false;
Toast.makeText( getApplicationContext(),"No longer recording!",Toast.LENGTH_SHORT).show();
}
(Original question):
I'm having trouble trying to get an app to record sound on a button click. I've included the code... and here's what my Toasts tell me:
after setAudioSource
after setOutputFile
isrec is not true
trying...
caught IO Exception...
Any help is greatly appreciated.
private OnClickListener micListener = new OnClickListener() {
boolean isrec = false;
public void onClick(View v) {
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
Toast.makeText( getApplicationContext(),"after setAudioSource",Toast.LENGTH_SHORT).show();
recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
File outputFile = null;
outputFile = getFileStreamPath("output.amr");
recorder.setOutputFile(outputFile.getAbsolutePath());
Toast.makeText( getApplicationContext(),"after setOutputFile",Toast.LENGTH_SHORT).show();
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
if(!isrec) {
Toast.makeText( getApplicationContext(),"isrec is not true",Toast.LENGTH_SHORT).show();
try {
Toast.makeText( getApplicationContext(),"trying...",Toast.LENGTH_SHORT).show();
recorder.prepare();
recorder.start();
isrec = true;
Toast.makeText( getApplicationContext(),"Recording!",Toast.LENGTH_SHORT).show();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText( getApplicationContext(),"caught IllegalState Exception...",Toast.LENGTH_SHORT).show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText( getApplicationContext(),"caught IO Exception...",Toast.LENGTH_SHORT).show();
}
} else if(isrec) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
isrec = false;
Toast.makeText( getApplicationContext(),"No longer recording!",Toast.LENGTH_SHORT).show();
}
}
};
First of all, you should use a boolean for isrec instead of a string
That :
FileDescriptor fileName = null;
recorder.setOutputFile(fileName);
That means you want to record on a file which is null
If you create a file, and you pass it as a parameter of your recorder, it should work.
Edit : Sometimes the release doesn't work when you want to stop the recorder.
So, just keep stop() and reset()
Try the following code for the main activity :
public class AudioRecordTestActivity extends Activity
{
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private RecordButton mRecordButton = null;
private MediaRecorder mRecorder = null;
private PlayButton mPlayButton = null;
private MediaPlayer mPlayer = null;
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
class RecordButton extends Button {
boolean mStartRecording = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
setText("Stop recording");
} else {
setText("Start recording");
}
mStartRecording = !mStartRecording;
}
};
public RecordButton(Context ctx) {
super(ctx);
setText("Start recording");
setOnClickListener(clicker);
}
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop playing");
} else {
setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start playing");
setOnClickListener(clicker);
}
}
public AudioRecordTestActivity() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout ll = new LinearLayout(this);
mRecordButton = new RecordButton(this);
ll.addView(mRecordButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
and in the manifest file specify the following permissions
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Maybe this will help? The article will show you how to solve two issues:
Show the way to record WAV file.
Record audio with best quality as possible.