|
// 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) {} |
|
} |