.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获取当前应用的主窗口,然后将其激活并置于前台。具体实现如下:
- 先添加必要的命名空间引用:
using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using WinRT.Interop;
- 修改
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
相关产品推荐
相关产品推荐

