Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Detective is a small library that detects Application focus changes
object Detective : SimpleActivityLifecycleCallbacks() {
private infix fun <T> List<T>.notContains(element: T): Boolean {
return !contains(element)
}
/** Timeout when app looses focus */
private val backgroundEnterTimeout: Int = 120
private val appFocusListeners = ArrayList<ApplicationFocusListener>()
private var registered = false
private val appEnteredBackground = AtomicBoolean(false)
private val appHasFocus = AtomicBoolean(false)
fun register(context: Context) {
if (!registered) {
registered = true
(context.applicationContext as Application).registerActivityLifecycleCallbacks(this)
}
}
/** Start listening focus changes */
fun listen(focusListener: ApplicationFocusListener): Boolean {
if (appFocusListeners notContains focusListener) {
appFocusListeners += focusListener
return true
}
return false
}
/** Stop listening focus changes */
fun stopListening(focusListener: ApplicationFocusListener): Boolean {
return appFocusListeners.remove(focusListener)
}
override fun onActivityPaused(activity: Activity) {
appHasFocus.getAndSet(false)
activity.window.decorView.postDelayed({
if (!appHasFocus.get()) {
appEnteredBackground.compareAndSet(false, true)
appFocusListeners.forEach { it.changed(false) }
}
}, backgroundEnterTimeout.toLong())
}
override fun onActivityResumed(activity: Activity) {
appHasFocus.getAndSet(true)
appEnteredBackground.getAndSet(false)
appFocusListeners.forEach { it.changed(true) }
}
/**
* Receive application focus changes
*
* By application focus means, that at least one window has focus gained,
* oterwise app entered background state
* */
interface ApplicationFocusListener {
/**
* Called whenever application loose or gain focus back
*
* @param hasFocus True on Application is focused
*/
fun changed(hasFocus: Boolean)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment