Navigate back to home page if there is no user interaction for x duration (user is idle)

Viewed 31

I am working on a self management app and I need to implement an inactivity timer or something similar to know if the user is idling (without interacting with a view for x duration) so when this happens it returns to the home page.

Is this possible? Already check app lifecycle docs and doesn't found any relevant info.

I was thinking of making a timer per view that when the time comes x redirects but it seems less than optimal. Is there a way to integrate it directly into the application or do I really have to set a timer per view?

Sorry if my question is not clear. Please ask and I can update if it doesn't make sense.

1 Answers

Cross platform code (common)

using Timer = System.Timers.Timer;

App.xaml.cs

Timer IdleTimer = new Timer( 60 * 1000);  //each 1 minute

public App()
{
    InitializeComponent();
    MainPage = new AppShell();

    IdleTimer.Elapsed += Idleimer_Elapsed;
    IdleTimer.Start();
}

async void Idleimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    Console.WriteLine(":::Elapsed");
    if (MainThread.IsMainThread)
        await Shell.Current.Navigation.PopToRootAsync();
    else
        MainThread.BeginInvokeOnMainThread(async () => await Shell.Current.Navigation.PopToRootAsync());}

public void ResetIdleTimer()
{
    IdleTimer.Stop();
    IdleTimer.Start();
}

Android

To detect user interaction on Android you can relay on OnUserInteraction().

Android docs

MainActivity.cs

public override void OnUserInteraction()
{
    base.OnUserInteraction();
    (App.Current as App).ResetIdleTimer();
}

iOS

on ios you can listen to touche events at application level source.

Program.cs

static void Main(string[] args)
{
   UIApplication.Main(args, typeof(CustomApplication), typeof(AppDelegate));
}

CustomApplication.cs

public class CustomApplication : UIApplication
{
    public CustomApplication() : base()
    {
    }

    public CustomApplication(IntPtr handle) : base(handle)
    {
    }

    public CustomApplication(Foundation.NSObjectFlag t) : base(t)
    {
    }
    public override void SendEvent(UIEvent uievent)
    {
        if (uievent.Type == UIEventType.Touches)
        {
            if (uievent.AllTouches.Cast<UITouch>().Any(t => t.Phase == UITouchPhase.Began))
            {
                (App.Current as App).ResetIdleTimer();
            }
        }

        base.SendEvent(uievent);
    }

Windows

For windows you can listen to some native window events like WM_NCACTIVATE: 0x0086 or WM_SETCURSOR 0x0020 or WM_MOUSEACTIVATE.

I am sure there is a more efficient way which listens to mouse cursor moving event, for some reasons is not reported at this level (for example WM_MOUSEMOVE).

MauiProgram.cs

            .ConfigureLifecycleEvents(events =>
            {
#if WINDOWS
                events
                    .AddWindows(windows => windows
                        .OnPlatformMessage((window, args) =>
                        {
                            if (args.MessageId == Convert.ToUInt32("0x0086", 16) ||
                                args.MessageId == Convert.ToUInt32("0x0020", 16) ||
                                args.MessageId == Convert.ToUInt32("0x0021", 16) )
                            {
                                (App.Current as App).ResetIdleTimer();
                            }
                        }));
#endif
Related