Поделиться через


Уведомления приложений из UWP в миграцию WinUI 3

Единственное различие при переносе кода уведомлений приложения из UWP в WinUI 3 заключается в обработке активации уведомлений. Отправка уведомлений приложений и управление ими остается точно такой же.

Примечание.

Термин "всплывающее уведомление" заменяется на "уведомление приложения". Эти термины относятся к одной и той же функции Windows, но с течением времени мы будем поэтапно использовать всплывающее уведомление в документации.

Примечание.

Некоторые сведения относятся к предварительной версии продукта, в которую перед коммерческим выпуском могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Различия в активации

Категория UWP WinUI 3
Точка входа активации переднего плана OnActivatedВызывается метод внутри App.xaml.cs OnLaunched Вызывается метод внутри App.xaml.cs .
Точка входа в фоновую активацию Обработка отдельно в качестве фоновой задачи То же, что и активация переднего плана. OnLaunched Вызывается метод внутри App.xaml.cs . Используйте GetActivatedEventArgs , чтобы определить, должно ли приложение полностью запустить или просто обработать задачу и выйти.
Активация окна Окно автоматически доведено до переднего плана при активации переднего плана При желании необходимо перенести окно на передний план

Миграция для приложений C#

Шаг 1. Установка библиотеки NuGet

Для приложения WinUI 3 вы обрабатываете активацию уведомлений с помощью класса AppNotificationManager . Этот класс предоставляется пакетом Nuget Microsoft.WindowsAppSDK, который включен по умолчанию в шаблоны проектов WinUI 3 Visual Studio.

Шаг 2. Обновление манифеста

В package.appxmanifest добавьте:

  1. Объявление для xmlns:com
  2. Объявление для xmlns:desktop
  3. В атрибуте IgnorableNamespaces com и desktop
  4. desktop:Extension for windows.toastNotificationActivation , чтобы объявить идентификатор CLSID toast (используя новый GUID вашего выбора).
  5. Только MSIX: com:Extension для активатора COM с помощью GUID из шага 4. Не забудьте включить так Arguments="----AppNotificationActivated:" , чтобы вы знали, что ваш запуск был получен из уведомления
<!--Add these namespaces-->
<Package
  ...
  xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
  xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
  IgnorableNamespaces="... com desktop">
  ...
  <Applications>
    <Application>
      ...
      <Extensions>

        <!--Specify which CLSID to activate when app notification clicked-->
        <desktop:Extension Category="windows.toastNotificationActivation">
          <desktop:ToastNotificationActivation ToastActivatorCLSID="replaced-with-your-guid-C173E6ADF0C3" /> 
        </desktop:Extension>

        <!--Register COM CLSID LocalServer32 registry key-->
        <com:Extension Category="windows.comServer">
          <com:ComServer>
            <com:ExeServer Executable="YourProject.exe" Arguments="----AppNotificationActivated:" DisplayName="App notification activator">
              <com:Class Id="replaced-with-your-guid-C173E6ADF0C3" DisplayName="App notification activator"/>
            </com:ExeServer>
          </com:ComServer>
        </com:Extension>

      </Extensions>
    </Application>
  </Applications>
 </Package>

Шаг 3. Обработка активации

В коде запуска приложения (обычно App.xaml.cs), обновите код , выполнив следующие действия:

  1. В OnLaunched получите экземпляр класса AppNotificationManager по умолчанию.
  2. Зарегистрируйте событие AppNotificationManager.NotificationInvoked.
  3. Вызовите Microsoft.Windows.AppNotifications.AppNotificationManager.Register , чтобы зарегистрировать приложение для получения событий уведомлений. Важно, чтобы этот метод вызывался после регистрации обработчика NotificationInvoked .
  4. Рефакторинг кода запуска и активации окна в выделенный LaunchAndBringToForegroundIfNeeded вспомогательный метод, чтобы можно было вызвать его из нескольких мест.
  5. Создайте вспомогательный HandleNotification метод, чтобы его можно было вызывать из нескольких мест.
  6. Вызовите AppInstance.GetActivatedEventArgs и проверьте свойство AppActivationArguments.Kind возвращаемого объекта для значения ExtendedActivationKind.AppNotification.
  7. Если тип активации не является AppNotification , вызовите вспомогательный метод LaunchAndBringToForegroundIfNeed .
  8. Если тип активации AppNotification приводит свойство AppActivationArguments.Data к объекту AppNotificationActivatedEventArgs и передает его в вспомогательный HandleNotification метод.
  9. В обработчике ApplicationManager.NotificationInvoked вызовите вспомогательный HandleNotification метод.
  10. HandleNotification Перед выполнением любого кода, связанного с пользовательским интерфейсом, перед выполнением любого кода, связанного с пользовательским интерфейсом, не забудьте отправить в диспетчер приложений или окно.
  11. Перенос старого кода UWP OnActivated , обрабатывающего активацию уведомлений приложения, в новый HandleNotification вспомогательный метод.

