From d3299d0818b7dab0a1f9e6daa6a000196844b79b Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Wed, 22 Oct 2025 22:54:19 +0530 Subject: [PATCH] feat(ui): implement waking screen on alarm without wakelock Closes: #46 --- app/src/main/AndroidManifest.xml | 19 ++++++- .../java/org/nsh07/pomodoro/MainActivity.kt | 6 ++- .../org/nsh07/pomodoro/data/AppContainer.kt | 17 ++++++- .../nsh07/pomodoro/service/TimerService.kt | 49 +++++++++---------- .../pomodoro/ui/timerScreen/AlarmDialog.kt | 32 +++++------- 5 files changed, 73 insertions(+), 50 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 84c8ae7..3f3f018 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,4 +1,20 @@ - + + @@ -7,7 +23,6 @@ - . + * This file is part of Tomato - a minimalist pomodoro timer for Android. + * + * Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Tomato. + * If not, see . */ package org.nsh07.pomodoro.data @@ -27,6 +37,7 @@ interface AppContainer { val notificationBuilder: NotificationCompat.Builder val timerState: MutableStateFlow val time: MutableStateFlow + var activityTurnScreenOn: (Boolean) -> Unit } class DefaultAppContainer(context: Context) : AppContainer { @@ -78,4 +89,6 @@ class DefaultAppContainer(context: Context) : AppContainer { MutableStateFlow(appTimerRepository.focusTime) } + override var activityTurnScreenOn: (Boolean) -> Unit = {} + } \ No newline at end of file diff --git a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt index fc104ab..e9158c5 100644 --- a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt +++ b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2025 Nishant Mishra + * + * This file is part of Tomato - a minimalist pomodoro timer for Android. + * + * Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Tomato. + * If not, see . + */ + package org.nsh07.pomodoro.service import android.annotation.SuppressLint @@ -7,7 +24,6 @@ import android.media.AudioAttributes import android.media.MediaPlayer import android.os.Build import android.os.IBinder -import android.os.PowerManager import android.os.SystemClock import android.os.VibrationEffect import android.os.Vibrator @@ -23,7 +39,6 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import org.nsh07.pomodoro.MainActivity import org.nsh07.pomodoro.R import org.nsh07.pomodoro.TomatoApplication import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerMode @@ -60,10 +75,6 @@ class TimerService : Service() { private val skipScope = CoroutineScope(Dispatchers.IO + job) private var alarm: MediaPlayer? = null - - - private var wakeLock: PowerManager.WakeLock? = null - private val vibrator by lazy { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { val vibratorManager = getSystemService(VIBRATOR_MANAGER_SERVICE) as VibratorManager @@ -94,7 +105,6 @@ class TimerService : Service() { saveTimeToDb() notificationManager.cancel(1) alarm?.release() - wakeLock?.release() } super.onDestroy() } @@ -123,7 +133,6 @@ class TimerService : Service() { return super.onStartCommand(intent, flags, startId) } - private fun toggleTimer() { updateProgressSegments() @@ -164,20 +173,6 @@ class TimerService : Service() { if (iterations == 0) showTimerNotification(time.toInt()) if (time < 0) { - val powerManager = this@TimerService.getSystemService(POWER_SERVICE) as PowerManager - wakeLock = powerManager.newWakeLock( - PowerManager.SCREEN_BRIGHT_WAKE_LOCK or - PowerManager.ACQUIRE_CAUSES_WAKEUP or - PowerManager.ON_AFTER_RELEASE, - "PomodoroApp:AlarmWakeLock" - ) - wakeLock?.acquire(2 * 60 * 1000L) - val intent = Intent(this@TimerService, MainActivity::class.java).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP) - } - startActivity(intent) - - skipTimer() _timerState.update { currentState -> currentState.copy(timerRunning = false) @@ -197,7 +192,10 @@ class TimerService : Service() { } } - @SuppressLint("MissingPermission", "StringFormatInvalid") // We check for the permission when pressing the Play button in the UI + @SuppressLint( + "MissingPermission", + "StringFormatInvalid" + ) // We check for the permission when pressing the Play button in the UI fun showTimerNotification( remainingTime: Int, paused: Boolean = false, complete: Boolean = false ) { @@ -372,6 +370,8 @@ class TimerService : Service() { fun startAlarm() { if (timerRepository.alarmEnabled) alarm?.start() + appContainer.activityTurnScreenOn(true) + if (timerRepository.vibrateEnabled) { if (!vibrator.hasVibrator()) { return @@ -393,8 +393,7 @@ class TimerService : Service() { vibrator.cancel() } - wakeLock?.release() - wakeLock = null + appContainer.activityTurnScreenOn(false) _timerState.update { currentState -> currentState.copy(alarmRinging = false) diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/AlarmDialog.kt b/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/AlarmDialog.kt index ed39a73..7d13fa7 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/AlarmDialog.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/AlarmDialog.kt @@ -1,13 +1,22 @@ /* * Copyright (c) 2025 Nishant Mishra * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * This file is part of Tomato - a minimalist pomodoro timer for Android. + * + * Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Tomato. + * If not, see . */ package org.nsh07.pomodoro.ui.timerScreen -import androidx.activity.compose.LocalActivity import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -25,7 +34,6 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -39,21 +47,6 @@ fun AlarmDialog( modifier: Modifier = Modifier, stopAlarm: () -> Unit ) { - val activity = LocalActivity.current - - // Set lockscreen flags when dialog appears, remove when it disappears - DisposableEffect(Unit) { - // Show over lockscreen - activity?.setShowWhenLocked(true) - activity?.setTurnScreenOn(true) - - onDispose { - // Remove lockscreen flags when dialog is dismissed - activity?.setShowWhenLocked(false) - activity?.setTurnScreenOn(false) - } - } - BasicAlertDialog( onDismissRequest = stopAlarm, modifier = modifier @@ -93,4 +86,3 @@ fun AlarmDialog( } } } -