Search code examples
maui-blazor

Blazor for MAUI - How to know within Blazor UI when the page is unloading or app is being paused or resumed


Good day,

I have a project that works with a physical scanner module on an android device. When a Blazor page loads it calls to the hardware scanner module in order to initialize the hardware.

What I am having an issue with is how to tell the hardware module to shut down without having a button on the UI to do so.

What I need to do is call the shutdown process when either the razor page is unloaded or when the app is paused.

If however the the app was paused, on resuming the app I would need to start up that hardware scanner module again.

I have tried to achieve this via the 'OnInitialized override, however this only runs when the page is first initialized and not when the app is resumed.

I have also looked at trying to gain access to the Android OnResume within the MainActivity however I cannot work out how to get these systems talking to each other properly.

I am busy looking at some form of dependency injection to try link them up, but was hoping that someone may know what I am struggling to understand about the communication between the Native MAUI implementation and the Blazor front-end.

Thanks


Solution

  • You will indeed need dependency injection to pass down the event of the window to the blazor component. Here is an exemple :

    Define a class that will be used to pass the window event :

    public class AppLifecycleService
    {
        public event Action Paused;
        public void OnPaused(object? pSender, EventArgs pArgs)
        {
            Paused?.Invoke();
        }
    }
    

    You want only one instance of this class since otherwise you wont be able to get the event. That what dependency injection is for (and more generally the singleton pattern) so you have to register this class to the MAUI app :

    Inside ./MauiProgram.cs :

        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            
    ...
    
            builder.Services.AddSingleton<AppLifecycleService>();
            return builder.Build();
        }
    

    Then you have to get the event from the window, inside ./App.xaml.cs :

    public partial class App : Application
    {
        private AppLifecycleService _AppLifecycle;
    
        public App(AppLifecycleService pAppLifecycle)
        {
            _AppLifecycle = pAppLifecycle;
    
            InitializeComponent();
            MainPage = new MainPage();
        }
    
        protected override Window CreateWindow(IActivationState? activationState)
        {
            Window window = base.CreateWindow(activationState);
            window.Deactivated += _AppLifecycle.OnPaused;
            return window;
        }
    }
    

    And then in any Blazor element you can have :

    @inject AppLifecycleService AppLifecycle
    
    @code {
        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                AppLifecycle.Paused += HandlePaused;
            }
        }
    
        private void HandlePaused()
        {
            // Do something
        }
    }