본문으로 건너뛰기

Audio Recording examples - Android

Audio recording is a common feature in many Android applications. The Android platform provides a built-in class called AudioRecord to capture audio data from the device's microphone. However, using this class can be a bit complicated for some developers. To simplify the process, Android provides a higher-level class called AudioRecorder.

In this article, we will explore the AudioRecorder class in Android and show you how to use it in your applications.

Prerequisites

To follow along with this tutorial, you should have a basic understanding of Android app development and the Kotlin programming language.

Setting Up

Create a new Android project in Android Studio. Choose an appropriate name for your project and select Kotlin as the programming language.

Using AudioRecorder

The AudioRecorder class provides a simple interface for recording audio data from the device's microphone. To use this class, we need to follow these steps:

Step 1: Request Permission

Before we can use the microphone to record audio, we need to request permission from the user. Add the following code to your AndroidManifest.xml file to request the RECORD_AUDIO permission:

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

Next, add the following code to your activity to request permission from the user:

private val REQUEST_RECORD_AUDIO_PERMISSION = 200
private var isRecording = false
private var recorder: AudioRecorder? = null
private var recordingThread: Thread? = null

private val permissions = arrayOf(Manifest.permission.RECORD_AUDIO)

private fun requestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissions, REQUEST_RECORD_AUDIO_PERMISSION)
} else {
startRecording()
}
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startRecording()
} else {
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show()
}
}
}

Step 2: Start Recording

Once we have permission to use the microphone, we can start recording. Add the following code to your activity to start recording:

private fun startRecording() {
recorder = AudioRecorder()
recorder?.start()

isRecording = true
recordingThread = Thread(Runnable { writeAudioDataToFile() }, "AudioRecorder Thread")
recordingThread?.start()
}

The AudioRecorder class provides a start() method to start recording audio. We also create a new thread to write audio data to a file.

Step 3: Write Audio Data to File

We need to write the audio data to a file to save it. Add the following code to your activity to write audio data to a file:

private fun writeAudioDataToFile() {
val data = ByteArray(recorder?.getBufferSize() ?: 0)
val filePath = "${externalCacheDir?.absolutePath}/audio.3gp"
val os = FileOutputStream(filePath)

while (isRecording) {
val read = recorder?.read(data, 0, data.size) ?: 0
if (read > 0) {
os.write(data)
}
}

os.close()
}

We create a new byte array to hold the audio data, and we use a FileOutputStream to write the data to a file. We keep writing data to the file until the recording is stopped.

Step 4: Stop Recording

Once we're done recording, we need to stop the recording and release resources. Add the following code to your activity to stop recording:

private fun stopRecording() {
isRecording = false

recorder?.stop()
recorder?.release()
recorder = null

recordingThread = null
}

We set the isRecording flag to false to stop the recording thread. We also release the AudioRecorder resources.

Step 5: Request Permission and Start Recording

Finally, we need to request permission and start recording when the user clicks a button. Add the following code to your activity to handle the button click:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

button.setOnClickListener {
if (isRecording) {
stopRecording()
} else {
requestPermissions()
}
}
}

We check if we're currently recording audio. If we are, we stop recording. If we're not, we request permission to use the microphone and start recording.

More Examples

Let us look at more examples:

Example 1: Record and Play Audio

This is a simple example written in Java that will allow you record audio in android then play the recorded audio.

Step 1: Create Project

Start by creating an empty Android Studio project.

Step 2: Dependencies

No third party dependencies are needed:

    implementation "androidx.appcompat:appcompat:$appCompat"
implementation "com.google.android.material:material:$supportLibVer"

Step 3: Add Necessary Permissions

Because we are recording and saving audio in our device we need two permissions: WRITE_EXTERNAL_STORAGE and RECORD_AUDIO. Add them in your app/src/main/AndroidManifest.xml:

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

Step 4: Design Layout

Create your activity_main.xml layout as follows: Add two floating action buttons: one for recording the audio and the other for playing.

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="github.nisrulz.audiorecording.MainActivity">

<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>

</com.google.android.material.appbar.AppBarLayout>

<include layout="@layout/content_main"/>

<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="80dp"
android:layout_marginRight="24dp"
android:src="@drawable/ic_play"
app:fabSize="mini"/>

<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_rec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_mic"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Step 4: Record Audio

We start by writing code that will allow us record audio. Create a file known as RecordAudio.java and import android.media.MediaRecorder:

import android.media.MediaRecorder;
import android.util.Log;
import java.io.IOException;

Create the class:

public class RecordAudio {

Define some properties as follows:

    private final String LOGTAG = getClass().getSimpleName().toString();
MediaRecorder mRecorder = null;
private boolean isRecording = false;

Here is the function to release resources occupied by the MediaRecorder:

    void releaseMediaRecorder() {
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
Log.i(LOGTAG, "Recorder Released");
}
isRecording = false;
}

Here is the function that will allow us start recording:

    void startRecording(String mFileName) {
if (!isRecording) {
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(LOGTAG, "prepare() failed");
}

mRecorder.start();
Log.i(LOGTAG, "Recording Started");
isRecording = true;
}
}

And here is the function that will allow us stop recording:

    void stopRecording() {
try {
if (mRecorder != null) {
mRecorder.stop();
Log.i(LOGTAG, "Recording Stopped");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mRecorder != null)
mRecorder.reset();
releaseMediaRecorder();
}
}