Перенесенные App.xaml.cs


protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    m_window = new MainWindow();

    // To ensure all Notification handling happens in this process instance, register for
    // NotificationInvoked before calling Register(). Without this a new process will
    // be launched to handle the notification.
    AppNotificationManager notificationManager = AppNotificationManager.Default;
    notificationManager.NotificationInvoked += NotificationManager_NotificationInvoked;
    notificationManager.Register();

    var activatedArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
    var activationKind = activatedArgs.Kind;
    if (activationKind != ExtendedActivationKind.AppNotification)
    {
        LaunchAndBringToForegroundIfNeeded();
    } else
    {
        HandleNotification((AppNotificationActivatedEventArgs)activatedArgs.Data);
    }

}

private void LaunchAndBringToForegroundIfNeeded()
{
    if (m_window == null)
    {
        m_window = new MainWindow();
        m_window.Activate();

        // Additionally we show using our helper, since if activated via a app notification, it doesn't
        // activate the window correctly
        WindowHelper.ShowWindow(m_window);
    }
    else
    {
        WindowHelper.ShowWindow(m_window);
    }
}

private void NotificationManager_NotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs args)
{
    HandleNotification(args);
}

private void HandleNotification(AppNotificationActivatedEventArgs args)
{
  // Use the dispatcher from the window if present, otherwise the app dispatcher
  var dispatcherQueue = m_window?.DispatcherQueue ?? DispatcherQueue.GetForCurrentThread();


  dispatcherQueue.TryEnqueue(async delegate
  {

      switch (args.Arguments["action"])
      {
          // Send a background message
          case "sendMessage":
              string message = args.UserInput["textBox"].ToString();
              // TODO: Send it

              // If the UI app isn't open
              if (m_window == null)
              {
                  // Close since we're done
                  Process.GetCurrentProcess().Kill();
              }

              break;

          // View a message
          case "viewMessage":

              // Launch/bring window to foreground
              LaunchAndBringToForegroundIfNeeded();

              // TODO: Open the message
              break;
      }
  });
}

private static class WindowHelper
{
    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetForegroundWindow(IntPtr hWnd);

    public static void ShowWindow(Window window)
    {
        // Bring the window to the foreground... first get the window handle...
        var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);

        // Restore window if minimized... requires DLL import above
        ShowWindow(hwnd, 0x00000009);

        // And call SetForegroundWindow... requires DLL import above
        SetForegroundWindow(hwnd);
    }
}

Создание содержимого уведомления о приложении

С помощью пакета SDK для приложений Для Windows вы по-прежнему можете создавать содержимое уведомлений приложения с помощью нового API AppNotificationsBuilder, который заменяет класс ToastContentBuilder, предоставляемый Набором средств сообщества Windows. Отправьте уведомление о приложении, вызвав AppNotificationManager.Show. Не рекомендуется смешивать api набора средств сообщества Windows и ПАКЕТА SDK для приложений.

using Microsoft.Windows.AppNotifications;
using Microsoft.Windows.AppNotifications.Builder;

...

var builder = new AppNotificationBuilder()
    .AddText("Send a message.")
    .AddTextBox("textBox")
    .AddButton(new AppNotificationButton("Send")
        .AddArgument("action", "sendMessage"));

var notificationManager = AppNotificationManager.Default;
notificationManager.Show(builder.BuildNotification());