fix(cw): add microphone permission check before starting decoder

- Dispatch CwPermissionResult alongside SstvPermissionResult
- Add requestMicPermission callback through TransceiversPage chain
- Check cw.hasPermission before starting audio capture
- Prevent crash when RECORD_AUDIO not granted
This commit is contained in:
atsunatsu committed 2026-07-31 19:00:56 +08:00
1 parent 33712c29fc
commit 5a6b162e4f
3 files changed
+27 -5

No files matched your search

@@ -89,10 +89,14 @@ fun RadarDestination(navigateUp: () -> Unit) {
) == PackageManager.PERMISSION_GRANTED
LaunchedEffect(hasPermission) {
viewModel.onAction(RadarAction.SstvPermissionResult(hasPermission))
viewModel.onAction(RadarAction.CwPermissionResult(hasPermission))
}
val permissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted -> viewModel.onAction(RadarAction.SstvPermissionResult(granted)) }
) { granted ->
viewModel.onAction(RadarAction.SstvPermissionResult(granted))
viewModel.onAction(RadarAction.CwPermissionResult(granted))
}
RadarScreen(uiState, viewModel::onAction, navigateUp, requestMicPermission = {
permissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
})
@@ -176,7 +180,8 @@ private fun PagerCard(
orbitalPos = uiState.orbitalPos,
cw = uiState.cw,
radioControl = uiState.radioControl,
onAction = onAction
onAction = onAction,
requestMicPermission = requestMicPermission
)
RadarPage.Sstv -> SstvPage(
sstv = uiState.sstv,
@@ -425,6 +425,10 @@ class RadarViewModel(
private fun startCwListening() {
if (cwListeningJob?.isActive == true) return
if (!_uiState.value.cw.hasPermission) {
// Permission not yet granted — request it (launcher handles the result)
return
}
// Stop SSTV if running (audio capture is shared)
stopSstvRecording()
initCwDecoder()
@@ -86,6 +86,7 @@ fun TransceiversPage(
cw: CwSubState,
radioControl: RadioControlSubState,
onAction: (RadarAction) -> Unit,
requestMicPermission: () -> Unit = {},
modifier: Modifier = Modifier
) {
if (transceivers.isEmpty()) {
@@ -112,6 +113,7 @@ fun TransceiversPage(
cw = cw,
radioControl = radioControl,
onAction = onAction,
requestMicPermission = requestMicPermission,
onToggle = { onAction(RadarAction.SelectTransmitter(radio.uuid)) }
)
}
@@ -150,6 +152,7 @@ private fun TransceiverItem(
cw: CwSubState,
radioControl: RadioControlSubState,
onAction: (RadarAction) -> Unit,
requestMicPermission: () -> Unit,
onToggle: () -> Unit
) {
val bgColor = if (isExpanded) MaterialTheme.colorScheme.surfaceContainerHighest
@@ -245,7 +248,8 @@ private fun TransceiverItem(
orbitalPos = orbitalPos,
cw = cw,
radioControl = radioControl,
onAction = onAction
onAction = onAction,
requestMicPermission = requestMicPermission
)
}
@@ -317,7 +321,8 @@ private fun ExpandedRadioControl(
orbitalPos: OrbitalPos?,
cw: CwSubState,
radioControl: RadioControlSubState,
onAction: (RadarAction) -> Unit
onAction: (RadarAction) -> Unit,
requestMicPermission: () -> Unit = {},
) {
Column(
modifier = Modifier
@@ -438,6 +443,7 @@ private fun ExpandedRadioControl(
CwDecoderPanel(
cw = cw,
onAction = onAction,
requestMicPermission = requestMicPermission,
modifier = Modifier.fillMaxWidth()
)
}
@@ -623,6 +629,7 @@ private enum class EditedField { TX, RX }
private fun CwDecoderPanel(
cw: CwSubState,
onAction: (RadarAction) -> Unit,
requestMicPermission: () -> Unit = {},
modifier: Modifier = Modifier
) {
Column(
@@ -662,7 +669,13 @@ private fun CwDecoderPanel(
) {
if (cw.status == CwStatus.Idle) {
Button(
onClick = { onAction(RadarAction.CwStartListening) },
onClick = {
if (!cw.hasPermission) {
requestMicPermission()
} else {
onAction(RadarAction.CwStartListening)
}
},
modifier = Modifier.weight(1f)
) {
Text(stringResource(R.string.radar_cw_start))