Audio Playback Capture in Android X

Learn how to integrate the Android Playback Capture API into your app, allowing you to record and play back audio from other apps. By Evana Margain Puig.

4.8 (4) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Listening to Recorded Audio

Great! Now that your app captures playback audio, the only step you’re missing is being able to listen to the audio content you saved.

You’ll do this in the other tab at the bottom of the app, List of Audios.

Getting the Files From Memory

You need to get the captured files from your device’s memory.

Open RecordingListFragment.kt located in com.raywenderlich.android.cataudio/UI. Next, locate a TODO prompting you to create a function for this and add:

 private fun createItems() {
    // 1
    val files = File(context?.getExternalFilesDir(null), "/AudioCaptures")
    items.clear()

    if (files.listFiles() != null) {
      val file : Array<File> = files.listFiles()!!

      // 2
      for (i in file.indices) {
        items.add(Pair(file[i], i))
      }
    } else {
      Log.d("Files", "No files")
    }
  }

Now, review what the code above does:

  1. First, you retrieve the directory where the files are.
  2. Then you add them to an array called items.

You also need to add a call in resetUI. Look for the TODO indicating where you should add:

createItems()

The items array doesn’t exist yet. You’ll find a TODO indicating where to do it. Add this:

private var items: MutableList<Pair<File, Int>> = ArrayList()

Lastly, you need to display the items in your recycler view. Locate the last TODO item inside onCreateView and add a call to createItems:

createItems()

Just below the code you just added, substitute DummyContent.ITEMS for your items variable.

Now that you’ve made this change, you’ll get an error in the adapter.

To fix this, open MyItemRecyclerViewAdapter and change values‘ type from List of DummyItems to List of File. The code should look like this:

 private val values: List<Pair<File, Int>>)

Add the following import as well:

import java.io.File

Now, onBindViewHolder is complaining because the properties in the files are different than they were with the dummy items. Fix this by replacing the two lines with an error inside onBindViewHolder with:

holder.idView.text = (position + 1).toString()
holder.contentView.text = item.first.name

With that, the errors in RecordListFragment should be gone.

Build and run. Go to the List of Audios tab and you’ll see your audios:

List of recorded audio clips

Finally, you need to change the UI to actually play your recordings.

Listening to Your Files

Each of the recorded files has a Play button, but nothing happens when you tap them. You’ll get the buttons working soon.

Go to MyItemRecyclerViewAdapter and add a listener in the constructor. See code below:

class MyItemRecyclerViewAdapter(private val values: List<Pair<File, Int>>, private val listener: (Pair<File, Int>) -> Unit)
  : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {

Now, in ViewHolder, below where you have the TextView declaration, add a reference to the button:

val button : ImageButton = view.findViewById(R.id.play_button)

With this line of code, the holder knows there’s a button on each row and will hold a reference to each one.

Android Studio might show an error because you haven’t imported ImageButton, add the import at the top:

import android.widget.ImageButton

Finally, in onBindViewHolder(), add onClickListener at the bottom of the function:

holder.button.isEnabled = true
holder.button.colorFilter = null
isPlaying = false
holder.button.setOnClickListener {
  if (!isPlaying) {
    isPlaying = true
    listener(item)
    if (item.second == position) {
      holder.button.colorFilter = PorterDuffColorFilter(holder.itemView.resources.getColor(R.color.colorPrimaryDark), PorterDuff.Mode.SRC_ATOP)
      holder.button.isEnabled = true
    }
  }
}

This listener references the one you added in the class declaration. Now the line of code where you initialized the adapter is showing an error because you aren’t passing listener as a parameter.

For the above code to work, you need to import PorterDuffColorFilter:

import android.graphics.PorterDuffColorFilter
import android.graphics.PorterDuff

Additionally, you need to add isPlaying as an instance of the class. Below the class, add:

private var isPlaying = false

Go to onCreateView in RecordingListFragment.kt and you’ll see an error because of the above mentioned listener. Change the adapter declaration to the code below:

adapter = MyItemRecyclerViewAdapter(items) {
  if (!isPlaying) {
    playSound(it.first)
  }
}
viewAdapter = adapter as MyItemRecyclerViewAdapter

playSound and its helper classes have already been provided, so with these changes, you’ll be able to play the sound.

Go ahead and try it!

Keep in mind that capturing copyrighted material from YouTube or other sources might violate copyright laws. Be sure to only capture copyright-free material or material you have permission to store.

Note: This API won’t record external sound through the device’s microphone. You need to run an app that has audio in it. For example, play a video in the YouTube app and let the app capture the audio.

Keep in mind that capturing copyrighted material from YouTube or other sources might violate copyright laws. Be sure to only capture copyright-free material or material you have permission to store.

Congratulations! You’ve now made an app that uses the Audio Playback Capture API to capture audio and play it back on demand.

Where to Go From Here?

You can download the final project by using the Download Materials button at the top or bottom of this tutorial.

In this Audio Playback Capture API tutorial you learned how to:

  • Configure your app to use the Audio Playback Capture API.
  • Request all the necessary permissions to start an audio capture.
  • Create a service and tie it to your app so it does the capturing work for you.

This project is only the beginning of your journey with the Audio Playback Capture API. If you want to learn more about media capturing, check out our tutorial Media Playback on Android with ExoPlayer.

If you have any suggestions, questions, or if you want to show the cool things you added to this project, join the discussion below.