如何在用户闲置X时长后锁定账户?附CountDownTimer实现疑问
Android 闲置时长触发操作(锁定账户/显示指定Activity)
针对你提到的两个需求,我来帮你梳理下正确的实现思路,先解决你当前代码里的问题,再给出完整可行的方案:
首先要指出你代码里的一个关键错误:BaseActivity baseActivity = new BaseActivity(); —— Android里绝对不能直接new一个Activity实例,Activity的启动必须通过Intent结合上下文来完成,直接实例化会导致各种生命周期异常。
一、基础实现:基于BaseActivity的闲置监听
如果你的所有页面都需要监听闲置状态,最简洁的方式是封装一个BaseActivity,让其他页面继承它,核心逻辑如下:
public class BaseActivity extends AppCompatActivity { private CountDownTimer inactivityTimer; // 自定义闲置时长,比如5分钟=300000毫秒 private static final long INACTIVITY_TIMEOUT = 300000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initInactivityTimer(); } // 初始化/重置闲置计时器 private void initInactivityTimer() { if (inactivityTimer != null) { inactivityTimer.cancel(); } inactivityTimer = new CountDownTimer(INACTIVITY_TIMEOUT, 1000) { @Override public void onTick(long millisUntilFinished) { // 可选:这里可以添加倒计时提示(比如状态栏显示剩余时间) } @Override public void onFinish() { // 闲置时间到,执行锁定账户+启动指定页面逻辑 handleInactiveState(); } }; inactivityTimer.start(); } // 用户有交互(触摸、按键等)时重置计时器 @Override public void onUserInteraction() { super.onUserInteraction(); initInactivityTimer(); } // 处理闲置状态的核心逻辑 private void handleInactiveState() { // 1. 锁定账户:清除用户登录状态、缓存、Token等 clearUserSession(); // 2. 启动指定的锁定/登录页面 Intent lockIntent = new Intent(this, LockScreenActivity.class); // 设置Flag避免栈混乱,清空当前页面栈,直接跳转到锁定页 lockIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(lockIntent); finish(); } // 示例:清除用户会话信息 private void clearUserSession() { SharedPreferences sp = getSharedPreferences("user_info", MODE_PRIVATE); sp.edit().clear().apply(); // 额外:清除内存中的用户对象、取消网络请求等 } // 页面销毁时及时取消计时器,避免内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if (inactivityTimer != null) { inactivityTimer.cancel(); inactivityTimer = null; } } }
二、进阶优化:全局监听App前后台状态
上面的基础实现只在页面前台时生效,如果需要监听App在前台的所有状态(包括切换页面时的闲置),可以结合Application的生命周期回调,实现全局闲置监听:
public class MyApp extends Application { private CountDownTimer globalInactivityTimer; private static final long INACTIVITY_TIMEOUT = 300000; private boolean isAppForeground = false; @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {} @Override public void onActivityStarted(@NonNull Activity activity) { isAppForeground = true; // App回到前台,重启计时器 restartGlobalTimer(); } @Override public void onActivityResumed(@NonNull Activity activity) {} @Override public void onActivityPaused(@NonNull Activity activity) {} @Override public void onActivityStopped(@NonNull Activity activity) { isAppForeground = false; // App进入后台,暂停计时器 if (globalInactivityTimer != null) { globalInactivityTimer.cancel(); } } @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {} @Override public void onActivityDestroyed(@NonNull Activity activity) {} }); } // 重置全局计时器 private void restartGlobalTimer() { if (globalInactivityTimer != null) { globalInactivityTimer.cancel(); } globalInactivityTimer = new CountDownTimer(INACTIVITY_TIMEOUT, 1000) { @Override public void onTick(long millisUntilFinished) {} @Override public void onFinish() { if (isAppForeground) { // 仅在前台时触发闲置操作 Intent lockIntent = new Intent(getApplicationContext(), LockScreenActivity.class); lockIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(lockIntent); } } }; globalInactivityTimer.start(); } // 提供给BaseActivity调用,用户交互时重置全局计时器 public void resetGlobalTimer() { if (isAppForeground) { restartGlobalTimer(); } } }
然后在BaseActivity的onUserInteraction里调用全局重置方法:
@Override public void onUserInteraction() { super.onUserInteraction(); ((MyApp) getApplication()).resetGlobalTimer(); }
三、注意事项
- 所有需要监听闲置的页面都要继承BaseActivity
onUserInteraction会响应用户的触摸、按键等操作,但弹窗(Dialog)、Toast等系统控件弹出时不会触发,若需要监听这类场景,要在弹窗的onShow/onDismiss方法里手动重置计时器- 闲置时长根据业务需求调整,单位为毫秒
- 启动锁定页面时的Flag要根据栈管理需求设置,避免出现页面叠加的问题
内容的提问来源于stack exchange,提问作者Noterezeck
相关产品推荐
相关产品推荐

