start a new foreground service when the stopwatch is active and the app is moved to the background

This commit is contained in:
Mysochenko Yuriy 2022-05-02 08:58:27 +03:00
parent 20a59bfd1e
commit d26372296d
37 changed files with 175 additions and 7 deletions

View File

@ -100,6 +100,8 @@
<service android:name=".services.TimerService" />
<service android:name=".services.StopwatchService" />
<receiver android:name=".receivers.AlarmReceiver" />
<receiver android:name=".receivers.HideTimerReceiver" />

View File

@ -12,9 +12,13 @@ import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import com.facebook.stetho.Stetho
import com.simplemobiletools.clock.extensions.*
import com.simplemobiletools.clock.helpers.Stopwatch
import com.simplemobiletools.clock.helpers.Stopwatch.State
import com.simplemobiletools.clock.models.TimerEvent
import com.simplemobiletools.clock.models.TimerState
import com.simplemobiletools.clock.services.StopwatchStopService
import com.simplemobiletools.clock.services.TimerStopService
import com.simplemobiletools.clock.services.startStopwatchService
import com.simplemobiletools.clock.services.startTimerService
import com.simplemobiletools.commons.extensions.checkUseEnglish
import org.greenrobot.eventbus.EventBus
@ -49,6 +53,9 @@ class App : Application(), LifecycleObserver {
startTimerService(this)
}
}
if (Stopwatch.state == State.RUNNING) {
startStopwatchService(this)
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
@ -62,6 +69,9 @@ class App : Application(), LifecycleObserver {
}
}
}
if (Stopwatch.state == State.RUNNING) {
EventBus.getDefault().post(StopwatchStopService)
}
}
@Subscribe(threadMode = ThreadMode.MAIN)

View File

