從 UWP 應用程式傳送本機快顯通知Send a local toast notification from UWP apps

快顯通知是一則訊息,App 可以建構此訊息,並於使用者目前未在 App 內時,傳遞給使用者。A toast notification is a message that an app can construct and deliver to the user while they are not currently inside your app. 這項快速入門會逐步引導您使用新的調適型範本和互動式動作,完成建立、傳遞和顯示 Windows 10 快顯通知的步驟。This Quickstart walks you through the steps to create, deliver, and display a Windows 10 toast notification with the new adaptive templates and interactive actions. 這些動作透過本機通知進行示範,本機通知是我們要實作的最簡單通知。These actions are demonstrated through a local notification, which is the simplest notification to implement.

重要

傳統型應用程式 (包括封裝 MSIX 應用程式、使用 稀疏套件 來取得套件身分識別的應用程式,以及傳統非封裝的桌面應用程式) 有不同的步驟來傳送通知和處理啟用。Desktop applications (including packaged MSIX apps, apps that use sparse packages to obtain package identity, and classic non-packaged Desktop apps) have different steps for sending notifications and handling activation. 請參閱 傳統型應用程式文件以了解如何實作快顯通知。Please see the Desktop apps documentation to learn how to implement toasts.

重要 APIToastNotification 類別ToastNotificationActivatedEventArgs 類別Important APIs: ToastNotification Class, ToastNotificationActivatedEventArgs Class

步驟1:安裝 NuGet 套件Step 1: Install NuGet package

安裝 node.js. [通知] NuGet 套件Install the Microsoft.Toolkit.Uwp.Notifications NuGet package. 我們的程式碼範例會使用此套件。Our code sample will use this package. 在本文結尾,我們將提供不使用任何 NuGet 套件的「一般」程式碼片段。At the end of the article we'll provide the "plain" code snippets that don't use any NuGet packages. 此套件可讓您在不使用 XML 的情況下建立快顯通知。This package allows you to create toast notifications without using XML.

步驟2:加入命名空間宣告Step 2: Add namespace declarations

Windows.UI.Notifications 包含快顯通知 Api。Windows.UI.Notifications includes the toast APIs.

using Windows.UI.Notifications;
using Microsoft.Toolkit.Uwp.Notifications; // Notifications library

步驟3:傳送快顯通知Step 3: Send a toast

在 Windows 10 中,您的快顯通知內容是使用賦予通知外觀極大彈性的調適性語言進行描述。In Windows 10, your toast notification content is described using an adaptive language that allows great flexibility with how your notification looks. 如需詳細資訊,請參閱快顯通知內容文件See the toast content documentation for more information.

我們將從以文字為基礎的簡單通知開始。We'll start with a simple text-based notification. 使用通知程式庫) 來建立通知內容 (,並顯示通知!Construct the notification content (using the Notifications library), and show the notification!

Simple text notification
// Construct the content
var content = new ToastContentBuilder()
    .AddToastActivationInfo("picOfHappyCanyon", ToastActivationType.Foreground)
    .AddText("Andrew sent you a picture")
    .AddText("Check this out, Happy Canyon in Utah!")
    .GetToastContent();

// Create the notification
var notif = new ToastNotification(content.GetXml());

// And show it!
ToastNotificationManager.CreateToastNotifier().Show(notif);

步驟4:處理啟用Step 4: Handling activation

當使用者按一下您的通知 (或具有前景啟用) 通知的按鈕時,將會叫用應用程式的 App.xaml.cs OnActivatedWhen the user clicks your notification (or a button on the notification with foreground activation), your app's App.xaml.cs OnActivated will be invoked.

App.xaml.csApp.xaml.cs

