main

square/leakcanary

Last updated at: 29/12/2023 09:38

BackgroundListener.kt

TLDR

The BackgroundListener class in the provided file is used to track whether the app is in the background by overriding ActivityLifecycleCallbacks methods and using ProcessInfo to check the app's importance. It provides methods to install and uninstall the listener, and a callback to report the background state.

Methods

install(application: Application)

This method registers the BackgroundListener as an ActivityLifecycleCallbacks for the provided Application, updates the background state to false, and starts checking if the app is in the background.

uninstall(application: Application)

This method unregisters the BackgroundListener as an ActivityLifecycleCallbacks from the provided Application, updates the background state to false, and stops checking if the app is in the background.

onActivityPaused(activity: Activity)

This method is called when an activity is paused. It removes the background-checking callback, and posts a new callback with a delay of BACKGROUND_DELAY_MS (1000 milliseconds).

onActivityResumed(activity: Activity)

This method is called when an activity is resumed. It updates the background state to false, and removes the background-checking callback.

Classes

None

package leakcanary.internal

import android.app.Activity
import android.app.Application
import android.app.Application.ActivityLifecycleCallbacks
import leakcanary.ProcessInfo
import leakcanary.internal.friendly.mainHandler
import leakcanary.internal.friendly.noOpDelegate

/**
 * Tracks whether the app is in background, based on the app's importance.
 */
internal class BackgroundListener(
  private val processInfo: ProcessInfo,
  private val callback: (Boolean) -> Unit
) : ActivityLifecycleCallbacks by noOpDelegate() {

  private val checkAppInBackground: Runnable = object : Runnable {
    override fun run() {
      val appInBackgroundNow = processInfo.isImportanceBackground
      updateBackgroundState(appInBackgroundNow)
      if (!appInBackgroundNow) {
        mainHandler.removeCallbacks(this)
        mainHandler.postDelayed(this, BACKGROUND_REPEAT_DELAY_MS)
      }
    }
  }

  private fun updateBackgroundState(appInBackgroundNow: Boolean) {
    if (appInBackground != appInBackgroundNow) {
      appInBackground = appInBackgroundNow
      callback.invoke(appInBackgroundNow)
    }
  }

  private var appInBackground = false

  fun install(application: Application) {
    application.registerActivityLifecycleCallbacks(this)
    updateBackgroundState(appInBackgroundNow = false)
    checkAppInBackground.run()
  }

  fun uninstall(application: Application) {
    application.unregisterActivityLifecycleCallbacks(this)
    updateBackgroundState(appInBackgroundNow = false)
    mainHandler.removeCallbacks(checkAppInBackground)
  }

  override fun onActivityPaused(activity: Activity) {
    mainHandler.removeCallbacks(checkAppInBackground)
    mainHandler.postDelayed(checkAppInBackground, BACKGROUND_DELAY_MS)
  }

  override fun onActivityResumed(activity: Activity) {
    updateBackgroundState(appInBackgroundNow = false)
    mainHandler.removeCallbacks(checkAppInBackground)
  }

  companion object {
    private const val BACKGROUND_DELAY_MS = 1000L
    private const val BACKGROUND_REPEAT_DELAY_MS = 5000L
  }
}