@ -159,6 +159,12 @@ fun Context.getOpenTimerTabIntent(timerId: Int): PendingIntent {
return PendingIntent.getActivity(this, timerId, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
fun Context.getOpenStopwatchTabIntent(): PendingIntent {
val intent = getLaunchIntent() ?: Intent(this, SplashActivity::class.java)
intent.putExtra(OPEN_TAB, TAB_STOPWATCH)
return PendingIntent.getActivity(this, OPEN_STOPWATCH_TAB_INTENT_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
fun Context.getAlarmIntent(alarm: Alarm): PendingIntent {
val intent = Intent(this, AlarmReceiver::class.java)
intent.putExtra(ALARM_ID, alarm.id)

View File

@ -34,10 +34,12 @@ const val DEFAULT_MAX_TIMER_REMINDER_SECS = 60
const val PICK_AUDIO_FILE_INTENT_ID = 9994
const val REMINDER_ACTIVITY_INTENT_ID = 9995
const val OPEN_ALARMS_TAB_INTENT_ID = 9996
const val OPEN_STOPWATCH_TAB_INTENT_ID = 9993
const val UPDATE_WIDGET_INTENT_ID = 9997
const val OPEN_APP_INTENT_ID = 9998
const val ALARM_NOTIF_ID = 9998
const val TIMER_RUNNING_NOTIF_ID = 10000
const val STOPWATCH_RUNNING_NOTIF_ID = 10001
const val OPEN_TAB = "open_tab"
const val TAB_CLOCK = 0

View File

@ -0,0 +1,116 @@
package com.simplemobiletools.clock.services
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.IBinder
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import com.simplemobiletools.clock.R
import com.simplemobiletools.clock.extensions.getFormattedDuration
import com.simplemobiletools.clock.extensions.getOpenStopwatchTabIntent
import com.simplemobiletools.clock.helpers.STOPWATCH_RUNNING_NOTIF_ID
import com.simplemobiletools.clock.helpers.Stopwatch
import com.simplemobiletools.clock.helpers.Stopwatch.State
import com.simplemobiletools.clock.helpers.Stopwatch.UpdateListener
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class StopwatchService : Service() {
private val bus = EventBus.getDefault()
private lateinit var notificationManager: NotificationManager
private lateinit var notificationBuilder: NotificationCompat.Builder
private var isStopping = false
override fun onCreate() {
super.onCreate()
bus.register(this)
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationBuilder = getServiceNotificationBuilder(
getString(R.string.app_name),
getString(R.string.stopwatch)
)
}
override fun onBind(intent: Intent?): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
isStopping = false
startForeground(
STOPWATCH_RUNNING_NOTIF_ID,
notificationBuilder.build()
)
Stopwatch.addUpdateListener(updateListener)
return START_NOT_STICKY
}
override fun onDestroy() {
super.onDestroy()
bus.unregister(this)
Stopwatch.removeUpdateListener(updateListener)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: StopwatchStopService) {
isStopping = true
stopForeground(true)
}
private fun getServiceNotificationBuilder(
title: String,
contentText: String
): NotificationCompat.Builder {
val channelId = "simple_alarm_stopwatch"
val label = getString(R.string.stopwatch)
val importance = NotificationManager.IMPORTANCE_DEFAULT
NotificationChannel(channelId, label, importance).apply {
setSound(null, null)
notificationManager.createNotificationChannel(this)
}
return NotificationCompat.Builder(this, channelId)
.setContentTitle(title)
.setContentText(contentText)
.setSmallIcon(R.drawable.ic_stopwatch_vector)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setSound(null)
.setOngoing(true)
.setAutoCancel(true)
.setContentIntent(getOpenStopwatchTabIntent())
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
}
private fun updateNotification(totalTime: Long) {
val formattedDuration = totalTime.getFormattedDuration()
notificationBuilder.setContentTitle(formattedDuration)
.setContentText(getString(R.string.stopwatch))
notificationManager.notify(
STOPWATCH_RUNNING_NOTIF_ID,
notificationBuilder.build()
)
}
private val updateListener = object : UpdateListener {
override fun onUpdate(totalTime: Long, lapTime: Long, useLongerMSFormat: Boolean) {
if (!isStopping) {
updateNotification(totalTime)
}
}
override fun onStateChanged(state: State) {
if (state == State.STOPPED) {
stopForeground(STOP_FOREGROUND_REMOVE)
}
}
}
}
fun startStopwatchService(context: Context) {
ContextCompat.startForegroundService(context, Intent(context, StopwatchService::class.java))
}
object StopwatchStopService

View File

@ -6,6 +6,7 @@
<string name="label">Etiket</string>
<string name="no_days_selected">Gün seçilməyib</string>
<string name="timer">Sayğac</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Dövrə</string>
<string name="stopwatch_stopped">Saniyəölçən dayandı</string>
<string name="timer_stopped">Sayğaç dayandı</string>

View File

@ -6,6 +6,7 @@
<string name="label">Štítek</string>
<string name="no_days_selected">Nebyly označeny žádné dny</string>
<string name="timer">Časovač</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Mezičas</string>
<string name="stopwatch_stopped">Stopky byly zastaveny</string>
<string name="timer_stopped">Časovač byl zastaven</string>

View File

@ -6,6 +6,7 @@
<string name="label">Label</string>
<string name="no_days_selected">Dim diwrnodau wedi\'u dewis</string>
<string name="timer">Amserydd</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Lap</string>
<string name="stopwatch_stopped">Cafodd y stopwats ei stopio</string>
<string name="timer_stopped">Cafodd yr amserydd ei stopio</string>

View File

@ -6,6 +6,7 @@
<string name="label">Etiket</string>
<string name="no_days_selected">Der er ikke valgt nogen dage</string>
<string name="timer">Æggeur</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Mellemtid</string>
<string name="stopwatch_stopped">Stopuret er standset</string>
<string name="timer_stopped">Æggeuret er standset</string>

View File

@ -7,6 +7,7 @@
<string name="label">Label</string>
<string name="no_days_selected">Keine Tage ausgewählt</string>
<string name="timer">Timer</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Runde</string>
<string name="stopwatch_stopped">Die Stoppuhr wurde angehalten</string>
<string name="timer_stopped">Der Timer wurde angehalten</string>

View File

@ -7,6 +7,7 @@
<string name="label">Ετικέτα</string>
<string name="no_days_selected">Δεν έχουν επιλεγεί ημέρες</string>
<string name="timer">Χρονόμετρο</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Γύρος</string>
<string name="stopwatch_stopped">Ο χρονοδιακόπτης σταμάτησε</string>
<string name="timer_stopped">Το χρονόμετρο σταμάτησε</string>

View File

@ -6,6 +6,7 @@
<string name="label">Etiqueta</string>
<string name="no_days_selected">Ningún día seleccionado</string>
<string name="timer">Temporizador</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Vuelta</string>
<string name="stopwatch_stopped">El cronómetro s eha detenido</string>
<string name="timer_stopped">El temporizador se ha detenido</string>

View File

@ -7,6 +7,7 @@
<string name="label">Silt</string>
<string name="no_days_selected">Ühtegi päeva pole valitud</string>
<string name="timer">Taimer</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Ringi aeg</string>
<string name="stopwatch_stopped">Stopper on kinni</string>
<string name="timer_stopped">Taimer on peatunud</string>

View File

@ -6,6 +6,7 @@
<string name="label">Etiketa</string>
<string name="no_days_selected">Ez duzu egunik hautatu</string>
<string name="timer">Tenporizagailua</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Bira</string>
<string name="stopwatch_stopped">Kronometroa gelditu da</string>
<string name="timer_stopped">Tenporizagailua gelditu da</string>

View File

@ -6,6 +6,7 @@
<string name="label">Tunniste</string>
<string name="no_days_selected">Ei päiviä valittuna</string>
<string name="timer">Ajastin</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Kierrosaika</string>
<string name="stopwatch_stopped">Sekuntikello pysäytetty</string>
<string name="timer_stopped">Ajastin on pysäytetty</string>

View File

@ -7,6 +7,7 @@
<string name="label">Titre</string>
<string name="no_days_selected">Aucun jour sélectionné</string>
<string name="timer">Minuterie</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Tour</string>
<string name="stopwatch_stopped">Chronomètre arrêté</string>
<string name="timer_stopped">La minuterie a été arrêtée</string>

View File

@ -7,6 +7,7 @@
<string name="label">Etiqueta</string>
<string name="no_days_selected">Ningún día seleccionado</string>
<string name="timer">Temporizador</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Volta</string>
<string name="stopwatch_stopped">Cronómetro parado</string>
<string name="timer_stopped">Temporizador parado</string>

View File

@ -6,6 +6,7 @@
<string name="label">Oznaka</string>
<string name="no_days_selected">Nije odabran nijedan dan</string>
<string name="timer">Brojač</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Krug</string>
<string name="stopwatch_stopped">Štoperica je zaustavljena</string>
<string name="timer_stopped">Brojač je zaustavljen</string>

View File

@ -6,6 +6,7 @@
<string name="label">Címke</string>
<string name="no_days_selected">Nincs nap kiválasztva</string>
<string name="timer">Időzítő</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Kör</string>
<string name="stopwatch_stopped">A stopper leállt</string>
<string name="timer_stopped">Az időzítő leállt</string>

View File

@ -6,6 +6,7 @@
<string name="label">Label</string>
<string name="no_days_selected">Tidak ada hari yang dipilih</string>
<string name="timer">Timer</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Putaran</string>
<string name="stopwatch_stopped">Stopwatch telah berhenti</string>
<string name="timer_stopped">Timer telah berhenti</string>

View File

@ -7,6 +7,7 @@
<string name="label">Etichetta</string>
<string name="no_days_selected">Nessun giorno selezionato</string>
<string name="timer">Contaminuti</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Parziale</string>
<string name="stopwatch_stopped">Il cronometro è stato fermato</string>
<string name="timer_stopped">Il contaminuti è stato fermato</string>

View File

@ -6,6 +6,7 @@
<string name="label">ラベル</string>
<string name="no_days_selected">曜日が選択されていません</string>
<string name="timer">タイマー</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">ラップ</string>
<string name="stopwatch_stopped">ストップウォッチが停止しました</string>
<string name="timer_stopped">タイマーが停止しました</string>

View File

@ -6,6 +6,7 @@
<string name="label">Etiketė</string>
<string name="no_days_selected">Nepasirinkta nė vienos dienos</string>
<string name="timer">Laikmatis</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Etapas</string>
<string name="stopwatch_stopped">Chronometras buvo sustabdytas</string>
<string name="timer_stopped">Laikmatis buvo sustabdytas</string>

View File

@ -6,6 +6,7 @@
<string name="label">അടിക്കുറിപ്പ് </string>
<string name="no_days_selected">ദിവസങ്ങളൊന്നും തിരഞ്ഞെടുത്തിട്ടില്ല</string>
<string name="timer">ടൈമർ</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">ലാപ്‌</string>
<string name="stopwatch_stopped">Stopwatch has been stopped</string>
<string name="timer_stopped">സ്റ്റോപ്പ് വാച്ച് നിർത്തി</string>

View File

@ -6,6 +6,7 @@
<string name="label">Påskrift</string>
<string name="no_days_selected">Ingen dager valgte</string>
<string name="timer">Timer</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Runde</string>
<string name="stopwatch_stopped">Stoppeklokke er stoppet</string>
<string name="timer_stopped">Timer er stoppet</string>

View File

@ -6,6 +6,7 @@
<string name="label">Label</string>
<string name="no_days_selected">Geen dagen geselecteerd</string>
<string name="timer">Timer</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Ronde</string>
<string name="stopwatch_stopped">Stopwatch is gestopt</string>
<string name="timer_stopped">Timer is gestopt</string>

View File

@ -7,6 +7,7 @@
<string name="label">Etykieta</string>
<string name="no_days_selected">Nie wybrano dni</string>
<string name="timer">Minutnik</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Okrążenie</string>
<string name="stopwatch_stopped">Stoper został zatrzymany</string>
<string name="timer_stopped">Minutnik został zatrzymany</string>

View File

@ -6,6 +6,7 @@
<string name="label">Legenda</string>
<string name="no_days_selected">Nenhum dia selecionado</string>
<string name="timer">Temporizador</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Volta</string>
<string name="stopwatch_stopped">Cronómetro parado</string>
<string name="timer_stopped">Temporizador parado</string>

View File

@ -6,6 +6,7 @@
<string name="label">Etichetă</string>
<string name="no_days_selected">Nici o zi selectată</string>
<string name="timer">Temporizator</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">O tură</string>
<string name="stopwatch_stopped">Cronometrul a fost oprit</string>
<string name="timer_stopped">Temporizatorul a fost oprit</string>

View File

@ -7,6 +7,7 @@
<string name="label">Метка</string>
<string name="no_days_selected">Дни не выбраны</string>
<string name="timer">Таймер</string>
<string name="stopwatch">Секундомер</string>
<string name="lap">Круг</string>
<string name="stopwatch_stopped">Секундомер остановлен</string>
<string name="timer_stopped">Таймер остановлен</string>

View File

@ -6,6 +6,7 @@
<string name="label">Štítok</string>
<string name="no_days_selected">Neboli označené žiadne dni</string>
<string name="timer">Časovač</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Okruh</string>
<string name="stopwatch_stopped">Stopky boli zastavené</string>
<string name="timer_stopped">Časovač bol zastavený</string>

View File

@ -7,6 +7,7 @@
<string name="label">Etikett</string>
<string name="no_days_selected">Inga dagar har valts</string>
<string name="timer">Timer</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Varv</string>
<string name="stopwatch_stopped">Stoppuret har stoppats</string>
<string name="timer_stopped">Timern har stoppats</string>

View File

@ -7,6 +7,7 @@
<string name="label">Etiket</string>
<string name="no_days_selected">Hiçbir gün seçilmedi</string>
<string name="timer">Zamanlayıcı</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Tur</string>
<string name="stopwatch_stopped">Kronometre durduruldu</string>
<string name="timer_stopped">Zamanlayıcı durduruldu</string>

View File

@ -6,6 +6,7 @@
<string name="label">Мітка</string>
<string name="no_days_selected">Дні не обрано</string>
<string name="timer">Таймер</string>
<string name="stopwatch">Секундомір</string>
<string name="lap">Інтервал</string>
<string name="stopwatch_stopped">Секундомір зупинено</string>
<string name="timer_stopped">Таймер зупинено</string>

View File

@ -7,6 +7,7 @@
<string name="label">标签</string>
<string name="no_days_selected">未选择哪一天</string>
<string name="timer">定时器</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">分段</string>
<string name="stopwatch_stopped">秒表已停止</string>
<string name="timer_stopped">定时器已停止</string>

View File

@ -6,6 +6,7 @@
<string name="label">標籤</string>
<string name="no_days_selected">未選擇哪一天</string>
<string name="timer">計時器</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">分段</string>
<string name="stopwatch_stopped">碼錶已停止</string>
<string name="timer_stopped">計時器已停止</string>

View File

@ -6,6 +6,7 @@
<string name="label">Label</string>
<string name="no_days_selected">No days selected</string>
<string name="timer">Timer</string>
<string name="stopwatch">Stopwatch</string>
<string name="lap">Lap</string>
<string name="stopwatch_stopped">Stopwatch has been stopped</string>
<string name="timer_stopped">Timer has been stopped</string>