Suppose I have an action to be executed after a certain amount of time without the user touching the screen. How can I implement a timer that executes an action when it times out, but starts over every time the user touches the screen?
Asked
Active
Viewed 1,045 times
0
-
[Getting Touches](https://stackoverflow.com/a/7450074/6783797) and combine it with [Tenfour04](https://stackoverflow.com/a/59005100/6783797)s answer – Tomes Nov 23 '19 at 08:49
2 Answers
1
I searched through a few answers and couldn't find anything as simple as the solution I wanted for this problem. Heres what worked for me:
I made use of the onUserInteraction() function, which is called every time the user touches the screen. I declared a CountDownTimer that gets started in onCreate() and canceled in onDestroy(). Every time onUserInteraction() is called, the CountDownTimer is canceled, reset, and then started again. When the CountDownTimer finishes, the action is performed.
package com.example.inactivityapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.CountDownTimer
import android.util.Log
import android.widget.Toast
private val TAG = InactivityActivity::class.java.simpleName
private const val INACTIVITY_SECONDS: Int = 5
class InactivityActivity : AppCompatActivity() {
var inactivitySeconds = INACTIVITY_SECONDS
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_inactivity)
inactivityCountDownTimer.start()
}
override fun onDestroy() {
super.onDestroy()
inactivityCountDownTimer.cancel()
}
override fun onUserInteraction() {
super.onUserInteraction()
Log.i(TAG, "user interaction")
inactivityCountDownTimer.cancel()
inactivitySeconds = INACTIVITY_SECONDS
inactivityCountDownTimer.start()
}
var inactivityCountDownTimer =
object : CountDownTimer(inactivitySeconds * 1000.toLong(), 1000) {
override fun onTick(millisUntilFinished: Long) {
Log.i(TAG, inactivitySeconds.toString())
inactivitySeconds--
}
override fun onFinish() {
Toast.makeText(
this@InactivityActivity,
"Activity Timeout: Perform timeout task",
Toast.LENGTH_LONG
).show()
Log.i(TAG, "activity timeout")
}
}
}

August W. Gruneisen
- 207
- 1
- 3
- 9
1
Here's an untested idea with coroutines:
private const val INACTIVITY_SECONDS: Int = 5
abstract class InactivityActivity : AppCompatActivity() {
private val counterScope = CoroutineScope(Dispatchers.Main)
private fun restartCountDown() {
counterScope.cancel()
counterScope.launch {
delay(INACTIVITY_SECONDS * 1000L)
onInactivity()
}
}
protected abstract fun onInactivity()
override fun onPause() {
super.onPause()
counterScope.cancel()
}
override fun onResume() {
super.onResume()
restartCountDown()
}
override fun onUserInteraction() {
super.onUserInteraction()
restartCountDown()
}
}

Tenfour04
- 83,111
- 11
- 94
- 154