Everybody,
I'm trying to make a simple audio recording.
The audio is record perfectly when record button is clicked.
I try to record another audio and play it back. It crash when I try to play the 2nd audio.
Can you please help me on fixing this app so that I can record audio multiple time without crashing the app.
Here's the code.
stop.setEnabled(false);
play.setEnabled(false);
outputFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/recording.3gp";;
myAudioRecorder=new MediaRecorder();
myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myAudioRecorder.setOutputFile(outputFile);
record.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
myAudioRecorder.prepare();
myAudioRecorder.start();
}
catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
record.setEnabled(false);
stop.setEnabled(true);
Toast.makeText(getApplicationContext(), "Recording started", Toast.LENGTH_LONG).show();
}
});
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myAudioRecorder.stop();
myAudioRecorder.reset();
record.setEnabled(true);
stop.setEnabled(false);
play.setEnabled(true);
Toast.makeText(getApplicationContext(), "Audio recorded successfully",Toast.LENGTH_LONG).show();
}
});
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) throws IllegalArgumentException,SecurityException,IllegalStateException {
MediaPlayer m = new MediaPlayer();
try {
m.setDataSource(outputFile);
}
catch (IOException e) {
e.printStackTrace();
}
try {
m.prepare();
}
catch (IOException e) {
e.printStackTrace();
}
m.start();
Toast.makeText(getApplicationContext(), "Playing audio", Toast.LENGTH_LONG).show();
}
});
Thanks!
You don't seem to enable record button when stop button is clicked. Write
record.setEnabled(true);
in the onClick() method implementation of stop button.
Another case is when stop button is clicked you are setting myAudioRecorder = null. If after this record button is clicked you will get a NullPointerException on this statement
myAudioRecorder.prepare() //exception
Solution will be to remove the statement of setting myAudioRecorder to null in onClick() implementation of stop.
Another problem comes because of this statement myAudioRecorder.release(). You can't get back the previous instance of MediaRecorder once you have released the resource. Either reinitialize myAudioRecorder each time you record or do not release the resource after stop has been clicked. To look at MediaRecorder lifecycle see this.
Here is a reference code you can look and understand. Please catch exceptions wherever required.
//package name
//imports
public class RecordPlayActivity extends AppCompatActivity implements View.OnClickListener {
// declare buttons here
private MediaRecorder myAudioRecorder;
private String recordOutputFile;
private MediaPlayer mediaPlayer;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(null);
setContentView(R.layout.layout_name);
//find buttons view by Id here
record.setOnClickListener(this);
stop.setOnClickListener(this);
play.setOnClickListener(this);
recordOutputFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/recording.3gp";
myAudioRecorder = new MediaRecorder();
myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myAudioRecorder.setOutputFile(recordOutputFile);
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(recordOutputFile);
//Initial condition
//stop.setEnabled(false); //not required as stop can be made always enabled
play.setEnabled(false);
}
#Override
public void onClick(View view){
switch(view.getId()){
case R.id.idForRecord:
myAudioRecorder.prepare();
myAudioRecorder.start();
//Recording started
record.setEnabled(false);
// don't make play enabled cause you dont want to play
// and record at same time without stopping record.
play.setEnabled(false); //required because play can get enabled from stop but it should not remain when recording
break;
case R.id.idForStop:
//if clicked after record
myAudioRecorder.stop();
myAudioRecorder.reset();
//if clicked after play
if(mediaPlayer.isLooping()) {
mediaPlayer.stop();
}
//recording stopped and saved;
record.setEnabled(true);
play.setEnabled(true);
break;
case R.id.idForPlay:
mediaPlayer.prepare();
mediaPlayer.start();
//playing
record.setEnabled(false); // you dont wanna play and record at same time
break;
default:
}
}
}`
Hope these all solves your problem.
It's crashing because outputFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/recording.3gp" ; directs to top directory od Android OS ...
If you use this path Environment.getExternalStorageDirectory()+File.separator+"sounds" "/recording.3gp" then your recording will be going into one level down directory "sounds" into directory sounds .
App will not crash if you recording is in folder down from top level path ...
Related
This is the method where I create my Mediaplayer and set it's source, but directly after I call seekTo it does't play anymore (If I give it some time-depends on the audio, it worksm--> Conclusion after debug).
public void makeAudio(boolean isInit){
try{
if(!isInit){
mediaPlayer = new MediaPlayer();
}
soundSource = episode.getAudio();
mediaPlayer.setDataSource(soundSource);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
soundLength = mediaPlayer.getDuration();
seekBar.setMax(soundLength/1000);
mediaPlayer.seekTo(progress);//the problem I guess
}
});
}catch (Exception e){
e.printStackTrace();
}
}
It shows me this error message:
E/MediaPlayerNative: Attempt to perform seekTo in wrong state: mPlayer=0x706c23ebc0, mCurrentState=0
I would like to have any suggestion about this, because I want to make my mediaplayer go to the progress value(I get it from my intent).
I suggest you to use ExoPlayer, it is an improved version of MediaPlayer and addListener works better for online audio.
You have to add listener until it is prepared and only then you can get the duration:
exoPlayer.addListener(new Player.Listener() {
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_READY) {
long realDurationMillis = exoPlayer.getDuration();
seekBar.setMax((int)realDurationMillis/1000);
dialog.dismiss();
}
if (playbackState == ExoPlayer.STATE_ENDED){
performEndExoPlayer();
}
}
});
Here is an example you can have a look https://developer.android.com/codelabs/exoplayer-intro#5
In android studio I am able to create a mediaRecorder instance and record audio, I can then create an instance of a mediaRecorder with a different audio source and record audio. The problem is that I cannot have two mediaRecorders at one time (or so I think).
In addition to mediaRecorder, I have looked into using two different AudioRecord objects but it appears someone here tried that about a month ago and it does not work either. I have looked into the mediaMuxer which may be the key to this, but I am new to the concept of multiplexing and do not know how to implement something of this kind.
// not to professional standards
btnRecord.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(checkPermissionFromDevice()) {
pathsave = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/"
+ UUID.randomUUID().toString() +
"_audio_record.3gp";
setupMediaRecorder();
try {
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IOException e) {
e.printStackTrace();
}
btnPlay.setEnabled(false);
btnStop.setEnabled(false);
btnStopRecord.setEnabled(true);
Toast.makeText(MainActivity.this, "Recording...",
Toast.LENGTH_SHORT).show();
}
else{
requestPermission();
}
}
});
//------------------------------------------------------------------------
btnRecord2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(checkPermissionFromDevice()) {
pathsave2 = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/"
+ UUID.randomUUID().toString() +
"_audio_record.3gp";
setupMediaRecorder2();
try {
mediaRecorder2.prepare();
mediaRecorder2.start();
} catch (IOException e) {
e.printStackTrace();
}
btnPlay2.setEnabled(false);
btnStop2.setEnabled(false);
btnStopRecord2.setEnabled(true);
Toast.makeText(MainActivity.this, "Recording...",
Toast.LENGTH_SHORT).show();
}
else{
requestPermission();
}
}
});
//-----------------------------------------------------------------------
private void setupMediaRecorder() {
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
mediaRecorder.setOutputFile(pathsave);
}
//------------------------------------------------------------------------
private void setupMediaRecorder2() {
mediaRecorder2 = new MediaRecorder();
mediaRecorder2.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder2.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder2.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
mediaRecorder2.setOutputFile(pathsave2);
}
I can record, stop recording and playback both media recorders separately. When I try to record both at the same time, the app crashes. Any help would be greatly appreciated.
Let me start by saying that if image shooting interval is anything more than 1 second it works. For example taking a picture every 2 seconds works perfectly fine. But taking a picture every second sometimes throws java.lang.RuntimeException: takePicture failed. What could be causing this kind of a behaviour?
Here is the code I use and it is in Service:
#Override
public void onCreate()
{
super.onCreate();
prefs = getSharedPreferences("general",Context.MODE_PRIVATE);
handler = new Handler();
shotInterval = prefs.getInt(getString(R.string.prefs_int_imageShootingFrequency),1);
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG).show();
} else {
cameraId = findBackFacingCamera();
if (cameraId < 0) {
Toast.makeText(this, "No front facing camera found.",Toast.LENGTH_LONG).show();
} else {
camera = Camera.open(cameraId);
}
}
cameraParameters = camera.getParameters();
cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); //set camera to continuously auto-focus
camera.setParameters(cameraParameters);
pictureTaker.run(); // Start looping
}
Runnable pictureTaker = new Runnable() {
#Override
public void run() {
try {
takePicture();
} finally {
// 100% guarantee that this always happens, even if
// your update method throws an exception
handler.postDelayed(pictureTaker, shotInterval*1000);
}
}
};
private void takePicture(){
SurfaceView view = new SurfaceView(this);
try {
camera.setPreviewDisplay(view.getHolder());
camera.startPreview();
camera.takePicture(null, null,new PhotoHandler(getApplicationContext()));
} catch (IOException e) {
e.printStackTrace();
}
}
You should launch postDelayed() from the onPictureTaken() callback. You can check the system timer on call to takePicture() and reduce the delay respectively, to keep 1000ms repetition, but maybe once in a while, this delay will reach 0.
I am trying to write an Android Soundboard with multiple buttons. Each button should play a different sound.
I have a OnClickListener on each button:
buttonAlan.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
playSound("alan");
}
});
Each of these buttons is calling the following function.
private void playSound(String sound) {
int path = getResources().getIdentifier(sound, "raw", getPackageName());
mediaplayer = MediaPlayer.create(this, path);
try {
mediaplayer.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mediaplayer.start();
}
The soundboard works, but everytime you click a button it plays the sound over and over again. I need the mediaplayer to stop playing, but everytime I write something like mediaplayer.stop(), the App won't work at all.
Any suggestions what I should change in my function/code?
i solved it using a soundpool, there you can also play multiple sounds at the same time.
i first initialize it and load sounds i need in the constructor
SoundPool soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
int gameOverSound = soundPool.load(context, R.raw.gameover, 1);
and then you can play it like this:
public void playSound(int soundId) {
soundPool.play(soundId, 1.0f, 1.0f, 0, 0, 1);
}
edit:
regarding the mediaplayer you have to call stop() and release() before you start playing another sound.
also you can set
mPlayer.setLooping(false);
I have some code I have been experimenting with to see what I can do with the camera device. This following code works, but I have some issues with it that I cannot seem to solve.
The first call never works. The first time running the code the onPictureTaken callback is never called, so the file is never written. However the camera goes through all the other steps, including making the fake shutter noise.
I can't seem to set the picture size to something other than whatever it defaults to. If I try to set it to something else, the code stops working. Does the same as above, where the camera goes through all the motions, but the onPictureTaken callback is never called.
When the pictures are saved to the DCIM folder, the taken pictures do not show up in the default 'Photos' app on my phone, unless i reboot the phone.
Is there any way through code to disable the shutter noise?
Sorry, the code is a little messy because its an experiment.
Also, this code is executed in a BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if(intent.getAction().equals(TAKE_PICTURE_INTENT))
{
Toast.makeText(context, "Test", Toast.LENGTH_LONG).show();
System.out.println("GOT THE INTENT");
try
{
Camera camera = Camera.open();
System.out.println("CAMERA OPENED");
Parameters params = camera.getParameters();
params.set("flash-mode", "off");
params.set("focus-mode", "infinity");
params.set("jpeg-quality", "100");
//params.setPictureSize(2592, 1952);
String str = params.get("picture-size" + "-values");
System.out.println(str);
String size = str.split(",")[0];
System.out.println(size);
//params.set("picture-size", size);
camera.setParameters(params);
System.out.println("CAMERA PARAMETERS SET");
camera.startPreview();
System.out.println("CAMERA PREVIEW STARTED");
camera.autoFocus(new AutoFocusCallBackImpl());
}
catch(Exception ex)
{
System.out.println("CAMERA FAIL, SKIP");
return ;
}
}//if
}//onreceive
private void TakePicture(Camera camera)
{
camera.takePicture(new Camera.ShutterCallback() {
#Override
public void onShutter() {
// TODO Auto-generated method stub
System.out.println("CAMERA SHUTTER CALLBACK");
}
}
, null,
new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
//c.release();
System.out.println("CAMERA CALLBACK");
FileOutputStream outStream = null;
try {
System.out.println("Start Callback");
File esd = Environment.getExternalStorageDirectory();
outStream = new FileOutputStream(esd.getAbsolutePath() + String.format(
"/DCIM/%d.jpg", System.currentTimeMillis()));
outStream.write(imageData);
outStream.close();
System.out.println( "onPictureTaken - wrote bytes: " + imageData.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("File not found exception");
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO exception");
} finally {
System.out.println("Finally");
c.release();
}
}
}
);
//camera.release();
}//TAKE PICTURE
private class AutoFocusCallBackImpl implements Camera.AutoFocusCallback {
#Override
public void onAutoFocus(boolean success, Camera camera) {
//bIsAutoFocused = success; //update the flag used in onKeyDown()
System.out.println("Inside autofocus callback. autofocused="+success);
//play the autofocus sound
//MediaPlayer.create(CameraActivity.this, R.raw.auto_focus).start();
if(success)
{
System.out.println("AUTO FOCUS SUCCEDED");
}
else
{
System.out.println("AUTO FOCUS FAILED");
}
TakePicture(camera);
System.out.println("CALLED TAKE PICTURE");
}
}//AUTOFOCUSCALLBACK
1.First of all put all camera logic out of BroadCast receiver & put it into seprate Activity.
2.
When the pictures are saved to the DCIM folder, the taken pictures do not show up in the default 'Photos' app on my phone, unless i reboot the phone.
because MediaScanner needs to be called to rescan images/changes once you take photo. When u reboot phone mediascanner scans media & finds new images. for this isuue you should check out MediaScanner.
3.Follow Android Camera Tutorial & Camera API
-Thanks