protected override void OnActivated(IActivatedEventArgs e)
{
    // Handle notification activation
    if (e is ToastNotificationActivatedEventArgs toastActivationArgs)
    {
        // Obtain the arguments from the notification
        string args = toastActivationArgs.Argument;

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

重要

就像您的 OnLaunched 程式碼一樣,您必須初始化畫面並啟用視窗。You must initialize your frame and activate your window just like your OnLaunched code. 如果使用者按一下您的快顯通知,並不會呼叫 OnLaunched,即使您的 App 已關閉,然後正在首次啟動,也不會。OnLaunched is NOT called if the user clicks on your toast, even if your app was closed and is launching for the first time. 我們經常建議將 OnLaunchedOnActivated 結合成 OnLaunchedOrActivated 方法,因為兩者都需要進行相同的初始設定。We often recommend combining OnLaunched and OnActivated into your own OnLaunchedOrActivated method since the same initialization needs to occur in both.

深入啟用Activation in depth

讓您的通知可採取動作的第一個步驟,就是將一些啟動引數新增至您的通知,讓您的應用程式可以知道當使用者按一下通知時要啟動的內容 (在此案例中,我們會包含一些資訊,稍後會告訴我們,我們應該開啟交談,而我們知道要開啟哪個特定交談) 。The first step in making your notifications actionable is to add some launch args to your notification, so that your app can know what to launch when the user clicks the notification (in this case, we're including some information that later tells us we should open a conversation, and we know which specific conversation to open).

建議您安裝 QueryString.NET NuGet 套件,以協助針對您的通知引數來建立和剖析查詢字串,如下所示。We recommend installing the QueryString.NET NuGet package to help construct and parse query strings for your notification arguments, as seen below.

using Microsoft.QueryStringDotNET; // QueryString.NET

int conversationId = 384928;

// Construct the content
var content = new ToastContentBuilder()

    // Arguments returned when user taps body of notification
    .AddToastActivationInfo(new QueryString() // Using QueryString.NET
    {
        { "action", "viewConversation" },
        { "conversationId", conversationId.ToString() }
    }.ToString(), ToastActivationType.Foreground)

    .AddText("Andrew sent you a picture")
    ...

以下是更複雜的處理啟用範例 .。。Here's a more complex example of handling activation...

App.xaml.csApp.xaml.cs

protected override void OnActivated(IActivatedEventArgs e)
{
    // Get the root frame
    Frame rootFrame = Window.Current.Content as Frame;
 
    // TODO: Initialize root frame just like in OnLaunched
 
    // Handle toast activation
    if (e is ToastNotificationActivatedEventArgs toastActivationArgs)
    {            
        // Parse the query string (using QueryString.NET)
        QueryString args = QueryString.Parse(toastActivationArgs.Argument);
 
        // See what action is being requested 
        switch (args["action"])
        {
            // Open the image
            case "viewImage":
 
                // The URL retrieved from the toast args
                string imageUrl = args["imageUrl"];
 
                // If we're already viewing that image, do nothing
                if (rootFrame.Content is ImagePage && (rootFrame.Content as ImagePage).ImageUrl.Equals(imageUrl))
                    break;
 
                // Otherwise navigate to view it
                rootFrame.Navigate(typeof(ImagePage), imageUrl);
                break;
                             
 
            // Open the conversation
            case "viewConversation":
 
                // The conversation ID retrieved from the toast args
                int conversationId = int.Parse(args["conversationId"]);
 
                // If we're already viewing that conversation, do nothing
                if (rootFrame.Content is ConversationPage && (rootFrame.Content as ConversationPage).ConversationId == conversationId)
                    break;
 
                // Otherwise navigate to view it
                rootFrame.Navigate(typeof(ConversationPage), conversationId);
                break;
        }
 
        // If we're loading the app for the first time, place the main page on
        // the back stack so that user can go back after they've been
        // navigated to the specific page
        if (rootFrame.BackStack.Count == 0)
            rootFrame.BackStack.Add(new PageStackEntry(typeof(MainPage), null, null));
    }
 
    // TODO: Handle other types of activation
 
    // Ensure the current window is active
    Window.Current.Activate();
}

新增影像Adding images

您可以在通知中加入豐富的內容。You can add rich content to notifications. 我們會將內嵌影像和設定檔新增 (應用程式標誌覆寫) 映射。We'll add an inline image and a profile (app logo override) image.

注意

您可以使用 App 套件、App 本機存放區或網頁中的影像。Images can be used from the app's package, the app's local storage, or from the web. 從 Fall Creators Update 開始,一般連線的網頁影像可以高達 3 MB,而計量付費連線可以高達 1 MB。As of the Fall Creators Update, web images can be up to 3 MB on normal connections and 1 MB on metered connections. 在尚未執行 Fall Creators Update 的裝置上,網頁影像不得超過 200 KB。On devices not yet running the Fall Creators Update, web images must be no larger than 200 KB.

重要

只有在其資訊清單中具有網際網路功能的 UWP/MSIX/sparse 應用程式中,才支援 Http 映射。Http images are only supported in UWP/MSIX/sparse apps that have the internet capability in their manifest. 桌面非 MSIX/稀疏應用程式不支援 HTTP 映射;您必須將映射下載至本機應用程式資料,並在本機進行參考。Desktop non-MSIX/sparse apps do not support http images; you must download the image to your local app data and reference it locally.

Toast with images
// Construct the content
var content = new ToastContentBuilder()
    ...

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

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

新增按鈕和輸入Adding buttons and inputs

您可以新增按鈕和輸入,讓您的通知成為互動。You can add buttons and inputs to make your notifications interactive. 按鈕可以啟動您的前景應用程式、通訊協定或背景工作。Buttons can launch your foreground app, a protocol, or your background task. 我們會新增回復文字方塊、[贊] 按鈕,以及開啟影像的 [View] 按鈕。We'll add a reply text box, a "Like" button, and a "View" button that opens the image.

Toast with images and buttons
int conversationId = 384928;

// Construct the content
var content = new ToastContentBuilder()
    ...

    // Text box for replying
    .AddInputTextBox("tbReply", placeHolderContent: "Type a response")

    // Reference the text box's ID in order to place this button next to the text box
    .AddButton("tbReply", "Reply", ToastActivationType.Background, new QueryString()
    {
        { "action", "reply" },
        { "conversationId", conversationId.ToString() }
    }.ToString(), imageUri: new Uri("Assets/Reply.png", UriKind.Relative))

    .AddButton("Like", ToastActivationType.Background, new QueryString()
    {
        { "action", "like" },
        { "conversationId", conversationId.ToString() }
    }.ToString())

    .AddButton("View", ToastActivationType.Foreground, new QueryString()
    {
        { "action", "viewImage" },
        { "imageUrl", image.ToString() }
    }.ToString())
    
    .GetToastContent();
    
...

前景按鈕的啟動方式與主要的快顯通知主體相同, (您的 App.xaml.cs OnActivated 將被呼叫) 。The activation of foreground buttons are handled in the same way as the main toast body (your App.xaml.cs OnActivated will be called).

處理背景啟用Handling background activation

當您在快顯通知 (或快顯通知內的按鈕) 上指定背景啟用時,將會執行背景工作,而不是啟用前景 App。When you specify background activation on your toast (or on a button inside the toast), your background task will be executed instead of activating your foreground app.

如需背景工作的詳細資訊,請參閱使用背景工作支援 AppFor more information on background tasks, please see Support your app with background tasks.

如果您的目標組建為 14393 或更高版本,則可以同處理序背景工作,這將情況大幅簡化了。If you are targeting build 14393 or higher, you can use in-process background tasks, which greatly simplify things. 請注意,同處理序背景工作無法在舊版 Windows 上執行。Note that in-process background tasks will fail to run on older versions of Windows. 我們會在此程式碼範例中使用同處理序背景工作。We'll use an in-process background task in this code sample.

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 方法。Then in your App.xaml.cs, override the OnBackgroundActivated method. 然後,您可以取得預先定義的引數和使用者輸入,類似于前景啟用。You can then retrieve the pre-defined arguments and user input, similar to the foreground activation.

App.xaml.csApp.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();
}

設定到期時間Set an expiration time

在 Windows 10 中,所有快顯通知都會在使用者關閉或忽略之後進入控制中心,因此使用者可以在快顯視窗消失後查看您的通知。In Windows 10, all toast notifications go in Action Center after they are dismissed or ignored by the user, so users can look at your notification after the popup is gone.

不過,如果通知中的訊息僅與一段時間有關,您應該在快顯通知上設定到期時間,這樣才不會讓使用者在您的 App 中看到過時的資訊。However, if the message in your notification is only relevant for a period of time, you should set an expiration time on the toast notification so the users do not see stale information from your app. 例如,如果促銷期限為 12 小時,可將到期時間設為 12 個小時。For example, if a promotion is only valid for 12 hours, set the expiration time to 12 hours. 在下面程式碼中,我們將到期時間設定為 2 天。In the code below, we set the expiration time to be 2 days.

注意

本機快顯通知的預設及最長到期時間為 3 天。The default and maximum expiration time for local toast notifications is 3 days.

// Create toast content
var content = new ToastContentBuilder()
    .AddText("Expires in 2 days...")
    .GetToastContent();

// Set expiration time
var notif = new ToastNotification(content.GetXml())
{
    ExpirationTime = DateTime.Now.AddDays(2)
};

// And show it!
ToastNotificationManager.CreateToastNotifier().Show(notif);

提供快顯通知主索引鍵Provide a primary key for your toast

如果想以程式設計方式移除或取代您傳送的通知,您必須使用 Tag 屬性 (並選擇性使用 Group 屬性) 提供通知的主索引鍵。If you want to programmatically remove or replace the notification you send, you need to use the Tag property (and optionally the Group property) to provide a primary key for your notification. 那麼,日後就可以使用這個主索引鍵來移除或取代通知。Then, you can use this primary key in the future to remove or replace the notification.

若要查看更多有關取代/移除已傳送快顯通知的詳細資料,請參閱快速入門: 管理控制中心的快顯通知 (XAML)To see more details on replacing/removing already delivered toast notifications, please see Quickstart: Managing toast notifications in action center (XAML).

Tag 與 Group 結合可以做為主複合索引鍵。Tag and Group combined act as a composite primary key. Group 是較通用的識別碼,其中可以指定像是 "wallPosts"、"messages"、"friendRequests" 等群組。然而,Tag 則必須要在群組中唯一辨識通知本身。Group is the more generic identifier, where you can assign groups like "wallPosts", "messages", "friendRequests", etc. And then Tag should uniquely identify the notification itself from within the group. 然後可以使用一般群組,透過 RemoveGroup API 移除該群組中的所有通知。By using a generic group, you can then remove all notifications from that group by using the RemoveGroup API.

// Create toast content
var content = new ToastContentBuilder()
    .AddText("New post on your wall!")
    .GetToastContent();

// Set tag/group
new ToastNotification(content.GetXml())
{
    Tag = "18365",
    Group = "wallPosts"
};

// And show it!
ToastNotificationManager.CreateToastNotifier().Show(notif);

清除您的通知Clear your notifications

UWP app 會負責移除並清除其本身的通知。UWP apps are responsible for removing and clearing their own notifications. 啟動您的 App 時,我們並不會自動清除您的通知。When your app is launched, we do NOT automatically clear your notifications.

Windows 只有在使用者明確按一下通知時,才會自動移除通知。Windows will only automatically remove a notification if the user explicitly clicks the notification.

以下是一個範例,示範訊息中心 App 應該會做些什麼...Here's an example of what a messaging app should do…

  1. 使用者在交談中收到多個關於新訊息的快顯通知User receives multiple toasts about new messages in a conversation
  2. 使用者點選其中一個的快顯通知來開啟交談User taps one of those toasts to open the conversation
  3. App 開啟交談,然後清除該交談的所有快顯通知 (方法是針對該交談在 App 提供的群組上使用 RemoveGroup)The app opens the conversation and then clears all toasts for that conversation (by using RemoveGroup on the app-supplied group for that conversation)
  4. 使用者的控制中心現在會正確反映通知狀態,因為沒有該交談的任何過時通知留存在控制中心上。User's Action Center now properly reflects the notification state, since there are no stale notifications for that conversation left in Action Center.

若要了解清除所有通知,或移除特定通知,請參閱快速入門: 管理控制中心的快顯通知 (XAML)To learn about clearing all notifications or removing specific notifications, see Quickstart: Managing toast notifications in action center (XAML).

ToastNotificationManager.History.Clear();

純文字程式碼片段Plain code snippets

如果您不是使用來自 NuGet 的通知程式庫,您可以手動建立您的 XML,如下所示來建立 ToastNotificationIf you're not using the Notifications library from NuGet, you can manually construct your XML as seen below to create a ToastNotification.

using Windows.UI.Notifications;
using Windows.Data.Xml.Dom;

// In a real app, these would be initialized with actual data
string title = "Andrew sent you a picture";
string content = "Check this out, Happy Canyon in Utah!";
string image = "http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-81-permanent/2727.happycanyon1_5B00_1_5D00_.jpg";
string logo = "ms-appdata:///local/Andrew.jpg";
 
// TODO: all values need to be XML escaped
 
// Construct the visuals of the toast
string toastVisual =
$@"<visual>
  <binding template='ToastGeneric'>
    <text>{title}</text>
    <text>{content}</text>
    <image src='{image}'/>
    <image src='{logo}' placement='appLogoOverride' hint-crop='circle'/>
  </binding>
</visual>";

// In a real app, these would be initialized with actual data
int conversationId = 384928;
 
// Generate the arguments we'll be passing in the toast
string argsReply = $"action=reply&conversationId={conversationId}";
string argsLike = $"action=like&conversationId={conversationId}";
string argsView = $"action=viewImage&imageUrl={Uri.EscapeDataString(image)}";
 
// TODO: all args need to be XML escaped
 
string toastActions =
$@"<actions>
 
  <input
      type='text'
      id='tbReply'
      placeHolderContent='Type a response'/>
 
  <action
      content='Reply'
      arguments='{argsReply}'
      activationType='background'
      imageUri='Assets/Reply.png'
      hint-inputId='tbReply'/>
 
  <action
      content='Like'
      arguments='{argsLike}'
      activationType='background'/>
 
  <action
      content='View'
      arguments='{argsView}'/>
 
</actions>";

// Now we can construct the final toast content
string argsLaunch = $"action=viewConversation&conversationId={conversationId}";
 
// TODO: all args need to be XML escaped
 
string toastXmlString =
$@"<toast launch='{argsLaunch}'>
    {toastVisual}
    {toastActions}
</toast>";
 
// Parse to XML
XmlDocument toastXml = new XmlDocument();
toastXml.LoadXml(toastXmlString);
 
// Generate toast
var toast = new ToastNotification(toastXml);

資源Resources