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.
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();
}
To detect user interaction on Android you can relay on OnUserInteraction().
MainActivity.cs
public override void OnUserInteraction()
{
base.OnUserInteraction();
(App.Current as App).ResetIdleTimer();
}
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);
}
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