Skip to content
Snippets Groups Projects
Unverified Commit a36cf7ee authored by Matthias Urhahn's avatar Matthias Urhahn Committed by GitHub
Browse files

Fix ForegroundState not emitting updated values. (#2112)

parent 57e95dfc
No related branches found
No related tags found
No related merge requests found
...@@ -3,7 +3,7 @@ package de.rki.coronawarnapp.util ...@@ -3,7 +3,7 @@ package de.rki.coronawarnapp.util
import android.content.Context import android.content.Context
import android.net.wifi.WifiManager import android.net.wifi.WifiManager
import android.os.PowerManager import android.os.PowerManager
import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import de.rki.coronawarnapp.diagnosiskeys.download.DownloadDiagnosisKeysTask import de.rki.coronawarnapp.diagnosiskeys.download.DownloadDiagnosisKeysTask
import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.LocalData
...@@ -12,6 +12,7 @@ import de.rki.coronawarnapp.task.common.DefaultTaskRequest ...@@ -12,6 +12,7 @@ import de.rki.coronawarnapp.task.common.DefaultTaskRequest
import de.rki.coronawarnapp.task.submitBlocking import de.rki.coronawarnapp.task.submitBlocking
import de.rki.coronawarnapp.util.device.BackgroundModeStatus import de.rki.coronawarnapp.util.device.BackgroundModeStatus
import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.di.AppContext
import de.rki.coronawarnapp.util.di.ProcessLifecycle
import de.rki.coronawarnapp.worker.BackgroundWorkScheduler import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
...@@ -25,7 +26,8 @@ import javax.inject.Singleton ...@@ -25,7 +26,8 @@ import javax.inject.Singleton
class WatchdogService @Inject constructor( class WatchdogService @Inject constructor(
@AppContext private val context: Context, @AppContext private val context: Context,
private val taskController: TaskController, private val taskController: TaskController,
private val backgroundModeStatus: BackgroundModeStatus private val backgroundModeStatus: BackgroundModeStatus,
@ProcessLifecycle private val processLifecycleOwner: LifecycleOwner
) { ) {
private val powerManager by lazy { private val powerManager by lazy {
...@@ -44,7 +46,7 @@ class WatchdogService @Inject constructor( ...@@ -44,7 +46,7 @@ class WatchdogService @Inject constructor(
} }
Timber.tag(TAG).v("Acquiring wakelocks for watchdog routine.") Timber.tag(TAG).v("Acquiring wakelocks for watchdog routine.")
ProcessLifecycleOwner.get().lifecycleScope.launch { processLifecycleOwner.lifecycleScope.launch {
// A wakelock as the OS does not handle this for us like in the background job execution // A wakelock as the OS does not handle this for us like in the background job execution
val wakeLock = createWakeLock() val wakeLock = createWakeLock()
// A wifi lock to wake up the wifi connection in case the device is dozing // A wifi lock to wake up the wifi connection in case the device is dozing
......
...@@ -2,9 +2,9 @@ package de.rki.coronawarnapp.util.device ...@@ -2,9 +2,9 @@ package de.rki.coronawarnapp.util.device
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner import de.rki.coronawarnapp.util.di.ProcessLifecycle
import de.rki.coronawarnapp.CoronaWarnApplication
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onCompletion
...@@ -15,7 +15,9 @@ import javax.inject.Inject ...@@ -15,7 +15,9 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class ForegroundState @Inject constructor() { class ForegroundState @Inject constructor(
@ProcessLifecycle val processLifecycleOwner: LifecycleOwner
) {
val isInForeground: Flow<Boolean> by lazy { val isInForeground: Flow<Boolean> by lazy {
MutableStateFlow(false).apply { MutableStateFlow(false).apply {
...@@ -23,19 +25,19 @@ class ForegroundState @Inject constructor() { ...@@ -23,19 +25,19 @@ class ForegroundState @Inject constructor() {
@Suppress("unused") @Suppress("unused")
@OnLifecycleEvent(Lifecycle.Event.ON_START) @OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForegrounded() { fun onAppForegrounded() {
CoronaWarnApplication.isAppInForeground = true
Timber.v("App is in the foreground") Timber.v("App is in the foreground")
tryEmit(true)
} }
@Suppress("unused") @Suppress("unused")
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackgrounded() { fun onAppBackgrounded() {
CoronaWarnApplication.isAppInForeground = false
Timber.v("App is in the background") Timber.v("App is in the background")
tryEmit(false)
} }
} }
val processLifecycle = ProcessLifecycleOwner.get().lifecycle val processLifecycle = processLifecycleOwner.lifecycle
processLifecycle.addObserver(foregroundStateUpdater) processLifecycle.addObserver(foregroundStateUpdater)
} }
.onStart { Timber.v("isInForeground FLOW start") } .onStart { Timber.v("isInForeground FLOW start") }
......
...@@ -8,6 +8,8 @@ import android.content.Context ...@@ -8,6 +8,8 @@ import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.navigation.NavDeepLinkBuilder import androidx.navigation.NavDeepLinkBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import dagger.Module import dagger.Module
...@@ -63,4 +65,9 @@ class AndroidModule { ...@@ -63,4 +65,9 @@ class AndroidModule {
@Provides @Provides
@Singleton @Singleton
fun activityManager(@AppContext context: Context): ActivityManager = context.getSystemService()!! fun activityManager(@AppContext context: Context): ActivityManager = context.getSystemService()!!
@Provides
@Singleton
@ProcessLifecycle
fun procressLifecycleOwner(): LifecycleOwner = ProcessLifecycleOwner.get()
} }
package de.rki.coronawarnapp.util.di
import javax.inject.Qualifier
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class ProcessLifecycle
package de.rki.coronawarnapp.util.device
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import io.kotest.matchers.shouldBe
import io.mockk.MockKAnnotations
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.test.runBlockingTest
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import testhelpers.BaseTest
import testhelpers.coroutines.test
class ForegroundStateTest : BaseTest() {
@MockK lateinit var lifecycleOwner: LifecycleOwner
lateinit var lifecycle: LifecycleRegistry
@BeforeEach
fun setup() {
MockKAnnotations.init(this)
lifecycle = LifecycleRegistry(lifecycleOwner)
every { lifecycleOwner.lifecycle } returns lifecycle
}
@AfterEach
fun teardown() {
clearAllMocks()
}
fun createInstance() = ForegroundState(
processLifecycleOwner = lifecycleOwner
)
@Test
fun `test emissions`() = runBlockingTest {
val instance = createInstance()
val testCollector = instance.isInForeground.test(startOnScope = this)
testCollector.latestValue shouldBe false
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)
testCollector.latestValue shouldBe true
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
testCollector.latestValue shouldBe false
testCollector.cancel()
advanceUntilIdle()
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment