1 package leakcanary.internal
2 
3 import android.app.Activity
4 import android.app.Application
5 import android.app.Application.ActivityLifecycleCallbacks
6 import leakcanary.ProcessInfo
7 import leakcanary.internal.friendly.mainHandler
8 import leakcanary.internal.friendly.noOpDelegate
9 
10 /**
11  * Tracks whether the app is in background, based on the app's importance.
12  */
13 internal class BackgroundListener(
14   private val processInfo: ProcessInfo,
15   private val callback: (Boolean) -> Unit
16 ) : ActivityLifecycleCallbacks by noOpDelegate() {
17 
18   private val checkAppInBackground: Runnable = object : Runnable {
runnull19     override fun run() {
20       val appInBackgroundNow = processInfo.isImportanceBackground
21       updateBackgroundState(appInBackgroundNow)
22       if (!appInBackgroundNow) {
23         mainHandler.removeCallbacks(this)
24         mainHandler.postDelayed(this, BACKGROUND_REPEAT_DELAY_MS)
25       }
26     }
27   }
28 
updateBackgroundStatenull29   private fun updateBackgroundState(appInBackgroundNow: Boolean) {
30     if (appInBackground != appInBackgroundNow) {
31       appInBackground = appInBackgroundNow
32       callback.invoke(appInBackgroundNow)
33     }
34   }
35 
36   private var appInBackground = false
37 
installnull38   fun install(application: Application) {
39     application.registerActivityLifecycleCallbacks(this)
40     updateBackgroundState(appInBackgroundNow = false)
41     checkAppInBackground.run()
42   }
43 
uninstallnull44   fun uninstall(application: Application) {
45     application.unregisterActivityLifecycleCallbacks(this)
46     updateBackgroundState(appInBackgroundNow = false)
47     mainHandler.removeCallbacks(checkAppInBackground)
48   }
49 
onActivityPausednull50   override fun onActivityPaused(activity: Activity) {
51     mainHandler.removeCallbacks(checkAppInBackground)
52     mainHandler.postDelayed(checkAppInBackground, BACKGROUND_DELAY_MS)
53   }
54 
onActivityResumednull55   override fun onActivityResumed(activity: Activity) {
56     updateBackgroundState(appInBackgroundNow = false)
57     mainHandler.removeCallbacks(checkAppInBackground)
58   }
59 
60   companion object {
61     private const val BACKGROUND_DELAY_MS = 1000L
62     private const val BACKGROUND_REPEAT_DELAY_MS = 5000L
63   }
64 }
65