fix(cw): prevent double AudioRecord when toggling capture

CwDecodeScreen 的 LaunchedEffect 原先用内层 launch{} 启动音频采集。
isListening 在权限授予后由 false->true->(授予回调再次置 true), 加上
LaunchedEffect(isListening, permissionGranted) 的双 key 重启, 会造成
前一个 audioFlow().collect 尚未取消、新的又启动 —— 两个 AudioRecord
同时录音, 内存翻倍、音频混叠, 是低内存机 OOM 崩溃的实锤级嫌疑。

改为在 LaunchedEffect 协程体内直接 collect (取消时随父协程及时停止),
并保持 (isListening, permissionGranted) 双 key 以正确处理权限授予后
需要重启采集的情形。

同时清理不再使用的 kotlinx.coroutines.launch import。

验证: :feature:cw:compileDebugKotlin => BUILD SUCCESSFUL
This commit is contained in:
mckero committed 2026-08-13 03:16:36 +00:00
1 parent c374058e1d
commit e0405b541f
1 file changed
+11 -12
@@ -65,7 +65,6 @@ import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import com.rtbishop.look4sat.core.domain.repository.IContainerProvider
import com.rtbishop.look4sat.core.presentation.R as CoreR
import kotlinx.coroutines.launch
/**
* Full-page CW decoder backed by DeepCW.
@@ -110,19 +109,19 @@ fun CwDecodeScreen(navigateUp: () -> Unit = {}) {
if (granted) isListening = true
}
// Capture runs only while listening; cancelling the effect stops the mic.
// Capture runs only while listening. Keyed on both listening state and
// permission so granting the permission mid-flow restarts collection
// (isListening may already be true when the launcher returns).
LaunchedEffect(isListening, permissionGranted) {
if (!isListening || !permissionGranted) return@LaunchedEffect
launch {
audioCapture.audioFlow().collect { chunk ->
decoder.processBuffer(chunk, audioCapture.sampleRate)
waterfall.pushSamples(chunk, audioCapture.sampleRate)
}
if (!isListening) return@LaunchedEffect
if (!permissionGranted) {
permissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
return@LaunchedEffect
}
audioCapture.audioFlow().collect { chunk ->
decoder.processBuffer(chunk, audioCapture.sampleRate)
waterfall.pushSamples(chunk, audioCapture.sampleRate)
}
}
LaunchedEffect(permissionGranted) {
if (permissionGranted) isListening = true
}
DisposableEffect(Unit) {