Skip to content

Commit d3299d0

Browse files
committed
feat(ui): implement waking screen on alarm without wakelock
Closes: #46
1 parent d051b60 commit d3299d0

File tree

5 files changed

+73
-50
lines changed

5 files changed

+73
-50
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Copyright (c) 2025 Nishant Mishra
3+
~
4+
~ This file is part of Tomato - a minimalist pomodoro timer for Android.
5+
~
6+
~ Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU
7+
~ General Public License as published by the Free Software Foundation, either version 3 of the
8+
~ License, or (at your option) any later version.
9+
~
10+
~ Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
11+
~ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12+
~ Public License for more details.
13+
~
14+
~ You should have received a copy of the GNU General Public License along with Tomato.
15+
~ If not, see <https://www.gnu.org/licenses/>.
16+
-->
17+
218
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
319
xmlns:tools="http://schemas.android.com/tools">
420

@@ -7,7 +23,6 @@
723
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
824
<uses-permission android:name="android.permission.POST_PROMOTED_NOTIFICATIONS" />
925
<uses-permission android:name="android.permission.VIBRATE" />
10-
<uses-permission android:name="android.permission.WAKE_LOCK" />
1126

1227
<application
1328
android:name=".TomatoApplication"

app/src/main/java/org/nsh07/pomodoro/MainActivity.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import org.nsh07.pomodoro.utils.toColor
3535

3636
class MainActivity : ComponentActivity() {
3737

38-
private val timerViewModel: TimerViewModel by viewModels(factoryProducer = { TimerViewModel.Factory })
38+
private val timerViewModel: TimerViewModel by viewModels(factoryProducer = { TimerViewModel.Factory })
3939
private val settingsViewModel: SettingsViewModel by viewModels(factoryProducer = { SettingsViewModel.Factory })
4040

4141
private val appContainer by lazy {
@@ -45,6 +45,10 @@ class MainActivity : ComponentActivity() {
4545
override fun onCreate(savedInstanceState: Bundle?) {
4646
super.onCreate(savedInstanceState)
4747
enableEdgeToEdge()
48+
appContainer.activityTurnScreenOn = {
49+
setShowWhenLocked(it)
50+
setTurnScreenOn(it)
51+
}
4852
setContent {
4953
val preferencesState by settingsViewModel.preferencesState.collectAsStateWithLifecycle()
5054

app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
/*
22
* Copyright (c) 2025 Nishant Mishra
33
*
4-
* You should have received a copy of the GNU General Public License
5-
* along with this program. If not, see <https://www.gnu.org/licenses/>.
4+
* This file is part of Tomato - a minimalist pomodoro timer for Android.
5+
*
6+
* Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU
7+
* General Public License as published by the Free Software Foundation, either version 3 of the
8+
* License, or (at your option) any later version.
9+
*
10+
* Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
11+
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12+
* Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along with Tomato.
15+
* If not, see <https://www.gnu.org/licenses/>.
616
*/
717

818
package org.nsh07.pomodoro.data
@@ -27,6 +37,7 @@ interface AppContainer {
2737
val notificationBuilder: NotificationCompat.Builder
2838
val timerState: MutableStateFlow<TimerState>
2939
val time: MutableStateFlow<Long>
40+
var activityTurnScreenOn: (Boolean) -> Unit
3041
}
3142

3243
class DefaultAppContainer(context: Context) : AppContainer {
@@ -78,4 +89,6 @@ class DefaultAppContainer(context: Context) : AppContainer {
7889
MutableStateFlow(appTimerRepository.focusTime)
7990
}
8091

92+
override var activityTurnScreenOn: (Boolean) -> Unit = {}
93+
8194
}

app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/*
2+
* Copyright (c) 2025 Nishant Mishra
3+
*
4+
* This file is part of Tomato - a minimalist pomodoro timer for Android.
5+
*
6+
* Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU
7+
* General Public License as published by the Free Software Foundation, either version 3 of the
8+
* License, or (at your option) any later version.
9+
*
10+
* Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
11+
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12+
* Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along with Tomato.
15+
* If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
118
package org.nsh07.pomodoro.service
219

320
import android.annotation.SuppressLint
@@ -7,7 +24,6 @@ import android.media.AudioAttributes
724
import android.media.MediaPlayer
825
import android.os.Build
926
import android.os.IBinder
10-
import android.os.PowerManager
1127
import android.os.SystemClock
1228
import android.os.VibrationEffect
1329
import android.os.Vibrator
@@ -23,7 +39,6 @@ import kotlinx.coroutines.flow.asStateFlow
2339
import kotlinx.coroutines.flow.update
2440
import kotlinx.coroutines.launch
2541
import kotlinx.coroutines.runBlocking
26-
import org.nsh07.pomodoro.MainActivity
2742
import org.nsh07.pomodoro.R
2843
import org.nsh07.pomodoro.TomatoApplication
2944
import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerMode
@@ -60,10 +75,6 @@ class TimerService : Service() {
6075
private val skipScope = CoroutineScope(Dispatchers.IO + job)
6176

6277
private var alarm: MediaPlayer? = null
63-
64-
65-
private var wakeLock: PowerManager.WakeLock? = null
66-
6778
private val vibrator by lazy {
6879
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
6980
val vibratorManager = getSystemService(VIBRATOR_MANAGER_SERVICE) as VibratorManager
@@ -94,7 +105,6 @@ class TimerService : Service() {
94105
saveTimeToDb()
95106
notificationManager.cancel(1)
96107
alarm?.release()
97-
wakeLock?.release()
98108
}
99109
super.onDestroy()
100110
}
@@ -123,7 +133,6 @@ class TimerService : Service() {
123133
return super.onStartCommand(intent, flags, startId)
124134
}
125135

126-
127136
private fun toggleTimer() {
128137
updateProgressSegments()
129138

@@ -164,20 +173,6 @@ class TimerService : Service() {
164173
if (iterations == 0) showTimerNotification(time.toInt())
165174

166175
if (time < 0) {
167-
val powerManager = this@TimerService.getSystemService(POWER_SERVICE) as PowerManager
168-
wakeLock = powerManager.newWakeLock(
169-
PowerManager.SCREEN_BRIGHT_WAKE_LOCK or
170-
PowerManager.ACQUIRE_CAUSES_WAKEUP or
171-
PowerManager.ON_AFTER_RELEASE,
172-
"PomodoroApp:AlarmWakeLock"
173-
)
174-
wakeLock?.acquire(2 * 60 * 1000L)
175-
val intent = Intent(this@TimerService, MainActivity::class.java).apply {
176-
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
177-
}
178-
startActivity(intent)
179-
180-
181176
skipTimer()
182177
_timerState.update { currentState ->
183178
currentState.copy(timerRunning = false)
@@ -197,7 +192,10 @@ class TimerService : Service() {
197192
}
198193
}
199194

200-
@SuppressLint("MissingPermission", "StringFormatInvalid") // We check for the permission when pressing the Play button in the UI
195+
@SuppressLint(
196+
"MissingPermission",
197+
"StringFormatInvalid"
198+
) // We check for the permission when pressing the Play button in the UI
201199
fun showTimerNotification(
202200
remainingTime: Int, paused: Boolean = false, complete: Boolean = false
203201
) {
@@ -372,6 +370,8 @@ class TimerService : Service() {
372370
fun startAlarm() {
373371
if (timerRepository.alarmEnabled) alarm?.start()
374372

373+
appContainer.activityTurnScreenOn(true)
374+
375375
if (timerRepository.vibrateEnabled) {
376376
if (!vibrator.hasVibrator()) {
377377
return
@@ -393,8 +393,7 @@ class TimerService : Service() {
393393
vibrator.cancel()
394394
}
395395

396-
wakeLock?.release()
397-
wakeLock = null
396+
appContainer.activityTurnScreenOn(false)
398397

399398
_timerState.update { currentState ->
400399
currentState.copy(alarmRinging = false)

app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/AlarmDialog.kt

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
/*
22
* Copyright (c) 2025 Nishant Mishra
33
*
4-
* You should have received a copy of the GNU General Public License
5-
* along with this program. If not, see <https://www.gnu.org/licenses/>.
4+
* This file is part of Tomato - a minimalist pomodoro timer for Android.
5+
*
6+
* Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU
7+
* General Public License as published by the Free Software Foundation, either version 3 of the
8+
* License, or (at your option) any later version.
9+
*
10+
* Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
11+
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12+
* Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along with Tomato.
15+
* If not, see <https://www.gnu.org/licenses/>.
616
*/
717

818
package org.nsh07.pomodoro.ui.timerScreen
919

10-
import androidx.activity.compose.LocalActivity
1120
import androidx.compose.foundation.clickable
1221
import androidx.compose.foundation.layout.Column
1322
import androidx.compose.foundation.layout.Spacer
@@ -25,7 +34,6 @@ import androidx.compose.material3.Surface
2534
import androidx.compose.material3.Text
2635
import androidx.compose.material3.TextButton
2736
import androidx.compose.runtime.Composable
28-
import androidx.compose.runtime.DisposableEffect
2937
import androidx.compose.ui.Alignment
3038
import androidx.compose.ui.Modifier
3139
import androidx.compose.ui.res.painterResource
@@ -39,21 +47,6 @@ fun AlarmDialog(
3947
modifier: Modifier = Modifier,
4048
stopAlarm: () -> Unit
4149
) {
42-
val activity = LocalActivity.current
43-
44-
// Set lockscreen flags when dialog appears, remove when it disappears
45-
DisposableEffect(Unit) {
46-
// Show over lockscreen
47-
activity?.setShowWhenLocked(true)
48-
activity?.setTurnScreenOn(true)
49-
50-
onDispose {
51-
// Remove lockscreen flags when dialog is dismissed
52-
activity?.setShowWhenLocked(false)
53-
activity?.setTurnScreenOn(false)
54-
}
55-
}
56-
5750
BasicAlertDialog(
5851
onDismissRequest = stopAlarm,
5952
modifier = modifier
@@ -93,4 +86,3 @@ fun AlarmDialog(
9386
}
9487
}
9588
}
96-

0 commit comments

Comments
 (0)