COYO Hackathon: Audio Messages (for the Android platform)
By: Alexander Prodan
Tags: Android, Software Development, Mobile, Hackathons, Mobile App Development

1. General Idea

My employer COYO offers a mobile app called ‘Engage’ that lets employees easily communicate with each other including a messaging functionality like you might know from WhatsApp or other messengers.

One very commonly asked feature is Audio Messages. This is extremely useful especially when you quickly want to share something without tipping endless texts.

As part of a 3-days Hackathon I decided to add this little nice feature to our app for the Android platform without relying too much on any libraries and instead using plain Android functionality. The app is entirely written in Kotlin. The basic messaging functionality is already implemented. We will focus on adding audio messages here.

The feature basically has the following requirements:

The user is able to record his own voice and send it as a message

The user can listen to his own and received audio messages

The user sees a progress bar for the duration

The user can jump to a specific point of the audio message

Given situation:

The chat part of the app is based on a general Recycler View Component. Each message type is presented by a different view holder in the respective adapter. There already exist types like pure text messages, pictures & messages with attachments. Now we want to add a new message type for audio messages.

In order to get a general idea how it looks like and where we are going to end have a look on the following screenshot:

We got a microphone in the input bar of the chat to start the recording and a message with a play button to play the actual recording.

2. Implementation part

2.1 Playing audio records

In our respective onCreateViewHolder method of the respective adapter used for the recycler view we are going to consider a new ViewHolder type for our audio messages:

The general layout we use for our message is based on a linear layout. We are going to add some views to our layout.

Our pressPlay View which will initialize as button view later on to start and stop the played audio message. Moreover we add a seekbar view that shows the progress respectively the recent position of the audio playing.

For the actual audio playing we introduce a plain MediaPlayer. There might exist better players i.e. https://github.com/google/ExoPlayer for more functionality but the plain Android MediaPlayer provides everything we need here right now.

In our case we might want to play audio from a received message or a local recording. In order to consider both cases we are looking for the URI first which in our case might a path to file on the web or a local URI i.e. for a locally created record or available audio file.

Now comes the most trickiest part — showing the progress in the seekbar! Unfortunately Android provides nothing out of the box here, so we are going to implement our visualization on our own which looks like that:

2.1.1 Get the current position in the audio record and apply it to the progress of our seekbar

What this does is basically getting the overall duration of the audio record. Accordingly we are going to apply the current position of the audio to the progress attribute of the seekbar! Important to mention here is that we do that using a coroutine on a different context to not block the UI Thread of the app here! Otherwise the user is not able to do anything here while the audio record keeps playing.

As you might know you cannot reference and update a view straight from a coroutine or other thread. For this we use view.post that updates the view accordingly on the UI Thread.

2.1.2 Apply a seekbar change listener to jump to the current position of the audio record

onProgressChanged helps us to determine the current position of the seekbar progress — not the audio record. When it stays 0 zero or the total duration of the audio is reached we show the play button otherwise a pause button. (we use the same button view but just switch the background here)

onStopTrackingTouch determines the users taps somewhere in the progress bar. Accordingly we apply the progress position to our MediaPlayer and it continues to play from that respective position. Now we are able to jump back and forth in the audio record.

If you would like to know more about the MediaPlayer and the Seekbar you can find it right here:

https://developer.android.com/reference/android/media/MediaPlayer

https://developer.android.com/reference/android/widget/SeekBar

2.2 Recording audio

Again we are using plain Android components here. Before the app is actually able to use the Android audio recording functionality we need to add the following to our AndroidManifest:

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

Moreover we add an instance of the Android MediaRecorder class to our service class that keeps track of the recording functionality. More information regarding the recorders functionality can be found here:

https://developer.android.com/reference/android/media/MediaRecorder

Afterwards we added a basic ImageButton here with a microphone to our chat input bar.

The functionality is very basic. If the user taps on the microphone the recording starts. A second tap ends the recording. We use a basic clickHandler here that is associated to our microphone view.

The recording is saved on the local storage for our device as an m4a file.

The startRecordingAudio method looks like that:

What is very important to mention here is that the user is asked to confirm the apps access permission to be able record audio on the device once he starts using the functionality for the first time.

Accordingly we set the audio input source with,

setAudioSource(MediaRecorder.AudioSource.MIC)

define the output format for the record

setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)

and set a common used encoder

setAudioEncoder(MediaRecorder.AudioEncoder.AAC)

The stopRecording method looks like that:

The recorder stops recording and we add the generated file as an attachment to our created chat message.That’s it!

3. Summary

After finding out how those Android components like Seekbar, MediaRecorder & Player work in particular, the remaining implementation in our apps context was very straight-forward.

I recommend to simply start using those components and play a bit around with it! Moreover there exist a lot of basic tutorials and code snippets on all known platforms. I hope you enjoyed my article and get some useful insights for your next app project. Take care!

Alex