Notificaciones de aplicación de la migración de UWP a WinUI 3

La única diferencia al migrar el código de notificación de la aplicación de UWP a WinUI 3 es controlar la activación de notificaciones. El envío y la administración de notificaciones de la aplicación permanecen exactamente iguales.

Nota:

El término "notificación del sistema" se reemplaza por "notificación de aplicación". Estos términos hacen referencia a la misma característica de Windows, pero con el tiempo eliminaremos gradualmente el uso de "notificación del sistema" en la documentación.

Nota

Parte de la información hace referencia al producto de versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.

Diferencias de activación

Category UWP WinUI 3
Punto de entrada de activación en primer plano OnActivated se llama al método dentro App.xaml.cs de . OnLaunched se llama al método dentro App.xaml.cs de .
Punto de entrada de activación en segundo plano Se controla por separado como una tarea en segundo plano Igual que la activación en primer plano. OnLaunched se llama al método dentro App.xaml.cs de . Usa GetActivatedEventArgs para determinar si la aplicación debe iniciarse completamente o simplemente controlar la tarea y salir.
Activación de ventanas La ventana se lleva automáticamente al primer plano cuando se produce la activación en primer plano Si lo desea, debe traer la ventana al primer plano.

Migración para aplicaciones de C#

Paso 1: Instalación de la biblioteca NuGet

En el caso de una aplicación WinUI 3, se controla la activación de las notificaciones mediante la clase AppNotificationManager . Esta clase la proporciona el paquete NuGet Microsoft.WindowsAppSDK, que se incluye de forma predeterminada en las plantillas de proyecto de Visual Studio de WinUI 3.

Paso 2: Actualizar el manifiesto

En package.appxmanifest, agregue:

  1. Declaración para xmlns:com
  2. Declaración para xmlns:desktop
  3. En el atributo IgnoreableNamespaces , com y desktop
  4. desktop:Extension para windows.toastNotificationActivation para declarar el CLSID del activador del sistema (con un nuevo GUID de su elección).
  5. Solo MSIX: com:Extensión para el activador COM mediante el GUID del paso 4. Asegúrese de incluir para Arguments="----AppNotificationActivated:" que sepa que el inicio ha sido desde una notificación.
<!--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>

Paso 3: Controlar la activación

En el código de inicio de la aplicación (normalmente App.xaml.cs), actualice el código siguiendo estos pasos:

  1. En OnLaunched, obtenga la instancia predeterminada de la clase AppNotificationManager .
  2. Regístrese para el evento AppNotificationManager.NotificationInvoked .
  3. Llame a Microsoft.Windows.AppNotifications.AppNotificationManager.Register para registrar la aplicación para recibir eventos de notificación. Es importante que la llamada a este método después de registrar el controlador NotificationInvoked .
  4. Refactorice el código de inicio o activación de la ventana en un método auxiliar dedicado LaunchAndBringToForegroundIfNeeded , por lo que puede llamarlo desde varios lugares.
  5. Cree un HandleNotification método auxiliar para que se pueda llamar desde varios lugares.
  6. Llame a AppInstance.GetActivatedEventArgs y compruebe la propiedad AppActivationArguments.Kind del objeto devuelto para el valor ExtendedActivationKind.AppNotification.
  7. Si el tipo de activación no es AppNotification , llame al método auxiliar LaunchAndBringToForegroundIfNeeded .
  8. Si el tipo de activación es AppNotification , convierta la propiedad AppActivationArguments.Data en una appNotificationActivatedEventArgs y pásela al HandleNotification método auxiliar.
  9. En el controlador ApplicationManager.NotificationInvoked , llame al HandleNotification método auxiliar.
  10. HandleNotification Dentro del método auxiliar, asegúrese de enviar al distribuidor de aplicaciones o ventanas antes de ejecutar cualquier código relacionado con la interfaz de usuario, como mostrar una ventana o actualizar la interfaz de usuario.
  11. Migre el código de UWP OnActivated anterior que controló la activación de notificaciones de la aplicación al nuevo HandleNotification método auxiliar.

App.xaml.cs migrado


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);
    }
}

Creación de contenido de notificación de aplicación

Con SDK de Aplicaciones para Windows, todavía puedes crear contenido de notificación de aplicación con xml sin formato, pero también puedes crear contenido de notificación de aplicación mediante la nueva API AppNotificationsBuilder que reemplaza la clase ToastContentBuilder proporcionada por el Kit de herramientas de la comunidad de Windows. Envíe la notificación de la aplicación llamando a AppNotificationManager.Show. No se recomienda mezclar el Kit de herramientas de la comunidad de Windows y las API del SDK de aplicaciones.

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());