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

.NET MAUI全局检测用户无活动实现自动登出方案咨询

.NET MAUI全局无活动状态检测与自动登出方案

以下是几种实用的全局无活动检测实现方案,覆盖不同场景需求:

方案一:全局窗口事件监听 + 定时器服务

通过监听主窗口的触摸、按键事件,结合定时器实现全局无活动检测,无需修改每个页面。

实现步骤

  1. 创建单例无活动监控服务:
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;
        }
    }
}
  1. 在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();
        });
    }
}

优势:无需修改页面代码,覆盖窗口级的触摸、按键操作;后台休眠时自动停止检测,避免误触发。

方案二:自定义页面基类统一处理手势

如果窗口事件覆盖不全(比如自定义控件事件不冒泡),可以让所有页面继承统一基类,在基类中添加全局手势识别器。

实现步骤

  1. 创建页面基类:
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);
    }
}
  1. 所有业务页面继承基类:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 17:37:13