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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Audio Playback Capture in Android X
30 mins
- Getting Started
- What Is Audio Playback Capture API?
- Managing Permissions for Audio Capture
- Requesting Permissions
- Checking for Permissions in Your Activity
- Changing Permissions
- Recording Audio From Other Apps
- Requesting Permission Before a Capturing Session
- Checking Permissions
- Overriding onActivityResult
- Creating MediaCaptureService
- Starting the Service and Getting Notifications
- Triggering the Audio Capture Playback
- Starting the Playback Audio Capture
- Stopping the Audio Capture
- Connecting the Service
- Adding Your Service to the Android Manifest
- Disabling Audio Playback Capture
- Listening to Recorded Audio
- Getting the Files From Memory
- Listening to Your Files
- Where to Go From Here?
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:
- First, you retrieve the directory where the files are.
- 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:
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.
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.