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

.NET MAUI Windows平台如何激活后台运行的应用窗口?

问题:.NET MAUI Windows平台点击推送通知无法唤醒后台应用

我有一个运行在iOS、Android和Windows平台的.NET MAUI应用,支持接收推送通知。在Windows平台上,点击通知后无反应,我希望点击通知时唤醒已打开的应用实例,实现类似window.Focus()的效果。

以下是Xamarin Forms中的实现方式:

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active.
    if (rootFrame == null)
    {
        // Create a Frame to act as the navigation context and navigate to the first page.
        rootFrame = new Frame();

        rootFrame.NavigationFailed += OnNavigationFailed;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            //TODO: Load state from previously suspended application.
        }

        // Place the frame in the current Window.
        Window.Current.Content = rootFrame;
    }

    if (rootFrame.Content == null)
    {
        // When the navigation stack isn't restored navigate to the first page,
        // configuring the new page by passing required information as a navigation
        // parameter.
        rootFrame.Navigate(typeof(MainPage), e.Arguments);
    }

    // Ensure the current window is active.
    Window.Current.Activate();
}

我找到的示例中App类均继承自Application,但MAUI中App继承的是MauiWinUIApplication,我的App.xamls.cs代码如下:

public partial class App : MauiWinUIApplication
{
    /// <summary>
    /// Initializes the singleton application object.  This is the first line of authored code
    /// executed, and as such is the logical equivalent of main() or WinMain().
    /// </summary>
    /// 
    private readonly SingleInstanceDesktopApp _singleInstanceApp;
    LaunchActivatedEventArgs incomeArgs;

    public App()
    {
        this.InitializeComponent();

        _singleInstanceApp = new SingleInstanceDesktopApp("GIKI");
        _singleInstanceApp.Launched += OnSingleInstanceLaunched;
    }

    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

    protected override async void OnLaunched(LaunchActivatedEventArgs args)
    {
        incomeArgs = args;
        _singleInstanceApp.Launch(args.Arguments);
    }

    private void OnSingleInstanceLaunched(object? sender, SingleInstanceLaunchEventArgs e)
    {
        try
        {
            if (e.IsFirstLaunch)
            {
                base.OnLaunched(incomeArgs);
            }
            else
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex}");
        }
    }

    void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
    {
        throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
    }
    private void OnSuspending(object sender, SuspendingEventArgs e)
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        //TODO: Save application state and stop any background activity
        deferral.Complete();
    }
}

目前OnSingleInstanceLaunched方法可正常工作,请问在else分支中该如何实现将后台窗口显示出来?


解决方案

在OnSingleInstanceLaunched的else分支中,你可以通过WinUI的API获取当前应用的主窗口,然后将其激活并置于前台。具体实现如下:

  1. 先添加必要的命名空间引用:
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using WinRT.Interop;
  1. 修改OnSingleInstanceLaunched方法的else分支,并添加辅助方法:
private void OnSingleInstanceLaunched(object? sender, SingleInstanceLaunchEventArgs e)
{
    try
    {
        if (e.IsFirstLaunch)
        {
            base.OnLaunched(incomeArgs);
        }
        else
        {
            // 获取当前应用的主窗口
            var mainWindow = Application.Current.Windows.OfType<Window>().FirstOrDefault();
            
            if (mainWindow != null)
            {
                // 激活窗口使其获得焦点
                mainWindow.Activate();
                
                // 处理窗口最小化的情况,恢复正常显示状态
                var appWindow = GetAppWindowForWindow(mainWindow);
                if (appWindow.Presenter is OverlappedPresenter overlappedPresenter)
                {
                    if (overlappedPresenter.State == OverlappedPresenterState.Minimized)
                    {
                        overlappedPresenter.Restore();
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex}");
    }
}

// 辅助方法:获取Window对应的AppWindow实例
private AppWindow GetAppWindowForWindow(Window window)
{
    var hwnd = WindowNative.GetWindowHandle(window);
    return AppWindow.GetFromWindowId(Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hwnd));
}

代码说明:

  • 通过Application.Current.Windows.OfType<Window>().FirstOrDefault()定位到应用的主窗口实例。
  • 调用mainWindow.Activate()直接激活窗口,让应用获得前台焦点。
  • 针对窗口最小化的场景,通过AppWindow获取窗口的展示器,判断状态后调用Restore()恢复窗口的正常大小。
  • GetAppWindowForWindow是WinUI中获取窗口底层操作实例的标准方式,用于实现更精细的窗口状态控制。

修改完成后,点击推送通知触发应用二次启动时,后台的应用窗口会被唤醒并显示在前台,达到你需要的类似window.Focus()的效果。

内容的提问来源于stack exchange,提问作者Higor Pereira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:10:46