You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Android实现60秒用户无活动检测及代码问题排查

Android应用内持续无活动检测解决方案

原代码存在的问题

  • 无活动提示触发后计时器不会重启,只能完成一次检测
  • onTouchEvent仅能监听MainActivity自身的触摸操作,Fragment内的用户触摸不会触发该方法,导致Fragment中操作时计时器无法重置

解决方案实现步骤

  1. 循环检测逻辑:在无活动提示触发后重新启动计时器,实现持续检测
  2. 全局触摸捕获:重写dispatchTouchEvent方法(替代onTouchEvent),该方法能拦截所有分发到Activity及其内部Fragment的触摸事件,确保Fragment内操作也能重置计时器
  3. 覆盖其他用户操作:重写onKeyDown方法,捕获按键操作(如返回键、菜单键),同步重置计时器
  4. 生命周期适配:应用进入后台时停止计时器,回到前台时重启,避免后台误触发;销毁时清理Handler防止内存泄漏

完整代码实现

class MainActivity : AppCompatActivity() {
    private val inactiveTime = 60000L // 60秒无活动阈值
    private lateinit var handler: Handler
    private lateinit var checkInactiveRunnable: Runnable

    // 无活动提示布局(需在布局文件中定义,初始设为GONE)
    private lateinit var inactiveTipLayout: View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        inactiveTipLayout = findViewById(R.id.inactive_tip_layout)

        // 初始化Handler与循环检测任务
        handler = Handler(Looper.getMainLooper())
        checkInactiveRunnable = Runnable {
            showInactiveTip()
            startInactiveCheck() // 触发提示后重启检测
        }

        startInactiveCheck() // 启动首次检测
    }

    private fun startInactiveCheck() {
        handler.postDelayed(checkInactiveRunnable, inactiveTime)
    }

    private fun stopInactiveCheck() {
        handler.removeCallbacks(checkInactiveRunnable)
        inactiveTipLayout.visibility = View.GONE
    }

    private fun showInactiveTip() {
        inactiveTipLayout.visibility = View.VISIBLE
        Log.d("InactiveCheck", "用户已无活动60秒")
        // 可在此添加弹窗、震动等提示逻辑
    }

    // 拦截所有触摸事件(包括Fragment内操作)
    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        if (ev.action == MotionEvent.ACTION_DOWN) {
            stopInactiveCheck()
            startInactiveCheck()
        }
        return super.dispatchTouchEvent(ev)
    }

    // 捕获按键操作,重置计时器
    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        stopInactiveCheck()
        startInactiveCheck()
        return super.onKeyDown(keyCode, event)
    }

    // 后台时停止检测
    override fun onPause() {
        super.onPause()
        stopInactiveCheck()
    }

    // 前台时重启检测
    override fun onResume() {
        super.onResume()
        startInactiveCheck()
    }

    // 销毁时清理Handler,避免内存泄漏
    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacksAndMessages(null)
    }
}

补充说明

  • 需确保布局文件中存在inactive_tip_layout,并设置初始可见性为GONE
  • dispatchTouchEvent已覆盖所有触摸相关操作(点击、滑动、长按等),无需额外处理
  • 若想进一步优化内存泄漏问题,可改用ViewModel结合Coroutine实现计时器,用delay替代postDelayed,用Job控制启停

内容的提问来源于stack exchange,提问作者Ajith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:20:05