Skip to content

Instantly share code, notes, and snippets.

@Gazer
Created March 20, 2023 18:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gazer/356555747008b4c7b9189e0e41dbd80b to your computer and use it in GitHub Desktop.
Save Gazer/356555747008b4c7b9189e0e41dbd80b to your computer and use it in GitHub Desktop.
A Composable to record audio
// In the "Data Input"/"Event Output" paradigm, where would you put the Recorder logic?
//
// Leave your comment
//
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun RecordAudioButton(
onRecordedAudio: (File) -> Unit
) {
var isRecording by remember { mutableStateOf(false) }
var elapsed by remember { mutableStateOf(0) }
val recorder = remember { Recorder() }
var recordedFile by remember { mutableStateOf<File?>(null) }
val scope = rememberCoroutineScope()
val toggle = {
if (isRecording) {
scope.launch { recorder.stopRecording() }
isRecording = false
recordedFile?.let(onRecordedAudio)
} else {
elapsed = 0
recordedFile = File.createTempFile("recording", "wav")
scope.launch {
recorder.startRecording(
recordedFile!!,
onTick = { seconds ->
elapsed = seconds
}
) { e ->
scope.launch(Dispatchers.Main) {
isRecording = false
}
}
}
isRecording = true
}
}
val micPermissionState = rememberPermissionState(
permission = Manifest.permission.RECORD_AUDIO,
onPermissionResult = { granted ->
if (granted) {
toggle()
}
}
)
RecordAudioButton(
totalTime = elapsed,
isRecording = isRecording,
onClick = {
if (micPermissionState.status.isGranted) {
toggle()
} else {
micPermissionState.launchPermissionRequest()
}
},
)
}
@Composable
internal fun RecordAudioButton(
totalTime: Int,
isRecording: Boolean,
onClick: () -> Unit,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
if (isRecording) {
val minutes: Int = totalTime / 60
val seconds: Int = totalTime % 60
val text = "%02d:%02d".format(minutes, seconds)
Text(text, modifier = Modifier.padding(start = 8.dp))
}
IconButton(onClick = onClick) {
if (isRecording) {
Icon(Icons.Rounded.Stop, "record")
} else {
Icon(Icons.Rounded.Mic, "record")
}
}
}
}
@Preview
@Composable
fun ButtonIsNotRecording() {
RecordAudioButton(0, false) {}
}
@Preview
@Composable
fun ButtonIsRecording() {
RecordAudioButton(93, true) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment