通知リスナー。すべての通知へのアクセスします。Notification listener: Access all notifications

通知リスナーを使用すると、ユーザーの通知にアクセスすることができます。The notification listener provides access to a user's notifications. スマートウォッチや他のウェアラブルでは、通知リスナーを使用して、電話の通知をウェアラブル デバイスに送信することができます。Smartwatches and other wearables can use the notification listener to send the phone's notifications to the wearable device. ホーム オートメーション アプリは、通知リスナーを使用して、呼び出しを受信するときに、ライトが点滅するなど、通知が受信したときに、特定のアクションを実行できます。Home automation apps can use notification listener to perform specific actions when notifications are received, such as making the lights blink when you receive a call.

重要

Anniversary Update が必要です:SDK 14393 を対象にして、14393 以上通知リスナーを使用するビルドを実行します。Requires Anniversary Update: You must target SDK 14393 and be running build 14393 or higher to use Notification Listener.

重要な API:UserNotificationListener クラスUserNotificationChangedTrigger クラスImportant APIs: UserNotificationListener class, UserNotificationChangedTrigger class

ユーザー通知機能を追加して、リスナーを有効にするEnable the listener by adding the User Notification capability

通知リスナーを使用するには、ユーザー通知リスナー機能をアプリ マニフェストに追加する必要があります。To use the notification listener, you must add the User Notification Listener capability to your app manifest.

  1. Visual Studio のソリューション エクスプローラーで、Package.appxmanifest ファイルをダブルクリックし、マニフェスト デザイナーを開きます。In Visual Studio, in the Solution Explorer, double click your Package.appxmanifest file to open the manifest designer.
  2. [機能] タブを開きます。Open the Capabilities tab.
  3. [ユーザー通知リスナー] 機能をオンにします。Check the User Notification Listener capability.

リスナーがサポートされているかどうかを確認するCheck whether the listener is supported

アプリで Windows 10 の以前のバージョンをサポートする場合は、ApiInformation クラス を使用して、リスナーがサポートされているかどうかを確認する必要があります。If your app supports older versions of Windows 10, you need to use the ApiInformation class to check whether the listener is supported. リスナーがサポートされていない場合は、リスナー API の呼び出しを実行しないでください。If the listener isn't supported, avoid executing any calls to the listener APIs.

if (ApiInformation.IsTypePresent("Windows.UI.Notifications.Management.UserNotificationListener"))
{
    // Listener supported!
}
 
else
{
    // Older version of Windows, no Listener
}

リスナーへのアクセスを要求するRequesting access to the listener

リスナーではユーザーの通知へのアクセスが許可されるため、ユーザーは、通知へのアクセス許可をアプリに付与する必要があります。Since the listener allows access to the user's notifications, users must give your app permission to access their notifications. アプリの最初の実行エクスペリエンスの際に、通知リスナーを使用するためのアクセスを要求する必要があります。During your app's first-run experience, you should request access to use the notification listener. 必要な場合は、RequestAccessAsync を呼び出す前に、アプリがユーザーの通知にアクセスする必要がある理由を説明する UI を事前に表示することができます。これにより、ユーザーはアクセスが許可される理由を理解することができます。If you want, you can show some preliminary UI that explains why your app needs access to the user's notifications before you call RequestAccessAsync, so that the user understands why they should allow access.

// Get the listener
UserNotificationListener listener = UserNotificationListener.Current;
 
// And request access to the user's notifications (must be called from UI thread)
UserNotificationListenerAccessStatus accessStatus = await listener.RequestAccessAsync();
 
switch (accessStatus)
{
    // This means the user has granted access.
    case UserNotificationListenerAccessStatus.Allowed:
 
        // Yay! Proceed as normal
        break;
 
    // This means the user has denied access.
    // Any further calls to RequestAccessAsync will instantly
    // return Denied. The user must go to the Windows settings
    // and manually allow access.
    case UserNotificationListenerAccessStatus.Denied:
 
        // Show UI explaining that listener features will not
        // work until user allows access.
        break;
 
    // This means the user closed the prompt without
    // selecting either allow or deny. Further calls to
    // RequestAccessAsync will show the dialog again.
    case UserNotificationListenerAccessStatus.Unspecified:
 
        // Show UI that allows the user to bring up the prompt again
        break;
}

