Anonymous
Я хочу, чтобы приложение Android Timer имело возможность работать в фоновом режиме
Сообщение
Anonymous » 14 июл 2025, 06:23
Я закодировал приложение таймера, которое выводит звук текста в речь, но таймер останавливается каждый раз, когда я переключаюсь на другое приложение или блокирую телефон, и я хотел бы, чтобы он продолжал время, даже когда я делаю это.
Код: Выделить всё
**@Composable**
fun rememberTextToSpeech(context: Context): TextToSpeech {
var ttsInstance: TextToSpeech? = null
val tts = remember {
TextToSpeech(context) { status ->
if (status == TextToSpeech.SUCCESS) {
ttsInstance?.language = Locale("spa")
}
}.also {
ttsInstance = it
}
}
DisposableEffect(Unit) {
onDispose {
tts.shutdown()
}
}
return tts
}
@OptIn(ExperimentalMaterial3Api::class)
**@Composable**
fun TimerScreen() {
val context = LocalContext.current
val tts = rememberTextToSpeech(context)
var inputText by remember { mutableStateOf("") }
var timeLeft by remember { mutableStateOf(0) } // seconds
var isRunning by remember { mutableStateOf(false) }
var isFinished by remember { mutableStateOf(false) } // ‹— NEW
var initialMinutes by remember { mutableStateOf(0) }
/* ───────────── COUNT‑DOWN ───────────── */
LaunchedEffect(isRunning, timeLeft) {
if (isRunning && timeLeft > 0) {
delay(1000) // tick
timeLeft -= 1
} else if (isRunning && timeLeft == 0) {
isRunning = false
isFinished = true // trigger the repeater
}
}
/* ───────────── REPEATER ───────────── */
LaunchedEffect(isFinished) {
while (isFinished) { // keeps looping until Reset toggles it off
val msg = "Your $initialMinutes minute timer is done"
tts.speak(msg, TextToSpeech.QUEUE_FLUSH, null, "timer_done")
delay(3000) // repeat interval (3s feels natural)
}
tts.stop() // stop any ongoing speech when reset
}
/* ───────────── UI ───────────── */
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFFF5F5DC))
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
"How many minutes would you like to time?",
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
color = Color.Black
)
Spacer(Modifier.height(32.dp))
TextField(
value = inputText,
onValueChange = { if (it.all(Char::isDigit)) inputText = it },
label = { Text("Minutes") },
singleLine = true,
modifier = Modifier.width(120.dp)
)
Spacer(Modifier.height(64.dp))
val mm = timeLeft / 60
val ss = timeLeft % 60
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
String.format("%02d:%02d", mm, ss),
fontSize = 64.sp,
fontWeight = FontWeight.Bold
)
Spacer(Modifier.height(64.dp))
/* START */
Button(
onClick = {
val minutes = inputText.toIntOrNull() ?: 0
if (minutes > 0) {
initialMinutes = minutes
timeLeft = minutes * 60
isRunning = true
isFinished = false // safeguard
}
},
enabled = !isRunning && inputText.isNotBlank(),
colors = ButtonDefaults.buttonColors(containerColor = Color.Green)
) { Text("Start", color = Color.Black) }
/* RESET */
Button(
onClick = {
isRunning = false
isFinished = false // stops the repeater loop
timeLeft = 0
inputText = ""
},
colors = ButtonDefaults.buttonColors(containerColor = Color.Red)
) { Text("Reset") }
}
}
}
Я попробовал только исходную реализацию, которую я не ожидал остановить при переключении приложения или блокировке телефона.
Подробнее здесь:
https://stackoverflow.com/questions/797 ... background
1752463420
Anonymous
Я закодировал приложение таймера, которое выводит звук текста в речь, но таймер останавливается каждый раз, когда я переключаюсь на другое приложение или блокирую телефон, и я хотел бы, чтобы он продолжал время, даже когда я делаю это.[code]**@Composable** fun rememberTextToSpeech(context: Context): TextToSpeech { var ttsInstance: TextToSpeech? = null val tts = remember { TextToSpeech(context) { status -> if (status == TextToSpeech.SUCCESS) { ttsInstance?.language = Locale("spa") } }.also { ttsInstance = it } } DisposableEffect(Unit) { onDispose { tts.shutdown() } } return tts } @OptIn(ExperimentalMaterial3Api::class) **@Composable** fun TimerScreen() { val context = LocalContext.current val tts = rememberTextToSpeech(context) var inputText by remember { mutableStateOf("") } var timeLeft by remember { mutableStateOf(0) } // seconds var isRunning by remember { mutableStateOf(false) } var isFinished by remember { mutableStateOf(false) } // ‹— NEW var initialMinutes by remember { mutableStateOf(0) } /* ───────────── COUNT‑DOWN ───────────── */ LaunchedEffect(isRunning, timeLeft) { if (isRunning && timeLeft > 0) { delay(1000) // tick timeLeft -= 1 } else if (isRunning && timeLeft == 0) { isRunning = false isFinished = true // trigger the repeater } } /* ───────────── REPEATER ───────────── */ LaunchedEffect(isFinished) { while (isFinished) { // keeps looping until Reset toggles it off val msg = "Your $initialMinutes minute timer is done" tts.speak(msg, TextToSpeech.QUEUE_FLUSH, null, "timer_done") delay(3000) // repeat interval (3s feels natural) } tts.stop() // stop any ongoing speech when reset } /* ───────────── UI ───────────── */ Column( modifier = Modifier .fillMaxSize() .background(Color(0xFFF5F5DC)) .padding(24.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( "How many minutes would you like to time?", fontSize = 20.sp, fontWeight = FontWeight.Bold, color = Color.Black ) Spacer(Modifier.height(32.dp)) TextField( value = inputText, onValueChange = { if (it.all(Char::isDigit)) inputText = it }, label = { Text("Minutes") }, singleLine = true, modifier = Modifier.width(120.dp) ) Spacer(Modifier.height(64.dp)) val mm = timeLeft / 60 val ss = timeLeft % 60 Column ( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( String.format("%02d:%02d", mm, ss), fontSize = 64.sp, fontWeight = FontWeight.Bold ) Spacer(Modifier.height(64.dp)) /* START */ Button( onClick = { val minutes = inputText.toIntOrNull() ?: 0 if (minutes > 0) { initialMinutes = minutes timeLeft = minutes * 60 isRunning = true isFinished = false // safeguard } }, enabled = !isRunning && inputText.isNotBlank(), colors = ButtonDefaults.buttonColors(containerColor = Color.Green) ) { Text("Start", color = Color.Black) } /* RESET */ Button( onClick = { isRunning = false isFinished = false // stops the repeater loop timeLeft = 0 inputText = "" }, colors = ButtonDefaults.buttonColors(containerColor = Color.Red) ) { Text("Reset") } } } } [/code] Я попробовал только исходную реализацию, которую я не ожидал остановить при переключении приложения или блокировке телефона. Подробнее здесь: [url]https://stackoverflow.com/questions/79700373/i-want-an-android-timer-app-to-be-able-to-run-in-the-background[/url]