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 특성에서 4단계의 GUID를 사용한 COM 활성자에 대한 com, desktop
  4. 선택한 신규 GUID를 사용한 알림 활성자 CLSID를 선언하는 windows.toastNotificationActivation에 대한 desktop:Extension
  5. MSIX만 해당: 4단계에서 GUID를 사용하는 COM 활성자의 com:Extension 알림에서 실행을 알 수 있도록 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를 호출하고 ExtendedActivationKind.AppNotification 값에 대해 반환된 개체의 AppActivationArguments.Kind 속성을 검사.
  7. 활성화 종류가 AppNotification이 아닌 경우 LaunchAndBringToForegroundIfNeeded 도우미 메서드를 호출 합니다.
  8. 활성화 종류가 AppNotification이면AppActivationArguments.Data 속성을 AppNotificationActivatedEventArgs로 캐스팅하고 HandleNotification 도우미 메서드에 전달합니다.
  9. ApplicationManager.NotificationInvoked 처리기에서 도우미 메서드를 HandleNotification 호출합니다.
  10. HandleNotification 도우미 메서드 내에서 창을 표시하거나 UI 업데이트와 같은 UI 관련 코드를 실행하기 전에 앱 또는 창 디스패처로 디스패치해야 합니다.
  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 App SDK를 사용하면 raw xml을 사용하여 앱 알림 콘텐츠를 만들 수 있지만 Windows Community Toolkit에서 제공하는 ToastContentBuilder 클래스를 대체하는 새로운 AppNotificationBuilder API를 사용하여 앱 알림 콘텐츠를 만들 수도 있습니다. AppNotificationManager.Show를 호출 하여 앱 알림을 보냅니다. Windows 커뮤니티 도구 키트와 앱 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());