Recording Audio using Android’s MediaRecorder Framework

Sometimes your app needs the ability to record and store audio files. As most devices come with a microphone it’s no surprise that Android offers app developers the possibility to do so. This post deals with the two most common ways to record audio on Android.

Recording audio using an Intent

As usual that’s by far the easiest option. You simply create the Intent object and check for its availability. When you have done so, start the Activity:

Intent intent = 
      new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
if (isAvailable(getApplicationContext(), intent)) {
   startActivityForResult(intent, 
         REQUESTCODE_RECORDING);
}

You have to use startActivityForResult() since you want to know which file has been created in your onActivityResult() method. REQUESTCODE_RECORDING is a final static int variable that you have to create. You can give it any name you like. The value of this field must be unique among all startActivityForResult() calls that you might want to use.

You need this int field again when checking for the result:

protected void onActivityResult(int requestCode, 
      int resultCode, Intent intent) {
   if (requestCode == REQUESTCODE_RECORDING) {
      if (resultCode == RESULT_OK) {
         Uri audioUri = intent.getData();
         // make use of this MediaStore uri 
         // e.g. store it somewhere
      }
      else {
         // react meaningful to problems
      }
   }
   else {
      super.onActivityResult(requestCode, 
            resultCode, intent);
   }
}

The standard activity to record audio looks like this:

Standard activity for audio recording

Standard activity for audio recording

Alas using an intent has the usual drawback: The intent might not be available. And, indeed, on my old LG Optimus One (P500) it doesn’t work :-(

So be sure to at least check for intent availability before trying to use it.

A problem with this solution is the location, that Android uses to store the recorded file. Android puts the file directly to the root of the SD card – something that often annoys users.

Doing it yourself

If you want to have more control over audio recording you could use the MediaRecorder.

But first you have to cover the basics – permissions. As usual you have to state that your app wants to record audio in the mainfest file. Add these lines to your AndroidManifest.xml:

<uses-permission 
      android:name="android.permission.RECORD_AUDIO" />

For the intent-based solution above you do not need this permission. But for using the MediaRecorder framework, you do. Without the correct permission you get an exception that is very misleading:

java.lang.RuntimeException: setAudioSource failed.

This is Android’s strange way to tell us, that we forgot to ask for this permission :-)

Using the MediaRecorder

Recording audio with the MediaRecorder requires you to adhere to the MediaRecorder's state transitions, so you have to be strict with the ordering of your operations. To start a recording you have to do the following steps:

  1. Create a MediaRecorder object
  2. State the source to use
  3. Set the file format
  4. Set the Encoding
  5. Prepare a file
  6. Start recording

And here it is in code:

MediaRecorder recorder = null;

private void startRecording(File file) {
   if (recorder != null) {
      recorder.release();
   }
   recorder = new MediaRecorder();
   recorder.setAudioSource(AudioSource.MIC);
   recorder.setOutputFormat(OutputFormat.THREE_GPP);
   recorder.setAudioEncoder(AudioEncoder.AMR_WB);
   recorder.setOutputFile(file.getAbsolutePath());
   try {
      recorder.prepare();
      recorder.start();
   } catch (IOException e) {
      Log.e("giftlist", "io problems while preparing [" +
            file.getAbsolutePath() + "]: " + e.getMessage());
   }
}

You need the MediaRecorder object later on to stop the recording and to clean up, so you have to use an instance variable for it.

Please follow Android’s best practices about storing files. In most cases your app-specific folder is the best choice for recorded files.

What could go wrong?

Now the order in which you call the methods of the MediaRecorder object is very important. If you stick with the order of the code snippet above, all is fine. If not you will see one of the following exceptions or messages in your log file:

  • java.lang.IllegalStateException
    Happens when you do not follow the order above, miss some important steps or when prepare() failed, but you continue anyway. The latter is where it is most likely to go wrong. You should only call start() when prepare() did exit without exceptions. Otherwise you will get an IllegalStateException. Since it is a RuntimeException you might not catch it and your app will force close. That’s where the documentation sample code is misleading.
  • mediarecorder went away with unhandled events
    Happens when you release the Mediarecorder object while events were still being processed or queued. No need to worry, though. Everything went fine anyway – this message is just to notify you about this.
  • Fatal signal 11 (SIGSEGV)
    That’s a really bad one. Not a Force close, but your app simply vanishes and then restarts. This segmentation fault can occur when you call release() and still use the object afterwards.
    Can also happen if you call reset() on a MediaRecorder object that hasn’t even been prepared. The next method call on the MediaRecorder object will cause the segmentation fault to occur.

