diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForAPIFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForAPIFragment.kt
index c7c45d7babc6cc52af544b1390ee3c23df91ad01..6f8e10d248095717d40e0de6284c41a731b541bc 100644
--- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForAPIFragment.kt
+++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/api/ui/TestForAPIFragment.kt
@@ -33,7 +33,6 @@ import com.google.zxing.BarcodeFormat
 import com.google.zxing.integration.android.IntentIntegrator
 import com.google.zxing.integration.android.IntentResult
 import com.google.zxing.qrcode.QRCodeWriter
-import de.rki.coronawarnapp.CoronaWarnApplication
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.RiskLevelAndKeyRetrievalBenchmark
 import de.rki.coronawarnapp.databinding.FragmentTestForAPIBinding
@@ -55,6 +54,7 @@ import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.storage.tracing.TracingIntervalRepository
 import de.rki.coronawarnapp.transaction.RiskLevelTransaction
 import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel
+import de.rki.coronawarnapp.util.CWADebug
 import de.rki.coronawarnapp.util.KeyFileHelper
 import de.rki.coronawarnapp.util.di.AppInjector
 import de.rki.coronawarnapp.util.di.AutoInject
@@ -298,9 +298,9 @@ class TestForAPIFragment : Fragment(R.layout.fragment_test_for_a_p_i),
             false
         }
 
-        binding.testLogfileToggle.isChecked = CoronaWarnApplication.fileLogger?.isLogging ?: false
+        binding.testLogfileToggle.isChecked = CWADebug.fileLogger?.isLogging ?: false
         binding.testLogfileToggle.setOnClickListener { buttonView ->
-            CoronaWarnApplication.fileLogger?.let {
+            CWADebug.fileLogger?.let {
                 if (binding.testLogfileToggle.isChecked) {
                     it.start()
                 } else {
@@ -310,7 +310,7 @@ class TestForAPIFragment : Fragment(R.layout.fragment_test_for_a_p_i),
         }
 
         binding.testLogfileShare.setOnClickListener {
-            CoronaWarnApplication.fileLogger?.let {
+            CWADebug.fileLogger?.let {
                 lifecycleScope.launch {
                     val targetPath = withContext(Dispatchers.IO) {
                         async {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
index 184ec476975eeee93a524b35091a2208054fc6ad..abeedeea482c5d135171cb36b9cd80306fd62db4 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
@@ -6,14 +6,11 @@ import android.app.Application
 import android.content.Context
 import android.content.IntentFilter
 import android.content.pm.ActivityInfo
-import android.net.wifi.WifiManager
 import android.os.Bundle
-import android.os.PowerManager
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleObserver
 import androidx.lifecycle.OnLifecycleEvent
 import androidx.lifecycle.ProcessLifecycleOwner
-import androidx.lifecycle.lifecycleScope
 import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import androidx.work.Configuration
 import androidx.work.WorkManager
@@ -23,187 +20,115 @@ import dagger.android.HasAndroidInjector
 import de.rki.coronawarnapp.exception.reporting.ErrorReportReceiver
 import de.rki.coronawarnapp.exception.reporting.ReportingConstants.ERROR_REPORT_LOCAL_BROADCAST_CHANNEL
 import de.rki.coronawarnapp.notification.NotificationHelper
-import de.rki.coronawarnapp.storage.LocalData
-import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction
 import de.rki.coronawarnapp.util.CWADebug
-import de.rki.coronawarnapp.util.ConnectivityHelper
-import de.rki.coronawarnapp.util.debug.FileLogger
+import de.rki.coronawarnapp.util.WatchdogService
 import de.rki.coronawarnapp.util.di.AppInjector
 import de.rki.coronawarnapp.util.di.ApplicationComponent
 import de.rki.coronawarnapp.worker.BackgroundWorkHelper
-import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
-import kotlinx.coroutines.launch
 import org.conscrypt.Conscrypt
 import timber.log.Timber
 import java.security.Security
-import java.util.UUID
 import javax.inject.Inject
 
-class CoronaWarnApplication : Application(), LifecycleObserver,
-    Application.ActivityLifecycleCallbacks, HasAndroidInjector {
+class CoronaWarnApplication : Application(), HasAndroidInjector {
 
-    companion object {
-        val TAG: String? = CoronaWarnApplication::class.simpleName
-        private lateinit var instance: CoronaWarnApplication
-
-        /* describes if the app is in foreground
-         * Initialized to false, because app could also be started by a background job.
-         * For the cases where the app is started via the launcher icon, the onAppForegrounded
-         * event will be called, setting it to true
-         */
-        var isAppInForeground = false
-
-        fun getAppContext(): Context =
-            instance.applicationContext
-
-        const val TEN_MINUTE_TIMEOUT_IN_MS = 10 * 60 * 1000L
-        var fileLogger: FileLogger? = null
-    }
+    @Inject lateinit var component: ApplicationComponent
 
-    private lateinit var errorReceiver: ErrorReportReceiver
-
-    @Inject
-    lateinit var component: ApplicationComponent
-
-    @Inject
-    lateinit var androidInjector: DispatchingAndroidInjector<Any>
+    @Inject lateinit var androidInjector: DispatchingAndroidInjector<Any>
     override fun androidInjector(): AndroidInjector<Any> = androidInjector
 
+    @Inject lateinit var watchdogService: WatchdogService
+
     override fun onCreate() {
         instance = this
         super.onCreate()
-        AppInjector.init(this)
+        CWADebug.init(this)
 
-        if (CWADebug.isDebugBuildOrMode) System.setProperty("kotlinx.coroutines.debug", "on")
+        Timber.v("onCreate(): Initializing Dagger")
+        AppInjector.init(this)
 
-        val configuration = Configuration.Builder()
-            .setMinimumLoggingLevel(android.util.Log.DEBUG)
-            .build()
-        WorkManager.initialize(this, configuration)
+        Timber.v("onCreate(): Initializing WorkManager")
+        Configuration.Builder()
+            .apply { setMinimumLoggingLevel(android.util.Log.DEBUG) }.build()
+            .let { WorkManager.initialize(this, it) }
 
         NotificationHelper.createNotificationChannel()
+
         // Enable Conscrypt for TLS1.3 Support below API Level 29
         Security.insertProviderAt(Conscrypt.newProvider(), 1)
-        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
-        registerActivityLifecycleCallbacks(this)
 
-        if (BuildConfig.DEBUG) {
-            Timber.plant(Timber.DebugTree())
-        }
-        if ((BuildConfig.FLAVOR == "deviceForTesters" || BuildConfig.DEBUG)) {
-            fileLogger = FileLogger(this)
-        }
+        ProcessLifecycleOwner.get().lifecycle.addObserver(foregroundStateUpdater)
+        registerActivityLifecycleCallbacks(activityLifecycleCallback)
 
-        // notification to test the WakeUpService from Google when the app
-        // was force stopped
+        // notification to test the WakeUpService from Google when the app was force stopped
         BackgroundWorkHelper.sendDebugNotification(
             "Application onCreate", "App was woken up"
         )
-        // Only do this if the background jobs are enabled
-        if (ConnectivityHelper.autoModeEnabled(applicationContext)) {
-            ProcessLifecycleOwner.get().lifecycleScope.launch {
-                // we want a wakelock as the OS does not handle this for us like in the background
-                // job execution
-                val wakeLock = createWakeLock()
-                // we keep a wifi lock to wake up the wifi connection in case the device is dozing
-                val wifiLock = createWifiLock()
-                try {
-                    BackgroundWorkHelper.sendDebugNotification(
-                        "Automatic mode is on", "Check if we have downloaded keys already today"
-                    )
-                    RetrieveDiagnosisKeysTransaction.startWithConstraints()
-                } catch (e: Exception) {
-                    BackgroundWorkHelper.sendDebugNotification(
-                        "RetrieveDiagnosisKeysTransaction failed",
-                        (e.localizedMessage
-                            ?: "Unknown exception occurred in onCreate") + "\n\n" + (e.cause
-                            ?: "Cause is unknown").toString()
-                    )
-                    // retry the key retrieval in case of an error with a scheduled work
-                    BackgroundWorkScheduler.scheduleDiagnosisKeyOneTimeWork()
-                }
-
-                if (wifiLock.isHeld) wifiLock.release()
-                if (wakeLock.isHeld) wakeLock.release()
-            }
+        watchdogService.launch()
+    }
+
+    private val foregroundStateUpdater = object : LifecycleObserver {
+        @OnLifecycleEvent(Lifecycle.Event.ON_START)
+        fun onAppForegrounded() {
+            isAppInForeground = true
+            Timber.v("App is in the foreground")
+        }
 
-            // if the user is onboarded we will schedule period background jobs
-            // in case the app was force stopped and woken up again by the Google WakeUpService
-            if (LocalData.onboardingCompletedTimestamp() != null) BackgroundWorkScheduler.startWorkScheduler()
+        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+        fun onAppBackgrounded() {
+            isAppInForeground = false
+            Timber.v("App is in the background")
         }
     }
 
-    private fun createWakeLock(): PowerManager.WakeLock =
-        (getSystemService(Context.POWER_SERVICE) as PowerManager)
-            .run {
-                newWakeLock(
-                    PowerManager.PARTIAL_WAKE_LOCK,
-                    TAG + "-WAKE-" + UUID.randomUUID().toString()
-                ).apply {
-                    acquire(TEN_MINUTE_TIMEOUT_IN_MS)
-                }
-            }
+    private val activityLifecycleCallback = object : ActivityLifecycleCallbacks {
+        private val localBM by lazy {
+            LocalBroadcastManager.getInstance(this@CoronaWarnApplication)
+        }
+        private var errorReceiver: ErrorReportReceiver? = null
 
-    private fun createWifiLock(): WifiManager.WifiLock =
-        (getSystemService(Context.WIFI_SERVICE) as WifiManager)
-            .run {
-                createWifiLock(
-                    WifiManager.WIFI_MODE_FULL_HIGH_PERF,
-                    TAG + "-WIFI-" + UUID.randomUUID().toString()
-                ).apply {
-                    acquire()
-                }
+        override fun onActivityPaused(activity: Activity) {
+            errorReceiver?.let {
+                localBM.unregisterReceiver(it)
+                errorReceiver = null
             }
+        }
 
-    /**
-     * Callback when the app is open but backgrounded
-     */
-    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
-    fun onAppBackgrounded() {
-        isAppInForeground = false
-        Timber.v("App backgrounded")
-    }
+        override fun onActivityStarted(activity: Activity) {}
 
-    /**
-     * Callback when the app is foregrounded
-     */
-    @OnLifecycleEvent(Lifecycle.Event.ON_START)
-    fun onAppForegrounded() {
-        isAppInForeground = true
-        Timber.v("App foregrounded")
-    }
+        override fun onActivityDestroyed(activity: Activity) {}
 
-    override fun onActivityPaused(activity: Activity) {
-        // unregisters error receiver
-        LocalBroadcastManager.getInstance(this).unregisterReceiver(errorReceiver)
-    }
+        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
 
-    override fun onActivityStarted(activity: Activity) {
-        // does not override function. Empty on intention
-    }
+        override fun onActivityStopped(activity: Activity) {}
 
-    override fun onActivityDestroyed(activity: Activity) {
-        // does not override function. Empty on intention
-    }
+        @SuppressLint("SourceLockedOrientationActivity")
+        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
+            activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
+        }
 
-    override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
-        // does not override function. Empty on intention
-    }
+        override fun onActivityResumed(activity: Activity) {
+            errorReceiver?.let {
+                localBM.unregisterReceiver(it)
+                errorReceiver = null
+            }
 
-    override fun onActivityStopped(activity: Activity) {
-        // does not override function. Empty on intention
+            errorReceiver = ErrorReportReceiver(activity).also {
+                localBM.registerReceiver(it, IntentFilter(ERROR_REPORT_LOCAL_BROADCAST_CHANNEL))
+            }
+        }
     }
 
-    @SuppressLint("SourceLockedOrientationActivity")
-    override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
-        // set screen orientation to portrait
-        activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
-    }
+    companion object {
+        private lateinit var instance: CoronaWarnApplication
+
+        /* describes if the app is in foreground
+         * Initialized to false, because app could also be started by a background job.
+         * For the cases where the app is started via the launcher icon, the onAppForegrounded
+         * event will be called, setting it to true
+         */
+        var isAppInForeground = false
 
-    override fun onActivityResumed(activity: Activity) {
-        errorReceiver =
-            ErrorReportReceiver(activity)
-        LocalBroadcastManager.getInstance(this)
-            .registerReceiver(errorReceiver, IntentFilter(ERROR_REPORT_LOCAL_BROADCAST_CHANNEL))
+        fun getAppContext(): Context = instance.applicationContext
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CWADebug.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CWADebug.kt
index cc614f2797b1f7b66ff248131d4cbc5860716793..4c0373fa49911ef8e3eaac545eeccafa7d61cace 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CWADebug.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CWADebug.kt
@@ -1,8 +1,24 @@
 package de.rki.coronawarnapp.util
 
+import android.app.Application
 import de.rki.coronawarnapp.BuildConfig
+import de.rki.coronawarnapp.util.debug.FileLogger
+import timber.log.Timber
 
 object CWADebug {
+    var fileLogger: FileLogger? = null
+
+    fun init(application: Application) {
+        if (isDebugBuildOrMode) System.setProperty("kotlinx.coroutines.debug", "on")
+
+        if (BuildConfig.DEBUG) {
+            Timber.plant(Timber.DebugTree())
+        }
+        if ((BuildConfig.FLAVOR == "deviceForTesters" || BuildConfig.DEBUG)) {
+            fileLogger = FileLogger(application)
+        }
+    }
+
     val isDebugBuildOrMode: Boolean
         get() = BuildConfig.DEBUG || BuildConfig.BUILD_VARIANT == "deviceForTesters"
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/WatchdogService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/WatchdogService.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d2e5aa97c9fc787f2874d65145e9c203a8457d9b
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/WatchdogService.kt
@@ -0,0 +1,77 @@
+package de.rki.coronawarnapp.util
+
+import android.content.Context
+import android.net.wifi.WifiManager
+import android.os.PowerManager
+import androidx.lifecycle.ProcessLifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction
+import de.rki.coronawarnapp.worker.BackgroundWorkHelper
+import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
+import kotlinx.coroutines.launch
+import timber.log.Timber
+import java.util.UUID
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class WatchdogService @Inject constructor(private val context: Context) {
+
+    private val powerManager by lazy {
+        context.getSystemService(Context.POWER_SERVICE) as PowerManager
+    }
+    private val wifiManager by lazy {
+        context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
+    }
+
+    fun launch() {
+        // Only do this if the background jobs are enabled
+        if (!ConnectivityHelper.autoModeEnabled(context)) {
+            Timber.d("Background jobs are not enabled, aborting.")
+            return
+        }
+
+        Timber.v("Acquiring wakelocks for watchdog routine.")
+        ProcessLifecycleOwner.get().lifecycleScope.launch {
+            // A wakelock as the OS does not handle this for us like in the background job execution
+            val wakeLock = createWakeLock()
+            // A wifi lock to wake up the wifi connection in case the device is dozing
+            val wifiLock = createWifiLock()
+            try {
+                BackgroundWorkHelper.sendDebugNotification(
+                    "Automatic mode is on", "Check if we have downloaded keys already today"
+                )
+                RetrieveDiagnosisKeysTransaction.startWithConstraints()
+            } catch (e: Exception) {
+                BackgroundWorkHelper.sendDebugNotification(
+                    "RetrieveDiagnosisKeysTransaction failed",
+                    (e.localizedMessage
+                        ?: "Unknown exception occurred in onCreate") + "\n\n" + (e.cause
+                        ?: "Cause is unknown").toString()
+                )
+                // retry the key retrieval in case of an error with a scheduled work
+                BackgroundWorkScheduler.scheduleDiagnosisKeyOneTimeWork()
+            }
+
+            if (wifiLock.isHeld) wifiLock.release()
+            if (wakeLock.isHeld) wakeLock.release()
+        }
+
+        // if the user is onboarded we will schedule period background jobs
+        // in case the app was force stopped and woken up again by the Google WakeUpService
+        if (LocalData.onboardingCompletedTimestamp() != null) BackgroundWorkScheduler.startWorkScheduler()
+    }
+
+    private fun createWakeLock(): PowerManager.WakeLock = powerManager
+        .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CWA-WAKE-${UUID.randomUUID()}")
+        .apply { acquire(TEN_MINUTE_TIMEOUT_IN_MS) }
+
+    private fun createWifiLock(): WifiManager.WifiLock = wifiManager
+        .createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "CWA-WIFI-${UUID.randomUUID()}")
+        .apply { acquire() }
+
+    companion object {
+        private const val TEN_MINUTE_TIMEOUT_IN_MS = 10 * 60 * 1000L
+    }
+}