从 C++ UWP 应用发送本地 toast 通知

toast 通知是用户当前未在应用内部时可由应用构造并发送给用户的消息。

Toast 通知的屏幕截图

本快速入门将引导你完成使用丰富内容和交互式操作创建、交付和显示Windows 10或Windows 11 Toast 通知的步骤。 本快速入门使用本地通知,这是要实现的最简单通知。 所有类型的应用(WPF、UWP、WinForms、控制台)都可以发送通知!

重要

如果要编写 C++ 非 UWP 应用,请参阅 C++ WRL 文档。 如果要编写 C# 应用,请参阅 C# 文档

步骤 1:安装 NuGet 包

可以使用 Windows 社区工具包 (WCT) 的生成器语法或使用 XML 创建 toast 通知。 如果希望使用后者,请跳到“步骤 2”,参阅“无生成器语法”代码示例。

在 Visual Studio 解决方案中,右键单击项目,单击“管理 NuGet 包...”,然后搜索并安装 Microsoft.Toolkit.Uwp.NotificationsNuGet 包 7.0 或更高版本。

生成器语法代码示例将使用此包。 使用此包,无需使用 XML 即可创建 toast 通知。

步骤 2:添加命名空间声明

using namespace Microsoft::Toolkit::Uwp::Notifications;

步骤 3:发送 toast

在Windows 10和Windows 11中,你的 Toast 通知内容使用自适应语言进行描述,该语言可以非常灵活地显示通知的外观。 有关详细信息,请参阅 toast 内容文档

我们将从基于文本的简单通知开始。 构造通知内容(使用通知库),然后显示通知! 请注意,命名空间为 Microsoft.Toolkit.Uwp.Notifications

简单文本通知

如果不使用 WCT 通知库生成器语法,则改为构造 XML toast 模板,使用文本和值填充该模板,构造通知,然后显示它。

// Construct the content and show the toast!
(ref new ToastContentBuilder())
    ->AddArgument("action", "viewConversation")
    ->AddArgument("conversationId", 9813)
    ->AddText("Andrew sent you a picture")
    ->AddText("Check this out, The Enchantments in Washington!")
    ->Show();

步骤 4:处理激活

当用户单击通知(或具有前台激活功能的通知上的按钮)时,系统会调用应用的 App.xaml.cpp OnActivated。

App.xaml.cpp

void App::OnActivated(IActivatedEventArgs^ e)
{
    // Handle notification activation
    if (e->Kind == ActivationKind::ToastNotification)
    {
        ToastNotificationActivatedEventArgs^ toastActivationArgs = (ToastNotificationActivatedEventArgs^)e;

        // Obtain the arguments from the notification
        ToastArguments^ args = ToastArguments::Parse(toastActivationArgs->Argument);

        // Obtain any user input (text boxes, menu selections) from the notification
        auto userInput = toastActivationArgs->UserInput;
 
        // TODO: Show the corresponding content
    }
}

重要

必须按 OnLaunched 代码那样初始化框架和激活窗口。 如果用户单击你的 toast ,则不会调用 OnLaunched,即使你的应用已关闭并是首次启动也是如此。 通常建议将 OnLaunchedOnActivated 合并到你自己的 OnLaunchedOrActivated 方法中,因为二者中均需执行相同的初始化。

深度激活

使通知可操作的第一步是向通知添加一些启动参数,以便应用知道在用户单击通知时要启动的内容(在此示例中,我们将包括一些信息,该信息稍后会告知我们应打开一个对话,而我们知道要打开哪个特定的对话)。

// Construct the content and show the toast!
(ref new ToastContentBuilder())

    // Arguments returned when user taps body of notification
    ->AddArgument("action", "viewConversation")
    ->AddArgument("conversationId", 9813)

    ->AddText("Andrew sent you a picture")
    ->Show();

添加图像

可以将丰富的内容添加到通知。 我们将添加内联图像和配置文件(应用徽标替代)图像。

注意

图像可来自于应用包、应用的本地存储或来自 Web。 自 Fall Creators Update 起,正常连接上的 Web 图像的大小限制提升至 3 MB,按流量计费的连接上的限制提升至 1 MB。 在尚未运行 Fall Creators Update 的设备上,Web 图像的大小不得超过 200 KB。

带图像的 Toast
// Construct the content and show the toast!
(ref new ToastContentBuilder())
    ...

    // Inline image
    ->AddInlineImage(ref new Uri("https://picsum.photos/360/202?image=883"))

    // Profile (app logo override) image
    ->AddAppLogoOverride(ref new Uri("ms-appdata:///local/Andrew.jpg"), ToastGenericAppLogoCrop::Circle)
    
    ->Show();

添加按钮和输入

可以添加按钮和输入,使通知具有交互性。 按钮可以启动前台应用、协议或后台任务。 我们将添加一个回复文本框、一个“赞”按钮和一个打开图像的“查看”按钮。

