Migrazione delle notifiche delle app dalla piattaforma UWP a WinUI 3

L'unica differenza durante la migrazione del codice di notifica dell'app dalla piattaforma UWP a WinUI 3 consiste nella gestione dell'attivazione delle notifiche. L'invio e la gestione delle notifiche delle app rimangono esattamente uguali.

Nota

Il termine "notifica di tipo avviso popup" viene sostituito con "notifica dell'app". Questi termini si riferiscono entrambi alla stessa funzionalità di Windows, ma nel corso del tempo l'uso della "notifica di tipo avviso popup" verrà eliminato gradualmente nella documentazione.

Nota

Alcune informazioni sono relative a un prodotto non definitivo, che potrebbe subire modifiche sostanziali prima del rilascio sul mercato. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Differenze di attivazione

Categoria UWP WinUI 3
Punto di ingresso di attivazione in primo piano OnActivated il metodo in App.xaml.cs viene chiamato OnLaunched il metodo in App.xaml.cs viene chiamato.
Punto di ingresso di attivazione in background Gestito separatamente come attività in background Uguale all'attivazione in primo piano. OnLaunched il metodo in App.xaml.cs viene chiamato. Usare GetActivatedEventArgs per determinare se l'app deve essere avviata completamente o semplicemente gestire l'attività e chiudersi.
Attivazione di finestre Quando si verifica l'attivazione in primo piano ,la finestra viene automaticamente portata in primo piano Se lo si desidera, è necessario portare la finestra in primo piano

Migrazione per le app C#

Passaggio 1: installare la libreria NuGet

Per un'app WinUI 3, l'attivazione per le notifiche si gestisce usando la classe AppNotificationManager. Questa classe viene fornita dal pacchetto Nuget Microsoft.WindowsAppSDK, incluso per impostazione predefinita nei modelli di progetto di Visual Studio WinUI 3.

Passaggio 2: aggiornare il manifesto

Nel Package.appxmanifest, aggiungere:

  1. Dichiarazione per xmlns:com
  2. Dichiarazione per xmlns:desktop
  3. Nell'attributo IgnorableNamespaces, com e desktop
  4. desktop:Extension in modo che windows.toastNotificationActivation dichiari il CLSID dell'attivatore di tipo avviso popup (usando un nuovo GUID di propria scelta).
  5. Solo MSIX: com:Extension per l'attivatore COM che utilizza il GUID del passaggio 4. Assicurarsi di includere Arguments="----AppNotificationActivated:" in modo da sapere che il lancio è stato generato da una notifica
<!--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>

Passaggio 3: gestire l'attivazione

Nel codice di avvio dell'app (in genere App.xaml.cs), aggiornare il codice seguendo questa procedura:

  1. In OnLaunched, ottenere l'istanza predefinita della classe AppNotificationManager.
  2. Eseguire la registrazione per l'evento AppNotificationManager.NotificationInvoked.
  3. Chiamare Microsoft.Windows.AppNotifications.AppNotificationManager.Register per registrare l'app in modo che riceva gli eventi di notifica. È importante chiamare questo metodo dopo aver registrato il gestore NotificationInvoked.
  4. Effettuare il refactoring del codice di avvio/attivazione della finestra in un metodo helper dedicato LaunchAndBringToForegroundIfNeeded, in modo da poterlo chiamare da più posizioni.
  5. Creare un metodo helper HandleNotification in modo che possa essere chiamato da più posizioni.
  6. Chiamare AppInstance.GetActivatedEventArgs e controllare la proprietà AppActivationArguments.Kind dell'oggetto restituito per il valore ExtendedActivationKind.AppNotification.
  7. Se il tipo di attivazione non è AppNotification, chiamare il metoto helper LaunchAndBringToForegroundIfNeeded.
  8. Se il tipo di attivazione è AppNotification, eseguire il cast della proprietà AppActivationArguments.Data a un oggetto AppNotificationActivatedEventArgs e passarlo al metodo helper HandleNotification.
  9. Nel gestore ApplicationManager.NotificationInvoked, chiamare il metodo helper HandleNotification.
  10. Nel metodo helper HandleNotification, assicurarsi di inviare al dispatcher App o Window prima di eseguire codici relativi all'interfaccia utente, come la visualizzazione di una finestra o l'aggiornamento di un'interfaccia utente.
  11. Eseguire la migrazione del codice UWP precedente OnActivated che ha gestito l'attivazione delle notifiche dell'app al nuovo metodo helper HandleNotification.

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

Compilazione del contenuto delle notifiche dell'app

Con Windows App SDK, è possibile comunque creare contenuto di notifica dell'app utilizzando xml non elaborato, ma anche utilizzando la nuova API AppNotificationsBuilder, che sostituisce la classe ToastContentBuilder fornita da Windows Community Toolkit. Inviare la notifica dell'app chiamando AppNotificationManager.Show. Non è consigliabile combinare le API di Windows Community Toolkit e le API APP 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());