ユーザーは Windows 設定アプリを使用して、アクセスをいつでも取り消すことができます。The user can revoke access at any time via Windows Settings. そのため、アプリでする必要がありますを使用してアクセスの状態を確認常に、 GetAccessStatus通知リスナーを使用するコードを実行する前にメソッド。Therefore, your app should always check the access status via the GetAccessStatus method before executing code that uses the notification listener. ユーザーがアクセスを取り消すと、API は例外をスローせず、警告なしに失敗します (たとえば、すべての通知を取得する API は空のリストを返すだけです)。If the user revokes access, the APIs will silently fail rather than throwing an exception (for example, the API to get all notifications will simply return an empty list).

ユーザーの通知にアクセスするAccess the user's notifications

通知リスナーを使用すると、ユーザーの現在の通知に関する一覧を取得できます。With the notification listener, you can get a list of the user's current notifications. GetNotificationsAsync メソッドを呼び出し、取得する必要がある通知の種類を指定するだけです (現時点では、サポートされている通知の種類はトースト通知のみです)。Simply call the GetNotificationsAsync method, and specify the type of notifications you want to get (currently, the only type of notifications supported are toast notifications).

// Get the toast notifications
IReadOnlyList<UserNotification> notifs = await listener.GetNotificationsAsync(NotificationKinds.Toast);

通知の表示Displaying the notifications

各通知は UserNotification として表されます。このクラスは、通知の送信元となるアプリに関する情報、通知が作成された時間、通知の ID、および通知自体を提供します。Each notification is represented as a UserNotification, which provides information about the app that the notification is from, the time the notification was created, the notification's ID, and the notification itself.

public sealed class UserNotification
{
    public AppInfo AppInfo { get; }
    public DateTimeOffset CreationTime { get; }
    public uint Id { get; }
    public Notification Notification { get; }
}

AppInfo プロパティは、通知の表示に必要な情報を提供します。The AppInfo property provides the info you need to display the notification.

注意

1 つの通知をキャプチャしたときに予期しない例外が発生する場合に備えて、1 つの通知を処理するコードはすべて、try/catch で囲むことをお勧めします。We recommend surrounding all your code for processing a single notification in a try/catch, in case an unexpected exception occurs when you are capturing a single notification. ある特定の通知で問題が発生した場合でも、他の通知の表示がすべて失敗するのを防ぐ必要があります。You shouldn't completely fail to display other notifications just because of an issue with one specific notification.

// Select the first notification
UserNotification notif = notifs[0];
 
// Get the app's display name
string appDisplayName = notif.AppInfo.DisplayInfo.DisplayName;
 
// Get the app's logo
BitmapImage appLogo = new BitmapImage();
RandomAccessStreamReference appLogoStream = notif.AppInfo.DisplayInfo.GetLogo(new Size(16, 16));
await appLogo.SetSourceAsync(await appLogoStream.OpenReadAsync());

通知の本文などの通知自体のコンテンツは、Notification プロパティに含まれています。The content of the notification itself, such as the notification text, is contained in the Notification property. このプロパティには、通知の視覚的な部分が含まれます。This property contains the visual portion of the notification. (Windows での通知の送信について詳しく理解している方は、Notification オブジェクトの Visual プロパティと Visual.Bindings プロパティが、通知が表示されるときに開発者が送信するデータに対応するということにお気づきでしょう)。(If you are familiar with sending notifications on Windows, you will notice that the Visual and Visual.Bindings properties in the Notification object correspond to what developers send when popping a notification.)