包含输入和按钮的 Toast 通知的屏幕截图
// Construct the content
(ref new ToastContentBuilder())
    ->AddArgument("conversationId", 9813)
    ...

    // Text box for replying
    ->AddInputTextBox("tbReply", "Type a response")

    // Buttons
    ->AddButton((ref new ToastButton())
        ->SetContent("Reply")
        ->AddArgument("action", "reply")
        ->SetBackgroundActivation())

    ->AddButton((ref new ToastButton())
        ->SetContent("Like")
        ->AddArgument("action", "like")
        ->SetBackgroundActivation())

    ->AddButton((ref new ToastButton())
        ->SetContent("View")
        ->AddArgument("action", "view"))
    
    ->Show();

前台按钮激活处理方式与主 toast 正文相同(将调用 App.xaml.cpp OnActivated)。

处理后台激活

当你对你的 toast(或 toast 内的按钮)指定后台激活时,将执行后台任务而不是激活前台应用。

有关后台任务的详细信息,请参阅使用后台任务支持应用

如果面向内部版本 14393 或更高版本,则可以使用进程内后台任务,这极大地简化了操作。 请注意,无法在较旧版本的 Windows 上运行进程内后台任务。 在此代码示例中,将使用进程内后台任务。

const string taskName = "ToastBackgroundTask";

// If background task is already registered, do nothing
if (BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals(taskName)))
    return;

// Otherwise request access
BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync();

// Create the background task
BackgroundTaskBuilder builder = new BackgroundTaskBuilder()
{
    Name = taskName
};

// Assign the toast action trigger
builder.SetTrigger(new ToastNotificationActionTrigger());

// And register the task
BackgroundTaskRegistration registration = builder.Register();

然后,在 App.xaml.cs 中重写 OnBackgroundActivated 方法。 接下来可以检索预定义的参数和用户输入,类似于前台激活。

App.xaml.cs

protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
    var deferral = args.TaskInstance.GetDeferral();
 
    switch (args.TaskInstance.Task.Name)
    {
        case "ToastBackgroundTask":
            var details = args.TaskInstance.TriggerDetails as ToastNotificationActionTriggerDetail;
            if (details != null)
            {
                string arguments = details.Argument;
                var userInput = details.UserInput;

                // Perform tasks
            }
            break;
    }
 
    deferral.Complete();
}

设置过期时间

在 Windows 10 和 11 中,所有 toast 通知在被用户消除或忽略后都会进入操作中心,以便在弹出窗口消失后仍可供用户查看。

但是,如果你的通知中的消息仅在一段时间内相关,则应对 toast 通知设置过期时间,让用户不至于看到来自应用的过时信息。 例如,如果升级的有效时间仅为 12 个小时,则将过期时间设置为 12 个小时。 下面的代码中将过期时间设置为 2 天。

注意

本地 toast 通知的默认和最长过期时间为 3 天。

// Create toast content and show the toast!
(ref new ToastContentBuilder())
    ->AddText("Expires in 2 days...")
    ->Show(toast =>
    {
        toast->ExpirationTime = DateTime::Now->AddDays(2);
    });

为 toast 提供主键

如要以编程方式删除或替换发送的通知,需使用 Tag 属性(还可选择使用 Group 属性)来为通知提供主键。 然后,你可以在以后使用此主键来删除或替换该通知。

要查看有关替换/删除已发送的 toast 通知的更多详细信息,请参阅快速入门:在操作中心 (XAML) 中管理 toast 通知

Tag 和 Group 组合充当复合主键。 Group 是两者中较为通用的标识符,你可以用它来分配如“wallPosts”、“messages”、“friendRequests”等组。而 Tag 应该唯一标识组中的通知本身。 使用通用组时,可以使用 RemoveGroup API 删除该组中的所有通知。

// Create toast content and show the toast!
(ref new ToastContentBuilder())
    ->AddText("New post on your wall!")
    ->Show(toast =>
    {
        toast.Tag = "18365";
        toast.Group = "wallPosts";
    });

清除你的通知

应用负责删除和清除它们自己的通知。 当你的应用启动时,我们不会自动清除你的通知。

仅当用户显式单击通知时,Windows 才会自动删除该通知。

下面是消息传递应用应执行的操作的示例...

  1. 用户收到关于对话中新消息的多个 toast
  2. 用户点击其中一个 toast 以打开该对话
  3. 应用打开该对话,然后清除该对话的所有 toast(方法是对该对话的应用提供的组使用 RemoveGroup
  4. 用户的操作中心现在能正确反映通知状态,因为操作中心未留有该对话的过期通知。

若要了解有关清除所有通知或删除特定通知的信息,请参阅快速入门:在操作中心 (XAML) 中管理 toast 通知

ToastNotificationManagerCompat::History->Clear();

资源