.NET MAUI全局检测用户无活动实现自动登出方案咨询
.NET MAUI全局无活动状态检测与自动登出方案
以下是几种实用的全局无活动检测实现方案,覆盖不同场景需求:
方案一:全局窗口事件监听 + 定时器服务
通过监听主窗口的触摸、按键事件,结合定时器实现全局无活动检测,无需修改每个页面。
实现步骤
- 创建单例无活动监控服务:
public class InactivityMonitor { public static InactivityMonitor Instance { get; } = new InactivityMonitor(); private Timer _inactivityTimer; private readonly TimeSpan _timeout = TimeSpan.FromMinutes(1); public event Action OnInactivityTimeout; public void StartMonitoring() { ResetTimer(); var mainWindow = Application.Current?.MainWindow; if (mainWindow != null) { mainWindow.PointerPressed += OnUserInteraction; mainWindow.KeyDown += OnUserInteraction; } } private void OnUserInteraction(object sender, EventArgs e) => ResetTimer(); private void ResetTimer() { _inactivityTimer?.Dispose(); _inactivityTimer = new Timer(_ => { MainThread.BeginInvokeOnMainThread(() => OnInactivityTimeout?.Invoke()); }, null, _timeout, Timeout.InfiniteTimeSpan); } public void StopMonitoring() { _inactivityTimer?.Dispose(); var mainWindow = Application.Current?.MainWindow; if (mainWindow != null) { mainWindow.PointerPressed -= OnUserInteraction; mainWindow.KeyDown -= OnUserInteraction; } } }
- 在App类中初始化并绑定逻辑:
public partial class App : Application { public App() { InitializeComponent(); InactivityMonitor.Instance.OnInactivityTimeout += HandleInactivityTimeout; } protected override void OnStart() { base.OnStart(); InactivityMonitor.Instance.StartMonitoring(); } protected override void OnSleep() { base.OnSleep(); InactivityMonitor.Instance.StopMonitoring(); } protected override void OnResume() { base.OnResume(); InactivityMonitor.Instance.StartMonitoring(); } private void HandleInactivityTimeout() { MainThread.BeginInvokeOnMainThread(async () => { await Current.MainPage.DisplayAlert("提示", "长时间未操作,已自动登出", "确定"); // 执行登出逻辑:清除会话、导航到登录页 Current.MainPage = new LoginPage(); }); } }
优势:无需修改页面代码,覆盖窗口级的触摸、按键操作;后台休眠时自动停止检测,避免误触发。
方案二:自定义页面基类统一处理手势
如果窗口事件覆盖不全(比如自定义控件事件不冒泡),可以让所有页面继承统一基类,在基类中添加全局手势识别器。
实现步骤
- 创建页面基类:
public class BaseContentPage : ContentPage { protected override void OnAppearing() { base.OnAppearing(); // 监听触摸按下事件 var pointerGesture = new PointerGestureRecognizer(); pointerGesture.PointerPressed += (s, e) => InactivityMonitor.Instance.ResetTimer(); GestureRecognizers.Add(pointerGesture); // 补充监听点击事件(针对部分不触发PointerPressed的控件) var tapGesture = new TapGestureRecognizer(); tapGesture.Tapped += (s, e) => InactivityMonitor.Instance.ResetTimer(); GestureRecognizers.Add(tapGesture); } }
- 所有业务页面继承基类:
public class HomePage : BaseContentPage { // 页面业务逻辑 }
优势:确保每个页面的交互都能触发定时器重置,兼容更多控件场景。
方案三:平台特定系统级监听
针对Android、iOS等平台,使用系统级API捕获更全面的用户操作(如物理按键、截图、系统返回等)。
Android平台实现
在Platforms/Android/MainActivity.cs中添加:
public class MainActivity : MauiAppCompatActivity { private Timer _inactivityTimer; private readonly TimeSpan _timeout = TimeSpan.FromMinutes(1); protected override void OnResume() { base.OnResume(); ResetTimer(); Window.Callback = new CustomWindowCallback(Window.Callback, ResetTimer); } protected override void OnPause() { base.OnPause(); _inactivityTimer?.Dispose(); } private void ResetTimer() { _inactivityTimer?.Dispose(); _inactivityTimer = new Timer(_ => { RunOnUiThread(() => { MessagingCenter.Send<object>(this, "InactivityTimeout"); }); }, null, _timeout, Timeout.InfiniteTimeSpan); } private class CustomWindowCallback : WindowCallbackWrapper { private readonly Action _resetTimer; public CustomWindowCallback(IWindowCallback wrapped, Action resetTimer) : base(wrapped) { _resetTimer = resetTimer; } public override bool DispatchTouchEvent(MotionEvent e) { if (e.Action == MotionEventActions.Down) _resetTimer(); return base.DispatchTouchEvent(e); } public override bool DispatchKeyEvent(KeyEvent e) { if (e.Action == KeyEventActions.Down) _resetTimer(); return base.DispatchKeyEvent(e); } } }
iOS平台实现
在Platforms/iOS/AppDelegate.cs中添加:
[Register("AppDelegate")] public class AppDelegate : MauiUIApplicationDelegate { private Timer _inactivityTimer; private readonly TimeSpan _timeout = TimeSpan.FromMinutes(1); public override bool FinishedLaunching(UIApplication app, NSDictionary options) { base.FinishedLaunching(app, options); NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.UserDidTakeScreenshotNotification, _ => ResetTimer()); NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidBecomeActiveNotification, _ => ResetTimer()); NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.WillResignActiveNotification, _ => _inactivityTimer?.Dispose()); return true; } private void ResetTimer() { _inactivityTimer?.Dispose(); _inactivityTimer = new Timer(_ => { InvokeOnMainThread(() => { MessagingCenter.Send<object>(this, "InactivityTimeout"); }); }, null, _timeout, Timeout.InfiniteTimeSpan); } }
统一处理登出逻辑
在App类中订阅消息:
public partial class App : Application { public App() { InitializeComponent(); MessagingCenter.Subscribe<object>(this, "InactivityTimeout", _ => HandleInactivityTimeout()); } private void HandleInactivityTimeout() { // 执行登出逻辑 } }
优势:捕获系统级操作,兼容性最强;适合对无活动检测精度要求高的场景。
内容的提问来源于stack exchange,提问作者Esteban Chornet
相关产品推荐
相关产品推荐

