Share via


UWP から WinUI 3 への移行に関するアプリ通知

UWP から WinUI 3 にアプリ通知コードを移行する場合の唯一の違いは、通知のアクティブ化を処理することです。 アプリ通知の送信と管理はまったく同じです。

注意

"トースト通知" という用語は、"アプリ通知" に置き換えられます。 これらの用語はどちらも Windows の同じ機能を指しますが、時間の経過と共にドキュメントで "トースト通知" の使用を段階的に廃止します。

注意

一部の情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft は、ここに記載されている情報について、明示または黙示を問わず、一切保証しません。

アクティブ化の違い

カテゴリ UWP WinUI 3
フォアグラウンド アクティブ化エントリ ポイント OnActivated 内の App.xaml.cs メソッドが呼び出されます OnLaunched 内の App.xaml.cs メソッドが呼び出されます。
バックグラウンド アクティブ化エントリ ポイント バックグラウンド タスクとして個別に処理される フォアグラウンド アクティブ化と同じです。 OnLaunched 内の App.xaml.cs メソッドが呼び出されます。 GetActivatedEventArgs を使用して、アプリを完全に起動するか、単にタスクを処理して終了するかを判断します。
ウィンドウのアクティブ化 フォアグラウンドのアクティブ化が発生すると、ウィンドウが自動的にフォアグラウンドに移動する 必要に応じて、ウィンドウを前面に移動する必要があります

C# アプリの移行

手順 1: NuGet ライブラリをインストールする

WinUI 3 アプリの場合は、 AppNotificationManager クラスを使用して通知のアクティブ化を処理します。 このクラスは、WinUI 3 Visual Studio プロジェクト テンプレートに既定で含まれている Microsoft.WindowsAppSDK Nuget パッケージによって提供されます。

手順 2: マニフェストを更新する

Package.appxmanifest で、次を追加します。

  1. xmlns:com のための宣言
  2. xmlns:desktop のための宣言
  3. IgnorableNamespaces 属性に comdesktop を追加
  4. トースト アクティベーター CLSID (任意の新しい GUID を使用) を宣言するための、windows.toastNotificationActivationdesktop:Extension
  5. MSIX のみ: COM アクティベーターの com:Extension (手順 4 の GUID を使用)。 通知から起動されたことがわかるように、必ず 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. 値 ExtendedActivationKind.AppNotification の返されたオブジェクトの AppInstance.GetActivatedEventArgs を呼び出し、AppActivationArguments.Kind プロパティをチェックします。
  7. アクティブ化の種類が AppNotification でない場合は、 LaunchAndBringToForegroundIfNeeded ヘルパー メソッドを呼び出します。
  8. アクティブ化の種類が AppNotification の場合、 AppActivationArguments.Data プロパティを AppNotificationActivatedEventArgs にキャストし、ヘルパー メソッドに HandleNotification 渡します。
  9. ApplicationManager.NotificationInvoked ハンドラーで、ヘルパー メソッドを呼び出しますHandleNotification
  10. HandleNotificationヘルパー メソッド内で、ウィンドウの表示や UI の更新など、UI 関連のコードを実行する前に、必ず App または Window ディスパッチャーにディスパッチしてください
  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);
    }
}

アプリ通知コンテンツのビルド

Windows アプリ SDKでは、未加工の xml を使用してアプリ通知コンテンツを作成できますが、Windows Community Toolkit によって提供される ToastContentBuilder クラスを置き換える新しい AppNotificationsBuilder API を使用してアプリ通知コンテンツを作成することもできます。 AppNotificationManager.Show を呼び出してアプリ通知を送信します。 Windows Community Toolkit と App SDK API の混在はお勧めしません。

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