Other Media Recorder Methods

Appportunity

Build your own Android App Dev Empire

Get Instant Access

MediaRecorder has a variety of other methods available that we can use in relation to audio capture.

■ getMaxAmplitude: Allows us to request the maximum amplitude of audio that has been recorded by the MediaPlayer. The value is reset each time the method is called, so each call will return the maximum amplitude from the last time it is called. An audio level meter may be implemented by calling this method periodically.

■ setMaxDuration: Allows us to specify a maximum recording duration in milliseconds. This method must be called after the setOutputFormat method but before the prepare method.

■ setMaxFileSize: Allows us to specify a maximum file size for the recording in bytes. As with setMaxDuration, this method must be called after the setOutputFormat method but before the prepare method.

Here is an update to the custom recorder application we went through previously that includes a display of the current amplitude.

package com.apress.proandroidmedia.ch07.customrecorder;

import java.io.File; import java.io.IOException;

import android.app.Activity;

import android.media.MediaPlayer;

import android.media.MediaRecorder;

import android.media.MediaPlayer.OnCompletionListener;

import android.os.AsyncTask;

import android.os.Bundle;

import android.os.Environment;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

public class CustomRecorder extends Activity implements OnClickListener, OnCompletionListener {

In this version, we have added a TextView called amplitudeTextView. This will display the numeric amplitude of the audio input.

TextView statusTextView, amplitudeTextView;

Button startRecording, stopRecording, playRecording, finishButton;

MediaRecorder recorder;

MediaPlayer player;

File audioFile;

We'll need an instance of a new class called RecordAmplitude. This class is an inner class that is defined toward the end of this source code listing. It uses a Boolean called isRecording that will be set to true when we start the MediaRecorder.

RecordAmplitude recordAmplitude; boolean isRecording = false;

^Override public void onCreate(Bundle savedlnstanceState) { super.onCreate(savedlnstanceState); setContentView(R.layout.main);

statusTextView = (TextView) this.findViewByld(R.id.StatusTextView); statusTextView.setText("Ready");

We'll use a TextView to display the current amplitude of the audio as it is captured.

amplitudeTextView = (TextView) this

.findViewByld(R.id.AmplitudeTextView); amplitudeTextView.setText("0");

stopRecording = (Button) this.findViewByld(R.id.StopRecording); startRecording = (Button) this.findViewByld(R.id.StartRecording); playRecording = (Button) this.findViewByld(R.id.PlayRecording); finishButton = (Button) this.findViewByld(R.id.FinishButton);

startRecording.setOnClickListener(this); stopRecording.setOnClickListener(this); playRecording.setOnClickListener(this); finishButton.setOnClickListener(this);

stopRecording.setEnabled(false); playRecording.setEnabled(false);

public void onClick(View v) { if (v == finishButton) {

When we finish the recording, we set the isRecording Boolean to false and call cancel on our RecordAmplitude class. Since RecordAmplitude extends AsyncTask, calling cancel with true as the parameter will interrupt its thread if necessary.

isRecording = false; recordAmplitude.cancel(true);

recorder.stop(); recorder.release();

player = new MediaPlayer(); player.setOnCompletionListener(this); try {

player.setDataSource(audioFile.getAbsolutePath()); } catch (IllegalArgumentException e) { throw new RuntimeException(

"Illegal Argument to MediaPlayer.setDataSource", e); } catch (IllegalStateException e) { throw new RuntimeException(

"Illegal State in MediaPlayer.setDataSource", e); } catch (IOException e) {

throw new RuntimeException(

"IOException in MediaPalyer.setDataSource", e);

player.prepare(); } catch (IllegalStateException e) { throw new RuntimeException(

"IllegalStateException in MediaPlayer.prepare", e); } catch (IOException e) {

throw new RuntimeException(

"IOException in MediaPlayer.prepare", e);

statusTextView.setText("Ready to Play");

playRecording.setEnabled(true);

stopRecording.setEnabled(false);

startRecording.setEnabled(true);

} else if (v == startRecording) { recorder = new MediaRecorder();

recorder.setAudioSource(MediaRecorder.AudioSource.MIC);

recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);

recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

File path = new File^nvironment.getExternalStorageDirectoryQ'*'

.getAbsolutePath() + "/Android/data/com.apress.proandroidmedia.ch07'ta .customrecorder/files/");

audioFile = File.createTempFile("recording", ".3gp", path); } catch (IOException e) {

throw new RuntimeException(

"Couldn't create recording audio file", e);

recorder.setOutputFile(audioFile.getAbsolutePath());

recorder.prepare(); } catch (IllegalStateException e) { throw new RuntimeException(

"IllegalStateException on MediaRecorder.prepare", e); } catch (IOException e) {

throw new RuntimeException(

"IOException on MediaRecorder.prepare", e);

recorder.start();

After we start the recording, we set the isRecording Boolean to true and create a new instance of RecordAmplitude. Since RecordAmplitude extends AsyncTask, we'll call the execute method to start the RecordAmplitude's task running.

isRecording = true;

recordAmplitude = new RecordAmplitude(); recordAmplitude.execute();

statusTextView.setText("Recording");

playRecording.setEnabled(false); stopRecording.setEnabled(true); startRecording.setEnabled(false); } else if (v == playRecording) { player.start();

statusTextView.setText("Playing"); playRecording.setEnabled(false); stopRecording.setEnabled(false); startRecording.setEnabled(false);

public void onCompletion(MediaPlayer mp) { playRecording.setEnabled(true); stopRecording.setEnabled(false); startRecording.setEnabled(true); statusTextView.setText("Ready");

Here is the definition of RecordAmplitude. It extends AsyncTask, which is a nice utility class in Android that provides a thread to run long-running tasks without tying up the user interface or making an application unresponsive.

private class RecordAmplitude extends AsyncTask<Void, Integer, Void> {

The doInBackground method runs on a separate thread and is run when the execute method is called on the object. This method loops as long as isRecording is true and calls Thread.sleep(500), which causes it to not do anything for half a second. Once that is complete, it calls publishProgress and passes in the result of getMaxAmplitude on the MediaRecorder object.

@Override protected Void doInBackground(Void... params) { while (isRecording) {

Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace();

publishProgress(recorder.getMaxAmplitude());

return null;

The preceding call to publishProgress calls the onProgressUpdate method defined here, which runs on the main thread so it can interact with the user interface. In this case, it is updating the amplitudeTextView with the value that is passed in from the publishProgress method call.

protected void onProgressUpdate(Integer... progress) { amplitudeTextView.setText(progress[0].toString());

Of course, we'll need to update the layout XML to include the TextView for displaying the amplitude.

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<TextView android:layout_width="wrap_content" android:layout_height=^ "wrap_content" android:id="@+id/StatusTextView" android:text="Status"^ android:textSize="35dip"></TextView>

<TextView android:layout_width="wrap_content" android:layout_height=^ "wrap_content" android:id="@+id/AmplitudeTextView" android:textSize="35dip"^ android:text="0"></TextView>

<Button android:text="Start Recording" android:id="@+id/StartRecording"^ android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

<Button android:text="Stop Recording" android:id="@+id/StopRecording"^ android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

<Button android:text="Play Recording" android:id="@+id/PlayRecording"^ android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

<Button android:layout_width="wrap_content" android:layout_height=^ "wrap_content" android:id="@+id/FinishButton" android:text="Finish"></Button> </LinearLayout>

As we can see, using an AsyncTask to do something periodically is a nice way to provide automatically updating information to the user while something else is in progress. This provides a nicer user experience for our MediaRecorder example. Using the getMaxAmplitude method provides the user with some feedback about the recording that is currently happening.

In Android 2.2, Froyo, the following methods were made available:

■ setAudioChannels: Allows us to specify the number of audio channels that will be recorded. Typically this will be either one channel (mono) or two channels (stereo). This method must be called prior to the prepare method.

■ setAudioEncodingBitRate: Allows us to specify the number of bits per second that will be used by the encoder when compressing the audio. This method must be called prior to the prepare method.

■ setAudioSamplingRate: Allows us to specify the sampling rate of the audio as it is captured and encoded. The applicable rates are determined by the hardware and codec being used. This method must be called prior to the prepare method.

Was this article helpful?

0 -2

Responses

  • cailyn
    When will android release amplitude?
    8 years ago
  • charlie
    How to trace whether max recording time is completed in android mediarecorder?
    8 years ago
  • bryan
    How to show progress while using mediarecorder in android?
    8 years ago
  • Tyler
    How to get the amplitude from an recorder object in android?
    7 years ago
  • sarah
    How to use mediarecorder with asynk task?
    2 years ago

Post a comment