Skip to content

Instantly share code, notes, and snippets.

@RoryKelly
Last active October 15, 2020 14:41
Show Gist options
  • Save RoryKelly/967a2c293cfb80d33062414472e57282 to your computer and use it in GitHub Desktop.
Save RoryKelly/967a2c293cfb80d33062414472e57282 to your computer and use it in GitHub Desktop.
Flow that Immediately emits a set of AudioDeviceInfo's, i.e the current audio devices that are connected, followed by updates as devices are connect and disconnected. Useful for monitoring currently connected headphones
package com.klefmusic.eightbars.utils
import android.content.Context
import android.media.AudioDeviceCallback
import android.media.AudioDeviceInfo
import android.media.AudioManager
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.sendBlocking
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.callbackFlow
/**
* Immediately emits a set of [AudioDeviceInfo], i.e the current audio devices that are connected,
* followed by updates as devices are connect and disconnected.
*
* @param context android context.
* @param flags A set of bitflags specifying the criteria to test.
* @see [AudioManager.GET_DEVICES_OUTPUTS]
* @see [AudioManager.GET_DEVICES_INPUTS]
* @see [AudioManager.GET_DEVICES_INPUTS]
*/
@ExperimentalCoroutinesApi
fun audioDevices(context: Context, flags: Int): Flow<Set<AudioDeviceInfo>> = callbackFlow<Set<AudioDeviceInfo>>{
val myAudioManager : AudioManager = context.getSystemService (Context.AUDIO_SERVICE) as AudioManager
val audioDevices: MutableSet<AudioDeviceInfo> = mutableSetOf(*myAudioManager.getDevices(
AudioManager.GET_DEVICES_OUTPUTS
))
val callback = object : AudioDeviceCallback() {
override fun onAudioDevicesAdded(addedDevices: Array<AudioDeviceInfo>) {
super.onAudioDevicesAdded(addedDevices)
audioDevices.addAll(addedDevices)
sendBlocking(audioDevices)
}
override fun onAudioDevicesRemoved(removedDevices: Array<AudioDeviceInfo>) {
super.onAudioDevicesRemoved(removedDevices)
audioDevices.removeAll(removedDevices)
sendBlocking(audioDevices)
}
}
myAudioManager.registerAudioDeviceCallback(callback, null)
awaitClose {
myAudioManager.unregisterAudioDeviceCallback(callback)
}
}.buffer(capacity = Channel.CONFLATED)
/**
* Immediately emits a set of [AudioDeviceInfo], i.e the current audio devices that are connected,
* followed by updates as devices are connect and disconnected.
*
* @param context android context.
* @param flags A set of bitflags specifying the criteria to test.
* @see [AudioManager.GET_DEVICES_OUTPUTS]
* @see [AudioManager.GET_DEVICES_INPUTS]
* @see [AudioManager.GET_DEVICES_INPUTS]
*/
@ExperimentalCoroutinesApi
@JvmName("audioDevicesExt")
fun Context.audioDevices(flags: Int) : Flow<Set<AudioDeviceInfo>> = audioDevices(this, flags)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment