feat(ui): implement waking screen on alarm without wakelock
Closes: #46
This commit is contained in:
@@ -1,4 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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 <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
@@ -7,7 +23,6 @@
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.POST_PROMOTED_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<application
|
||||
android:name=".TomatoApplication"
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.nsh07.pomodoro.utils.toColor
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
private val timerViewModel: TimerViewModel by viewModels(factoryProducer = { TimerViewModel.Factory })
|
||||
private val timerViewModel: TimerViewModel by viewModels(factoryProducer = { TimerViewModel.Factory })
|
||||
private val settingsViewModel: SettingsViewModel by viewModels(factoryProducer = { SettingsViewModel.Factory })
|
||||
|
||||
private val appContainer by lazy {
|
||||
@@ -45,6 +45,10 @@ class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
appContainer.activityTurnScreenOn = {
|
||||
setShowWhenLocked(it)
|
||||
setTurnScreenOn(it)
|
||||
}
|
||||
setContent {
|
||||
val preferencesState by settingsViewModel.preferencesState.collectAsStateWithLifecycle()
|
||||
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Nishant Mishra
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.nsh07.pomodoro.data
|
||||
@@ -27,6 +37,7 @@ interface AppContainer {
|
||||
val notificationBuilder: NotificationCompat.Builder
|
||||
val timerState: MutableStateFlow<TimerState>
|
||||
val time: MutableStateFlow<Long>
|
||||
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 = {}
|
||||
|
||||
}
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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)
|
||||
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user