An example of what could go wrong: I tried to optimize above code by just calling reset() at the start of the method when the recorder object already exists. All nice and dandy if never ever anything goes wrong. But if for example the prepare stage goes wrong, this optimization fails miserably (segmentation fault again). That’s why I got rid of it and now simply call release() before creating a new MediaRecorder object.

Stopping the recording

With stopping you have to follow the ordering of the state chart in MediaRecorder’s documentation again. But since there are only two steps, this is easy:

private void stopRecording() {
   if (recorder != null) {
      recorder.stop();
      recorder.release();
      recorder = null;
   }
}

Releasing resources

When everything is done, you have to release resources. You should do so in the onPause() method of your activity, as you can see in the next snippet:

protected void onPause() {
   super.onPause();
   if (recorder != null) {
      recorder.release();
      recorder = null;
   }
}

Summary

You have seen how to leverage the RECORD_SOUND_ACTION action to use an intent for recording. Since this intent is not always available, or because you might want to present another UI, you can also use the MediaRecorder framework directly.

There is an even more fine-grained way to record audio in Android by using AudioRecord. This class allows you to deal with raw audio data. I will not go into this since it should be of interest only to few developers.

Share this article:

You can leave a response, or trackback from your own site.

15 Responses to “Recording Audio using Android’s MediaRecorder Framework”

  1. Doug Ponsford says:

    Hi, That was very useful – are you planning a similar one for recording video?

    Doug.

  2. Sush says:

    Hi,

    It is really helpful, but I have a doubt.

    1. Why are you releasing the media recorder before even creating the MediaRecorder object? Even if a MediaRecorder object reference exists, will it not be over written when you call new MediaRecorder()?

    2. For me it happens sometimes that, even if prepare passes without any exception, start fails with illegalStateException. Can you imagine some reason why it should happen!!

    Thanks
    Sush

    • About the release() method I prefer to err on the safe side. The MediaRecorder is mostly a Java wrapper for native methods. So I guess it’s better to release properly.

      About the exception. First of all: Do not continue when prepare failed. You cannot start recording when the prepare step went wrong. You might als want to implement OnInfoListeners and OnErrorListeners to get more information.

  3. Yasir says:

    Sir I am New in java plz can u send me the exact code to record a voice message and save it and also send it as a Mms.Plz sir help me for this.Will be thankful.

  4. KK REDDY says:

    CALL RECORDING IS VERY ERRATIC AND UNRELAIBLE ON ANDROID PROGRAMMATICALLY.
    ISSUES ARE:

    1. NOT SUPPORTED BY ALL PHONES(I.E OR CODE MIGHT WORK ON SOME , MAYNOT ON SOME OTHER)

    2. EVEN IF U RECORD THE RECORDING FILE MAY AT TIMES NOT CONTAIN THE RECORDING OF WHOLE CALL DURATION. I.E IF U LISTEN THE RECORDED FILE IT WILL BE ENDED IN THE MIDST OF THE CALL, TOTAL RECORDING NOT COMING UP

    3. IT IS NOT PERMITTED IN CERTAIN COUNTRIES

  5. AnujD says:

    Hi Wolfram! Thanks for this nice tutorial… The way you have presented it makes it really easy. :-)
    I want to make Recorder work in Background, will this code work in a Service?

  6. jayaraj says:

    How can we pause and resume an audio recording

  7. AnujD says:

    Hey! Now only one problem. Above code will create a 3gp file. How to record in AMR format? I tried it but can’t get it done correctly. Please help. Thanks.

Leave a Reply

You can also subscribe without commenting.

Subscribe to RSS Feed My G+-Profile Follow me on Twitter!