IllegalStateException when MediaRecorder is recording: how to fix - android

I got this issue and cant get my head around it, im recording calls directly from the speaker, so when i get TelephonyManager.CALL_STATE_OFFHOOK I instantly start recording audio from VOICE_CALL. thats part its ok, start recording but if the call is ended and start a new one, I get a java.lang.IllegalStateException
I think this is because the first call it's still being recorded... I've tried to do:
mRecorder.stop();
mRecorder.release();
mRecorder.reset();
but no luck, they all gave me a illegalStateException, I just want to know how to stop first call recording and record a new one without errors.
Here's my code for recording and call handling,
//At least one call exists that is dialing, active, or on hold, and no calls are ringing or waiting.
if (state == TelephonyManager.CALL_STATE_OFFHOOK){
if (record_calls == 1){
record_enviroment();
}
}
//when Idle = No activity.
if (state == TelephonyManager.CALL_STATE_IDLE){
//Check for audio recorded and if exists post audio to server
}
public void record_enviroment(){
path = context.getFilesDir().getAbsolutePath() + "/";
try {
//Random number for file name
Random r = new Random( System.currentTimeMillis() );
i = 10000 + r.nextInt(20000);
// Save file local to app
mFileName = path + i + "_call_" + id_asociado + ".3gp";
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e("AUDIO_RECORDER", "prepare() failed");
}
mRecorder.start();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Related

Unable to record audio of Incoming and Outgoing phone call in Android

Unable to record audio of Incoming and Outgoing phone call in Android
I am using Broadcastreceiver for detecting Phonecalls, It is working fine.
When ever phonecall is started I am using below code for start recording Phonecall and creating a folder of "CALLLOG", in which each call record will be stored.
public void startRecordingStoreFile(){
String out = new SimpleDateFormat("dd-MM-yyyy_hh-mm-ss").format(new Date());
File sampleDir = new File(Environment.getExternalStorageDirectory(), "/CALLLOG");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
String file_name = "Rec_"+out;
try {
audiofile = File.createTempFile(file_name, ".amr", sampleDir);
} catch (IOException e) {
e.printStackTrace();
}
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(audiofile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
recordstarted = true;
}
Below code for stopping the record
public void stopRecording(){
if (recordstarted) {
recorder.stop();
audioManager.setMode(AudioManager.MODE_NORMAL);
recordstarted = false;
}
}
The extension of audio files are ".amr".
Above code is not recording the audio of a phonecall, it is creating a folder of "CALLLOG" and ".amr" files are stored but audio is not recording.I was working on this from 2 days.
For example suppose lets say I am calling to "X" person,
1.MIC is not recording once the "X"(other) person lift the call, until then audio is recording some times,
2.Some times MIC instance is not available as mentioned below solution by Afsar,
I have tried with below code but it doesn't work(Sometimes it works, sometimes not).
I am unable to record audio of Incoming and outgoing calls.Some times it works, sometimes it is not working.
Please help me on this.
Thanks in Advance.
I had the same issue in the past I was trying to record Audio + Video during video call. While device is in call MIC is being used by other processes, so before setting MediaRecorder AudioSource as MIC just check whether MIC instance is available or not. You can test it like that
private boolean validateMicAvailability(){
Boolean available = true;
AudioRecord recorder =
new AudioRecord(MediaRecorder.AudioSource.MIC, 44100,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_DEFAULT, 44100);
try{
if(recorder.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED ){
available = false;
}
recorder.startRecording();
if(recorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING){
recorder.stop();
available = false;
}
recorder.stop();
} finally{
recorder.release();
recorder = null;
}
return available;
}
Simple solution of this problem is to use some CallRecorder Library following is the link.
aykuttasil/CallRecorder check it.

android - Which MediaRecorder configuration is supported by all device?

I am recording communication voice in my app and I added storage and audio record permission manifest and also getting programmatically.
My code is working fine on one device(Android 6.0 Lenovo K3 Note)
But not on another (Android 8.1 ONEPLUS A5010)
In second device output is saved as a blank file of 3.15KB
I am adding my code which I am using please tell what I am doing wrong.
MediaRecorder mRecorder;
String mFileName;
Code in OnCreate
File file = new File(getFilesDir(), "engwingoLastCall.3gp");
mFileName = file.getAbsolutePath();
try {
if(mRecorder == null) {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
}
} catch (Exception e) {
Log.d(TAG,"Recorder Error:"+e.getMessage());
}
Methods
public void startRecording() {
try {
if(mRecorder != null) {
mRecorder.prepare();
mRecorder.start();
}
} catch (Exception e) {
Log.d("Recorder", "prepare() failed");
}
}
public void stopRecording() {
if(mRecorder != null) {
try {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
} catch (IllegalStateException e) {
e.printStackTrace();
}catch (Exception e){
Log.d(TAG,e.getMessage());
}
}
}
Since you are not setting a profile with setProfile() method you may need to set audio channels, bitrate and sampling rate for audio too. Here is an example:
mRecorder.setAudioChannels(1);
// you would not want to record stereo, it is not logical
mRecorder.setAudioEncodingBitRate(128000);
// you can set it to 64000 or 96000 to lower quality, therefore decreasing the size of the audio
mRecorder.setAudioSamplingRate(44100);
// AFAIK, default value.
Hope this helps.
My Code was OK but the reason for this behavior of my recorder was,
Some other service also using my recorder at that time and that's why the file was saved empty (3.15KB Size)

block call recording in android

I want to create application in android which will block call recording.if someone has secretly install call recording app in my phone like virus or something then this app will restrict/prevent all call recording.
so my question is
Is there any way to block call recording?
Thank you in advance.
I think its possible!!! If one android device is running with two different call recording apps, the call will recorded by first app only, which will use the call recording resources in that device, rest of all apps will fail to record, because the resources can be used by one app at a time, its a computation, who will trigger to start using resources will gonna win..it can be your app!!
I'm just giving Idea only, not the perfect solution!!!
Sample code(Not Full code):
MediaRecorder recorder = new MediaRecorder();
Log.d(TAG, "RecordService will config MediaRecorder with audiosource: " + audiosource + " audioformat: " + audioformat);
try {
// These calls will throw exceptions unless you set the
// android.permission.RECORD_AUDIO permission for your app
recorder.reset();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
Log.d(TAG, "set encoder default");
recorder.setOutputFile(recording.getAbsolutePath());
Log.d(TAG, "set file: " + recording.getAbsolutePath());
//recorder.setMaxDuration(msDuration); //1000); // 1 seconds
//recorder.setMaxFileSize(bytesMax); //1024*1024); // 1KB
recorder.setOnInfoListener(this);
recorder.setOnErrorListener(this);
try {
recorder.prepare();
} catch (java.io.IOException e) {
Log.e(TAG, "RecordService::onStart() IOException attempting recorder.prepare()\n");
Toast t = Toast.makeText(getApplicationContext(), "CallRecorder was unable to start recording: " + e, Toast.LENGTH_LONG);
t.show();
recorder = null;
return; //return 0; //START_STICKY;
}
Log.d(TAG, "recorder.prepare() returned");
recorder.start();
isRecording = true;
Log.i(TAG, "recorder.start() returned");
//updateNotification(true);
} catch (java.lang.Exception e) {
Toast t = Toast.makeText(getApplicationContext(), "CallRecorder was unable to start recording: " + e, Toast.LENGTH_LONG);
t.show();
Log.e(TAG, "RecordService::onStart caught unexpected exception", e);
recorder = null;
}

Using MediaPlayer to play an AMR file created by MediaRecorder fails with muri null

I am writing an app that records voice from the microphone in AMR format using MediaRecorder, and then plays the data back using MediaPlayer.
That's the goal anyway.
I am fairly confident my MediaRecorder side is working, I'm producing the data file in the right place at the right data rate. Here's how I start and stop my MediaRecorder
public void OnStartRecord(View v )
{
System.out.println( "StartRecord");
try {
audioFile = File.createTempFile("amrtmp", ".amr", getApplicationContext().getFilesDir());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println( "Recording to " + audioFile.getAbsolutePath());
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setAudioEncodingBitRate(4750);
mRecorder.setAudioSamplingRate(8000);
mRecorder.setOutputFile(audioFile.getAbsolutePath());
try {
mRecorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mRecorder.start();
}
public void OnStopRecord(View v )
{
System.out.println( "StopRecord");
mRecorder.stop();
mRecorder.release();
}
This works like a charm. Typical output is something like
StartRecord
Recording to /data/data/com.test.playback/files/amrtmp-235967797.amr
And when I start, then stop recording I can see that the file has been created and it has a certain amount of data in it that properly corresponds to the settings.
Side note: I detect an odd buzzing at my speaker while this runs. Any idea what that is?
When I try to play the file back however I have no end of trouble. I have tried the following:
public void OnPlay(View v )
{
MediaPlayer mPlayer = new MediaPlayer();
mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
FileInputStream FIS = null;
try {
FIS = new FileInputStream(audioFile.getAbsolutePath());
mPlayer.setDataSource(FIS.getFD());
mPlayer.prepare();
}
catch( Exception e )
{
e.printStackTrace();
}
mPlayer.start();
}
This results in nothing being played at all with the following output from MediaPlayer:
start() mURI is null
I have also tried the same code, but setting mPlayer's data source differently:
mPlayer.setDataSource(audioFile.getAbsolutePath());
This fails when prepare is called witha java.io.IOException status 0x1.
I have to imagine there is something else I need to do with MediaPlayer to set it up properly. Any suggestions?

Mediarecorder start failed -19

I am getting this error when running start() for mediarecorder.
06-28 18:46:22.570: E/MediaRecorder(9540): start failed: -19
06-28 18:46:22.570: W/System.err(9540): java.lang.RuntimeException: start failed.
I am extending mediarecorder class
My code:
camera = Camera.open(cameraId);
super.setCamera(camera);
super.setVideoSource(MediaRecorder.VideoSource.CAMERA);
super.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
if (mode==MODE_DEFAULT) {
super.setMaxDuration(1000);
super.setMaxFileSize(Integer.MAX_VALUE);
} else {
// On some phones a RuntimeException might be thrown :/
try {
super.setMaxDuration(0);
super.setMaxFileSize(Integer.MAX_VALUE);
} catch (RuntimeException e) {
Log.e(TAG,"setMaxDuration or setMaxFileSize failed !");
}
}
super.setVideoEncoder(videoEncoder);
if(surfaceHolder!=null)
super.setPreviewDisplay(surfaceHolder.getSurface());
//super.setVideoSize(quality.resX,quality.resY);
super.setVideoFrameRate(quality.frameRate);
super.setVideoEncodingBitRate(quality.bitRate);
I saw these pages
Error opening android camera for streaming video
Android MediaRecorder - "start failed: -19"
But non of them worked for me...
Running on archos 80 g9, android 3.2
Any one got any ideas?
Fixed by removing
super.setVideoFrameRate(quality.frameRate);
I was facing the same proble during video recording and i solved it by adding this for video recording
/**
* Start video recording by cleaning the old camera preview
*/
private void startVideoRecorder() {
// THIS IS NEEDED BECAUSE THE GLASS CURRENTLY THROWS AN ERROR OF
// "MediaRecorder start failed: -19"
// THIS WONT BE NEEDED INCASE OF PHONE AND TABLET
// This causes crash in glass kitkat version so remove it
// try {
// mCamera.setPreviewDisplay(null);
// } catch (java.io.IOException ioe) {
// Log.d(TAG,
// "IOException nullifying preview display: "
// + ioe.getMessage());
// }
// mCamera.stopPreview();
// mCamera.unlock();
recorder = new MediaRecorder();
// Let's initRecorder so we can record again
initRecorder();
}
/**
* Initialize video recorder to record video
*/
private void initRecorder() {
try {
File dir = new File(folderPath);
if (!dir.exists()) {
dir.mkdirs();
}
mCamera.stopPreview();
mCamera.unlock();
videofile = new File(dir, fileName + ".mp4");
recorder.setCamera(mCamera);
// Step 2: Set sources
recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
recorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH));
// Step 4: Set output file
recorder.setOutputFile(videofile.getAbsolutePath());
// Step 5: Set the preview output
recorder.setPreviewDisplay(mPreview.getHolder().getSurface());
// Step 6: Prepare configured MediaRecorder
recorder.setMaxDuration(video_duration * 1000);
recorder.setOnInfoListener(new OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
mCamera.stopPreview();
releaseMediaRecorder();
/*
* initiate media scan and put the new things into the
* path array to make the scanner aware of the location
* and the files you want to see
*/MediaScannerConnection.scanFile(
CuxtomCamActivity.this,
new String[] { videofile.getPath() }, null,
null);
Intent intent = new Intent();
intent.putExtra(CuxtomIntent.FILE_PATH,
videofile.getPath());
intent.putExtra(CuxtomIntent.FILE_TYPE, FILE_TYPE.VIDEO);
setResult(RESULT_OK, intent);
finish();
}
}
});
recorder.prepare();
recorder.start();
} catch (Exception e) {
Log.e("Error Stating CuXtom Camera", e.getMessage());
}
}
private void releaseMediaRecorder() {
if (recorder != null) {
recorder.reset(); // clear recorder configuration
recorder.release(); // release the recorder object
recorder = null;
}
}
To see detail of how a camera is actually implemented refer to Open Source Cuxtom Cam
I found a subtle hint in documentation for the MediaRecorder.start() method that suggest if it fails to lock() the Camera before attempting to re-record. This worked for me. Implies a Camera state bug was fixed post API level 13 - calling Camera.lock() is the known workaround.
This code worked for me (found here)
mCamera.unlock(); // maybe not for your activity flow
//1st. Initial state
mProfile = CamcorderProfile.get( CamcorderProfile.QUALITY_HIGH );
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera( mCamera );
//2nd. Initialized state
mMediaRecorder.setAudioSource( MediaRecorder.AudioSource.CAMCORDER );
mMediaRecorder.setVideoSource( MediaRecorder.VideoSource.CAMERA );
//3rd. config
mMediaRecorder.setOutputFormat( mProfile.fileFormat );
mMediaRecorder.setAudioEncoder( mProfile.audioCodec );
mMediaRecorder.setVideoEncoder( mProfile.videoCodec );
mMediaRecorder.setOutputFile( "/sdcard/FBVideo.3gp" );
mMediaRecorder.setVideoSize( mProfile.videoFrameWidth, mProfile.videoFrameHeight );
mMediaRecorder.setVideoFrameRate( mProfile.videoFrameRate );
mMediaRecorder.setVideoEncodingBitRate( mProfile.videoBitRate );
mMediaRecorder.setAudioEncodingBitRate( mProfile.audioBitRate );
mMediaRecorder.setAudioChannels( mProfile.audioChannels );
mMediaRecorder.setAudioSamplingRate( mProfile.audioSampleRate );
mMediaRecorder.setPreviewDisplay( mHolder.getSurface() );
try {
mMediaRecorder.prepare();
mMediaRecorder.start();
} catch ( IllegalStateException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
}
The problem here is about the camera. Just use camera.unlock() to allow the media process to access the camera.
This must be done before calling MediaRecorder.setCamera(Camera). This cannot be called after recording starts.
Read more here.

Categories

Resources