トーストのバインディングを調べる必要があります (エラー防止コードのために、バインディングが null でないことを確認する必要があります)。We want to look for the toast binding (for error-proof code, you should check that the binding isn't null). バインディングから、テキスト要素を取得できます。From the binding, you can obtain the text elements. テキスト要素は、必要な数だけ表示するように選択できます You can choose to display as many text elements as you would like. (理想的には、する必要があります表示すべて)。テキスト要素を取り扱うことができます。たとえば、本文としてタイトルのテキストとして 1 つ目と後続の要素を処理します。(Ideally, you should display them all.) You can choose to treat the text elements differently; for example, treat the first one as title text, and subsequent elements as body text.

// Get the toast binding, if present
NotificationBinding toastBinding = notif.Notification.Visual.GetBinding(KnownNotificationBindings.ToastGeneric);
 
if (toastBinding != null)
{
    // And then get the text elements from the toast binding
    IReadOnlyList<AdaptiveNotificationText> textElements = toastBinding.GetTextElements();
 
    // Treat the first text element as the title text
    string titleText = textElements.FirstOrDefault()?.Text;
 
    // We'll treat all subsequent text elements as body text,
    // joining them together via newlines.
    string bodyText = string.Join("\n", textElements.Skip(1).Select(t => t.Text));
}

特定の通知を削除するRemove a specific notification

お使いのウェアラブルやサービスで、ユーザーが通知を無視することが許可されている場合、実際の通知を削除し、ユーザーの電話や PC に後で通知が表示されないようにすることができます。If your wearable or service allows the user to dismiss notifications, you can remove the actual notification so the user doesn't see it later on their phone or PC. そのためには、削除する通知の通知 ID (UserNotification オブジェクトから取得します) を指定するだけです。Simply provide the notification ID (obtained from the UserNotification object) of the notification you'd like to remove:

// Remove the notification
listener.RemoveNotification(notifId);

すべての通知を消去するClear all notifications

UserNotificationListener.ClearNotifications メソッドは、すべてのユーザーの通知を消去します。The UserNotificationListener.ClearNotifications method clears all the user's notifications. このメソッドは慎重に使用してください。Use this method with caution. お使いのウェアラブルやサービスですべての通知が表示される場合にのみ、すべての通知を消去してください。You should only clear all notifications if your wearable or service displays ALL notifications. ウェアラブルやサービスで表示されるのが特定の通知のみである場合、ユーザーが [通知を消去する] ボタンをクリックしたとき、ユーザーは特定の通知のみが削除されると想定しますが、ClearNotifications メソッドが呼び出されると、実際にはすべての通知 (ウェアラブルやサービスでは表示されていなかった通知を含む) が削除されてしまいます。If your wearable or service only displays certain notifications, when the user clicks your "Clear notifications" button, the user is only expecting those specific notifications to be removed; however, calling the ClearNotifications method would actually cause all the notifications, including ones that your wearable or service wasn't displaying, to be removed.

// Clear all notifications. Use with caution.
listener.ClearNotifications();

追加/無視される通知のバックグラウンド タスクBackground task for notification added/dismissed

アプリで通知をリッスンできるようにするための一般的な方法は、バックグラウンド タスクのセットアップです。これにより、アプリが現在実行されているかどうかに関係なく、いつ通知が追加されたかまたは無視されたかを把握することができます。A common way to enable an app to listen to notifications is to set up a background task, so that you can know when a notification was added or dismissed regardless of whether your app is currently running.

Anniversary Update にはシングル プロセス モデルが導入されたため、バックグラウンド タスクの追加が非常に簡単になりました。Thanks to the single process model added in the Anniversary Update, adding background tasks is fairly simple. メイン アプリのコードで、通知リスナーへのユーザー アクセスを取得し、バックグラウンド タスクを実行するためのアクセスを取得した後で、新しいバックグラウンド タスクを登録し、トースト通知の種類を使用して UserNotificationChangedTrigger を設定するだけです。In your main app's code, after you have obtained the user's access to Notification Listener and obtained access to run background tasks, simply register a new background task, and set the UserNotificationChangedTrigger using the Toast notification kind.

// TODO: Request/check Listener access via UserNotificationListener.Current.RequestAccessAsync
 
// TODO: Request/check background task access via BackgroundExecutionManager.RequestAccessAsync
 
// If background task isn't registered yet
if (!BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals("UserNotificationChanged")))
{
    // Specify the background task
    var builder = new BackgroundTaskBuilder()
    {
        Name = "UserNotificationChanged"
    };
 
    // Set the trigger for Listener, listening to Toast Notifications
    builder.SetTrigger(new UserNotificationChangedTrigger(NotificationKinds.Toast));
 
    // Register the task
    builder.Register();
}

その後で、App.xaml.cs で OnBackgroundActivated メソッドをオーバーライドします (まだオーバーライドしていない場合)。タスク名に対して switch ステートメントを使用して、どのバックグラウンド タスク トリガーが起動されたかを特定します。Then, in your App.xaml.cs, override the OnBackgroundActivated method if you haven't yet, and use a switch statement on the task name to determine which of your many background task triggers was invoked.

protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
    var deferral = args.TaskInstance.GetDeferral();
 
    switch (args.TaskInstance.Task.Name)
    {
        case "UserNotificationChanged":
            // Call your own method to process the new/removed notifications
            // The next section of documentation discusses this code
            await MyWearableHelpers.SyncNotifications();
            break;
    }
 
    deferral.Complete();
}

バックグラウンド タスクは単純な "ショルダー タップ" です。追加または削除された特定の通知に関する情報は提供しません。The background task is simply a "shoulder tap": it doesn't provide any information about which specific notification was added or removed. バックグラウンド タスクがトリガーされたら、プラットフォームでの通知が反映されるように、ウェアラブルの通知を同期する必要があります。When your background task is triggered, you should sync the notifications on your wearable so that they reflect the notifications in the platform. これにより、バックグラウンド タスクが失敗した場合でも、次回バックグラウンド タスクが実行されたときに、ウェアラブルの通知を復旧することができます。This ensures that if your background task fails, notifications on your wearable can still be recovered the next time your background task executes.

SyncNotifications を実装する方法します。次のセクションの方法を示します。SyncNotifications is a method you implement; the next section shows how.

追加または削除された通知を特定するDetermining which notifications were added and removed

SyncNotifications では、(ウェアラブルと通知を同期するときに) 追加または削除された通知を特定するために、現在の通知のコレクションとプラットフォームの通知との差分を計算する必要があります。In your SyncNotifications method, to determine which notifications have been added or removed (syncing notifications with your wearable), you have to calculate the delta between your current notification collection, and the notifications in the platform.

// Get all the current notifications from the platform
IReadOnlyList<UserNotification> userNotifications = await listener.GetNotificationsAsync(NotificationKinds.Toast);
 
// Obtain the notifications that our wearable currently has displayed
IList<uint> wearableNotificationIds = GetNotificationsOnWearable();
 
// Copy the currently displayed into a list of notification ID's to be removed
var toBeRemoved = new List<uint>(wearableNotificationIds);
 
// For each notification in the platform
foreach (UserNotification userNotification in userNotifications)
{
    // If we've already displayed this notification
    if (wearableNotificationIds.Contains(userNotification.Id))
    {
        // We want to KEEP it displayed, so take it out of the list
        // of notifications to remove.
        toBeRemoved.Remove(userNotification.Id);
    }
 
    // Otherwise it's a new notification
    else
    {
        // Display it on the Wearable
        SendNotificationToWearable(userNotification);
    }
}
 
// Now our toBeRemoved list only contains notification ID's that no longer exist in the platform.
// So we will remove all those notifications from the wearable.
foreach (uint id in toBeRemoved)
{
    RemoveNotificationFromWearable(id);
}

追加/無視される通知のフォアグラウンド イベントForeground event for notification added/dismissed

重要

既知の問題:17763 をビルドする前に/2018 の年 10 月のビルドで更新プログラム]、[バージョン 1809、フォア グラウンドのイベントにより、CPU のループや動作しませんでした。Known issue: In builds before Build 17763 / October 2018 Update / Version 1809, The foreground event will cause a CPU loop and/or didn't work. それらの以前のビルドでのサポートが必要な場合は、バック グラウンド タスクを使用します。If you need support on those earlier builds, use the background task instead.

メモリ内のイベント ハンドラーから通知をリッスンすることができますもしています.You can also listen to notifications from an in-memory event handler...

// Subscribe to foreground event
listener.NotificationChanged += Listener_NotificationChanged;
 
private void Listener_NotificationChanged(UserNotificationListener sender, UserNotificationChangedEventArgs args)
{
    // Your code for handling the notification
}

バック グラウンド タスクの遅延を修正する方法How to fix delays in the background task

アプリをテストするときにバック グラウンド タスクが遅延される場合があり、数分をトリガーしないことが分かります。When testing your app, you might notice that the background task is sometimes delayed and doesn't trigger for several minutes. プロンプトでユーザーをシステムの設定を遅延を解決するには、システム-> バッテリ-> アプリによってバッテリの使用量を -> の一覧でアプリを見つけ、選択し、および バック グラウンドで許可されている常に"に設定To fix the delay, prompt the user to go to the system settings -> System -> Battery -> Battery usage by app, find your app in the list, select it, and set it to be "Always allowed in background." その後にするバック グラウンド タスクの通知を受信している 2 つ目の周り内で常にトリガーする必要があります。 After this, the background task should always be triggered within around a second of the notification being received.