This function will check if we are currently recording or not:

    boolean isRecording() {
return isRecording;
}
}

Here is the full code:

RecordAudio.java

import android.media.MediaRecorder;
import android.util.Log;

import java.io.IOException;

public class RecordAudio {
private final String LOGTAG = getClass().getSimpleName().toString();
MediaRecorder mRecorder = null;
private boolean isRecording = false;

void releaseMediaRecorder() {
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
Log.i(LOGTAG, "Recorder Released");
}
isRecording = false;
}

void startRecording(String mFileName) {
if (!isRecording) {
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(LOGTAG, "prepare() failed");
}

mRecorder.start();
Log.i(LOGTAG, "Recording Started");
isRecording = true;
}
}

void stopRecording() {
try {
if (mRecorder != null) {
mRecorder.stop();
Log.i(LOGTAG, "Recording Stopped");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mRecorder != null)
mRecorder.reset();
releaseMediaRecorder();
}
}

boolean isRecording() {
return isRecording;
}
}

Step 5: Play Audio

Let us now write code to help us play the recorded audio. Create the PlayAudio.java file and add android.media.MediaPlayer as one of the imports. To play audio we use the MediaPlayer class:

import android.media.MediaPlayer;
import android.util.Log;
import java.io.IOException;

Now create teh class:

public class PlayAudio {

MediaPlayer will be one of the fields in this class:

    private final String LOGTAG = getClass().getSimpleName().toString();
private boolean isPlaying = false;
MediaPlayer mPlayer = null;

Here is how you release the MediaPlayer:

    void releaseMedidaPalyer() {
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
Log.i(LOGTAG, "Audio Player Released");
}
}

Here is how you play the audio using the MeidaPlayer provided we are passed the file name:

    void startPlaying(String mFileName) {
if (!isPlaying) {
mPlayer = new MediaPlayer();
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
stopPlaying();
isPlaying = false;

}
});
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
if (!mPlayer.isPlaying())
mPlayer.start();
Log.i(LOGTAG, "Audio Player Started");
} catch (IOException e) {
Log.e(LOGTAG, "prepare() failed");
}

isPlaying = true;

}
}

And here is how we stop playing the audio using the stop function, then invoke the reset():

    void stopPlaying() {
mPlayer.stop();
mPlayer.reset();
Log.i(LOGTAG, "Audio Player Stopped");
releaseMedidaPalyer();
isPlaying = false;
}

boolean isPlaying() {
return isPlaying;
}
}

Here is the full code:

PlayAudio.java

import android.media.MediaPlayer;
import android.util.Log;

import java.io.IOException;

public class PlayAudio {
private final String LOGTAG = getClass().getSimpleName().toString();
private boolean isPlaying = false;
MediaPlayer mPlayer = null;

void releaseMedidaPalyer() {
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
Log.i(LOGTAG, "Audio Player Released");
}
}

void startPlaying(String mFileName) {
if (!isPlaying) {
mPlayer = new MediaPlayer();
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
stopPlaying();
isPlaying = false;

}
});
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
if (!mPlayer.isPlaying())
mPlayer.start();
Log.i(LOGTAG, "Audio Player Started");
} catch (IOException e) {
Log.e(LOGTAG, "prepare() failed");
}

isPlaying = true;

}
}

void stopPlaying() {
mPlayer.stop();
mPlayer.reset();
Log.i(LOGTAG, "Audio Player Stopped");
releaseMedidaPalyer();
isPlaying = false;
}

boolean isPlaying() {
return isPlaying;
}
}

Step 6: MainActivity

Here is the MainActivity:

import android.os.Bundle;
import android.os.Environment;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private String LOGTAG = getClass().getSimpleName().toString();
String mFileName = null;

RecordAudio recordAudio = new RecordAudio();
PlayAudio playAudio = new PlayAudio();

TextView txt;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecord.3gp";

final FloatingActionButton fab_rec = (FloatingActionButton) findViewById(R.id.fab_rec);
txt=(TextView)findViewById(R.id.txt);

txt.setText("Press and hold record button to record");

fab_rec.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
txt.setText("Recording Started");
recordAudio.startRecording(mFileName);
break;
case MotionEvent.ACTION_UP:
txt.setText("Press and hold record button to record\nRecording Stopped");
recordAudio.stopRecording();
break;
}
return true;
}
});

FloatingActionButton fab_play = (FloatingActionButton) findViewById(R.id.fab_play);
fab_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (playAudio.isPlaying()) {
txt.setText("Press and hold record button to record\nAudio play stopped");
playAudio.stopPlaying();
} else {
txt.setText("Audio play started");
playAudio.startPlaying(mFileName);
}
}
});
}

@Override
public void onPause() {
super.onPause();

recordAudio.releaseMediaRecorder();
playAudio.releaseMedidaPalyer();
}
}

Run

Copy the code or download it in the link below, build and run.

Reference

Here are the reference links:

NumberLink
1.Download Example
2.Follow code author
3.Code: Apache 2.0 License

Conclusion

In this article, we explored the AudioRecorder class in Android and showed you how to use it to record audio data from the device's microphone. We also showed you how to request permission, start recording, write audio data to a file, and stop recording. We hope you found this tutorial helpful!