fix(ring): open the ring screen when an alarm or timer goes off in the app
A full-screen intent opens its activity only on a locked phone or a dark display. While the user is in Clockula, SystemUI shows it as a heads-up and the ring screen never comes up. Both ring services now start their screen directly when the app has a visible window, which Android allows from the background. Anywhere else the full-screen intent still decides.
This commit is contained in:
1 parent
caa8c50db3
commit
d3af7d5b7c
4 files changed
+49
-2
No files matched your search
+2
-1
@@ -47,7 +47,8 @@ The first release of Clockula: alarms, timers, a stopwatch and a world clock.
|
||||
default sound instead.
|
||||
- A ring screen over the lock screen with snooze and dismiss. The dismiss
|
||||
challenge always gives you a way out, works with a screen reader, and Back
|
||||
can't silence an alarm.
|
||||
can't silence an alarm. It also opens when the alarm or a timer goes off
|
||||
while you're using Clockula.
|
||||
- Choose what the volume buttons do while an alarm rings: change the volume
|
||||
(as before), snooze, dismiss or nothing. Dismiss still respects the dismiss
|
||||
challenge by snoozing instead, and a snooze press with no snoozes left
|
||||
|
||||
@@ -18,8 +18,10 @@ import de.jeanlucmakiola.clockula.domain.alarm.RingPresentationPolicy
|
||||
import de.jeanlucmakiola.clockula.domain.alarm.RingSession
|
||||
import de.jeanlucmakiola.clockula.domain.ring.RingFallbackPolicy
|
||||
import de.jeanlucmakiola.clockula.domain.ring.SilenceAfter
|
||||
import de.jeanlucmakiola.clockula.ring.ForegroundRingScreen
|
||||
import de.jeanlucmakiola.clockula.ring.RingAudioPlayer
|
||||
import de.jeanlucmakiola.clockula.ring.RingVibrator
|
||||
import de.jeanlucmakiola.clockula.ui.ring.AlarmRingActivity
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@@ -128,10 +130,12 @@ class AlarmRingService : Service() {
|
||||
* replaces it with the alarm's own notification as soon as the session is
|
||||
* read. Same channel and same id, so the user sees one notification — and
|
||||
* the placeholder is the first post, so it is the one that opens the ring
|
||||
* screen.
|
||||
* screen. Inside the app the full-screen intent only shows a heads-up,
|
||||
* so the screen is opened directly there.
|
||||
*/
|
||||
private fun startForegroundPreparing() {
|
||||
startForeground(RingNotifications.preparing(this, presentation(), repostPendingIntent()))
|
||||
ForegroundRingScreen.launchIfVisible(this, AlarmRingActivity::class.java)
|
||||
}
|
||||
|
||||
private fun startForeground(session: RingSession) {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.jeanlucmakiola.clockula.ring
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.ActivityManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
||||
/**
|
||||
* Opens a ring screen directly while one of Clockula's own windows is on
|
||||
* screen.
|
||||
*
|
||||
* A full-screen intent opens its activity only when the phone is locked or the
|
||||
* display is off. On a phone in use, and so always while the user is inside
|
||||
* Clockula, SystemUI shows it as a heads-up and the ring screen never comes up.
|
||||
* An app with a visible window may start activities from the background, so
|
||||
* the ring services start the screen themselves in that one case. Everywhere
|
||||
* else the full-screen intent stays in charge, and a heads-up over another app
|
||||
* is what the platform asks for.
|
||||
*/
|
||||
object ForegroundRingScreen {
|
||||
|
||||
fun launchIfVisible(context: Context, screen: Class<out Activity>) {
|
||||
if (!appIsVisible()) return
|
||||
// A refused start costs nothing: the notification is up either way.
|
||||
runCatching {
|
||||
context.startActivity(
|
||||
Intent(context, screen).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** The process holds a visible activity, not only a foreground service. */
|
||||
private fun appIsVisible(): Boolean {
|
||||
val process = ActivityManager.RunningAppProcessInfo()
|
||||
ActivityManager.getMyMemoryState(process)
|
||||
return process.importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE
|
||||
}
|
||||
}
|
||||
@@ -20,12 +20,14 @@ import de.jeanlucmakiola.clockula.domain.timer.TimerMode
|
||||
import de.jeanlucmakiola.clockula.domain.timer.TimerRing
|
||||
import de.jeanlucmakiola.clockula.domain.timer.TimerRingDecision
|
||||
import de.jeanlucmakiola.clockula.domain.timer.TimerSettings
|
||||
import de.jeanlucmakiola.clockula.ring.ForegroundRingScreen
|
||||
import de.jeanlucmakiola.clockula.ring.RingAudioPlayer
|
||||
import de.jeanlucmakiola.clockula.ring.RingVibrator
|
||||
import de.jeanlucmakiola.clockula.timer.AlarmRingStatus
|
||||
import de.jeanlucmakiola.clockula.timer.TimerEngine
|
||||
import de.jeanlucmakiola.clockula.timer.TimerIntents
|
||||
import de.jeanlucmakiola.clockula.timer.TimerServiceState
|
||||
import de.jeanlucmakiola.clockula.ui.ring.TimerRingActivity
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@@ -286,6 +288,8 @@ class TimerService : Service() {
|
||||
fullScreen = sounding && capabilities.snapshot().canUseFullScreenIntent
|
||||
}
|
||||
startForeground(TimerNotifications.timer(this, state, fullScreen))
|
||||
// Inside the app the full-screen intent only shows a heads-up.
|
||||
if (!state.alertOnce && sounding) ForegroundRingScreen.launchIfVisible(this, TimerRingActivity::class.java)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user