
Creating Your Own Android Voice Recorder Using Kotlin
- Transfer
- Tutorial
The Android multimedia framework supports audio recording and playback. In this article, I will show how to develop a simple recording application that will record audio and save it to the local storage of an Android device using MediaRecorder
the Android SDK.
You will also learn how to request permissions from a user in real time and how to work with the local storage of an Android device.
User Interface Creation
First we need to create an interface for sound recording. This is a simple three-button layout that will be used to start, pause / resume, and stop recording.
Request Permissions Required
After creating the user interface, we can start using it MediaRecorder
to implement the basic functionality of our application. But first, we need to request the necessary permissions to record audio and access local storage. We will do this with a few simple lines of code in our file AndroidManifest.xml
:
You also need to check if the user has approved the permissions before we can use ours MediaRecorder
. Let's do it in Activity MainActivity.kt
:
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
val permissions = arrayOf(android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE)
ActivityCompat.requestPermissions(this, permissions,0)
}
Note: later these lines of code will be moved to the OnClickListener
start button of the audio recording so that we can make sure that MediaRecorder
it will not be launched without the necessary permissions.
Record and save audio
Adding OnClickListeners
Add listeners to the buttons so that they respond to user events. As I mentioned earlier, a check for the necessary permissions will be added to the OnClickListener of the audio recording start button:
button_start_recording.setOnClickListener {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
val permissions = arrayOf(android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE)
ActivityCompat.requestPermissions(this, permissions,0)
} else {
startRecording()
}
}
button_stop_recording.setOnClickListener{
stopRecording()
}
button_pause_recording.setOnClickListener {
pauseRecording()
}
Configure MediaRecorder
Next, we need to specify the path to save the audio and configure MediaRecorder.
private var output: String? = null
private var mediaRecorder: MediaRecorder? = null
private var state: Boolean = false
private var recordingStopped: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
output = Environment.getExternalStorageDirectory().absolutePath + "/recording.mp3"
mediaRecorder = MediaRecorder()
mediaRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
mediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
mediaRecorder?.setOutputFile(output)
}
We take the path to the root of our external storage and add the name of our record and file type to it. After that, we create an object MediaRecorder
and determine the sound source, audio encoder, format and file for recording.
Record and save audio
The code used to start MediaRecorder
is defined in the OnClickListener
audio recording start button:
private fun startRecording() {
try {
mediaRecorder?.prepare()
mediaRecorder?.start()
state = true
Toast.makeText(this, "Recording started!", Toast.LENGTH_SHORT).show()
} catch (e: IllegalStateException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
As you can see, you need to call the function prepare
before we can start recording. We also embed the call into the try-catch block so that the application does not break when the function fails prepare
.
OnClickListeners
The record stop button is very similar to the code above.
private fun stopRecording() {
if (state) {
mediaRecorder?.stop()
mediaRecorder?.release()
state = false
} else {
Toast.makeText(this, "You are not recording right now!", Toast.LENGTH_SHORT).show()
}
}
Here we check whether it is working at the moment MediaRecorder
before we stop recording because our application will break if the method stop
is called while it MediaRecorder
will not start. After that, we change the state variable to false
so that the user cannot press the stop button again.
It remains OnClickListener
for us to define for the pause / resume button.
@SuppressLint("RestrictedApi", "SetTextI18n")
@TargetApi(Build.VERSION_CODES.N)
private fun pauseRecording() {
if (state) {
if (!recordingStopped) {
Toast.makeText(this,"Stopped!", Toast.LENGTH_SHORT).show()
mediaRecorder?.pause()
recordingStopped = true
button_pause_recording.text = "Resume"
} else {
resumeRecording()
}
}
}
@SuppressLint("RestrictedApi", "SetTextI18n")
@TargetApi(Build.VERSION_CODES.N)
private fun resumeRecording() {
Toast.makeText(this,"Resume!", Toast.LENGTH_SHORT).show()
mediaRecorder?.resume()
button_pause_recording.text = "Pause"
recordingStopped = false
}
In these two methods, we check to see if it works MediaRecorder
. If it works, we will pause recording and change the button text to resume. Pressing it again will resume recording.
Finally, we can record audio and listen to it by opening a file recording.mp3
that will be saved in our local storage. Just open the file explorer and search by file name recording.mp3
.
Source
Here is the full source code of our application:
package com.example.android.soundrecorder
import android.Manifest
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.content.pm.PackageManager
import android.media.MediaRecorder
import android.os.Build
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import java.io.IOException
class MainActivity : AppCompatActivity() {
private var output: String? = null
private var mediaRecorder: MediaRecorder? = null
private var state: Boolean = false
private var recordingStopped: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mediaRecorder = MediaRecorder()
output = Environment.getExternalStorageDirectory().absolutePath + "/recording.mp3"
mediaRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
mediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
mediaRecorder?.setOutputFile(output)
button_start_recording.setOnClickListener {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
val permissions = arrayOf(android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE)
ActivityCompat.requestPermissions(this, permissions,0)
} else {
startRecording()
}
}
button_stop_recording.setOnClickListener{
stopRecording()
}
button_pause_recording.setOnClickListener {
pauseRecording()
}
}
private fun startRecording() {
try {
mediaRecorder?.prepare()
mediaRecorder?.start()
state = true
Toast.makeText(this, "Recording started!", Toast.LENGTH_SHORT).show()
} catch (e: IllegalStateException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
@SuppressLint("RestrictedApi", "SetTextI18n")
@TargetApi(Build.VERSION_CODES.N)
private fun pauseRecording() {
if (state) {
if (!recordingStopped) {
Toast.makeText(this,"Stopped!", Toast.LENGTH_SHORT).show()
mediaRecorder?.pause()
recordingStopped = true
button_pause_recording.text = "Resume"
} else {
resumeRecording()
}
}
}
@SuppressLint("RestrictedApi", "SetTextI18n")
@TargetApi(Build.VERSION_CODES.N)
private fun resumeRecording() {
Toast.makeText(this,"Resume!", Toast.LENGTH_SHORT).show()
mediaRecorder?.resume()
button_pause_recording.text = "Pause"
recordingStopped = false
}
private fun stopRecording(){
if (state) {
mediaRecorder?.stop()
mediaRecorder?.release()
state = false
} else {
Toast.makeText(this, "You are not recording right now!", Toast.LENGTH_SHORT).show()
}
}
}
Conclusion
Now you know how it works MediaRecorder
, how to request real-time permissions, and why it is important to do so. You also learned about the local storage of your Android device and how to store data in it.
A more complex version of this application, which has some additional features, such as playing your recordings with MediaPlayer
, is available on Github .