Reputation: 1443
I am using USB to communicate audio and video from some external hardware.
Video is displayed on a Surface
as long as the app is in foreground but audio should keep playing even when in background.
Using threads doesn't seem to work, when the app goes to background the audio starts to stutter and sound very bad. I believe i need to use a service, am i wrong?
But from all the online documentation i can't figure out, what is the best type of service (or any) to use for such long running application and the best way to communicate the large amount of data between its Activity
& Surface
?
I looked into plain services, WorkManagers, ForegroundService, ServiceSocket and many others
Here is the current code i am using to run the streamed audio from the USB. It is using a coroutine and as said, audio starts to stutter when app in background
class AudioTrackPlayer {
private val channel = Channel<Boolean>(capacity = 15)
private var dataList = mutableListOf<ByteArray>()
private var readIndex = 0
private var writeIndex = 0
private val scope = CoroutineScope(Job() + Dispatchers.IO)
private var audio: AudioTrack? = null
var lastSize = 0
var isPlaying = false
companion object {
private const val DATA_LIST_SIZE = 11
}
init {
scope.launch {
startThread()
}
}
fun config(channels: Int, sampleRate: Int):Boolean {
//......
}
private suspend fun startThread() = withContext(Dispatchers.IO) {
var data:ByteArray
var isPlayingLast = false
var finalByteArray:ByteArray
channel.consumeEach {
if (audio != null) {
if (isPlaying) {
if (readIndex != writeIndex) {
isPlayingLast = true
data = dataList[readIndex]
lastSize = data.size - 8
if (audio?.playState != AudioTrack.PLAYSTATE_PLAYING) {
audio?.play()
}
audio?.write(data, 8, lastSize)
readIndex++
if (readIndex == DATA_LIST_SIZE) {
readIndex = 0
}
}
} else {
if (isPlayingLast) {
isPlayingLast = false
finalByteArray = ByteArray(lastSize * 2)
if (audio?.playState != AudioTrack.PLAYSTATE_PLAYING) {
audio!!.play()
}
audio!!.write(finalByteArray, 0, finalByteArray.size)
audio!!.stop()
audio!!.flush()
writeIndex = readIndex
}
}
}
}
}
fun write(data: ByteArray) {
scope.launch {
if (isPlaying) {
dataList.add(writeIndex, data)
writeIndex++
if (writeIndex == DATA_LIST_SIZE) {
writeIndex = 0
}
channel.send(true)
}
}
}
fun play() {
//...
}
fun stop() {
//....
}
}
Upvotes: 1
Views: 44