次の方法で共有


通知リスナー: すべての通知にアクセスする

通知リスナーは、ユーザーの通知にアクセスできます。 スマート ウォッチやその他のウェアラブルデバイスは、通知リスナーを使用して、スマートフォンの通知をウェアラブル デバイスに送信できます。 ホーム オートメーション アプリでは、通知リスナーを使用して、通知を受信したときに特定のアクション (電話がかかってきたときにランプを点滅するなど) を実行することができます。

重要

Anniversary Update が必要: 通知リスナーを使用するには、SDK 14393 をターゲットとし、ビルド 14393 以降を実行している必要があります。

重要な API: UserNotificationListener クラスUserNotificationChangedTrigger クラス

ユーザー通知機能を追加してリスナーを有効にする

通知リスナーを使用するには、ユーザー通知リスナー機能をアプリ マニフェストに追加する必要があります。

  1. Visual Studio のソリューション エクスプローラーで、Package.appxmanifest ファイルをダブルクリックしてマニフェスト デザイナーを開きます。
  2. [機能] タブを開きます。
  3. User 通知リスナー機能を確認します。

リスナーがサポートされているかどうかを確認する

アプリで以前のバージョンの Windows 10 がサポートされている場合は、 ApiInformation クラス を使用してリスナーがサポートされているかどうかを確認する必要があります。 リスナーがサポートされていない場合は、リスナー API への呼び出しを実行しないでください。

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

リスナーへのアクセスの要求

リスナーはユーザーの通知へのアクセスを許可するため、ユーザーは通知にアクセスするためのアクセス許可をアプリに付与する必要があります。 アプリの初回実行時に、通知リスナーを使用するためのアクセスを要求する必要があります。 必要に応じて、 RequestAccessAsync を呼び出す前にアプリがユーザーの通知にアクセスする必要がある理由を説明する暫定的な UI を表示して、アクセスを許可する理由をユーザーが理解できるようにすることができます。

// 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 設定を使用していつでもアクセスを取り消すことができます。 そのため、アプリでは常に、通知リスナーを使用するコードを実行する前に、GetAccessStatus メソッドを使用してアクセス状態を確認する必要があります。 ユーザーがアクセスを取り消した場合、API は例外をスローするのではなく、自動的に失敗します (たとえば、すべての通知を取得する API は空のリストを返します)。

ユーザーの通知にアクセスする

通知リスナーを使用すると、ユーザーの現在の通知の一覧を取得できます。 GetNotificationsAsync メソッドを呼び出し、取得する通知の種類を指定するだけです (現在、サポートされている通知の種類はトースト通知のみです)。

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

通知の表示

各通知は UserNotification として表され、通知の元のアプリ、通知の作成時刻、通知の ID、通知自体に関する情報が提供されます。

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

AppInfo プロパティは、通知を表示するために必要な情報を提供します。

Note

1 つの通知をキャプチャするときに予期しない例外が発生した場合に備えて、try/catch で 1 つの通知を処理するために、すべてのコードを囲うことをお勧めします。 1 つの特定の通知に問題があるため、他の通知の表示に完全に失敗しないようにしてください。

// 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 プロパティに含まれています。 このプロパティには、通知の視覚的な部分が含まれています。 (Windows での通知の送信に慣れている場合は、 Visual および Visual.Bindings Notification オブジェクトのプロパティは、通知をポップするときに開発者が送信する内容に対応します)。

トースト バインディングを検索します (エラー防止コードの場合は、バインディングが null ではないことを確認する必要があります)。 バインドから、テキスト要素を取得できます。 必要な数のテキスト要素を表示することを選択できます。 (理想的には、すべてを表示する必要があります)。テキスト要素を異なる方法で扱うことを選択できます。たとえば、最初の要素をタイトル テキストとして扱い、後続の要素を本文として扱います。

// 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));
}

特定の通知を削除する

ウェアラブルまたはサービスでユーザーが通知を無視できる場合は、実際の通知を削除して、ユーザーが後で電話や PC に表示されないようにすることができます。 削除する通知の通知 ID ( UserNotification オブジェクトから取得) を指定するだけです。

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

すべての通知をクリアする

UserNotificationListener.ClearNotifications メソッドは、ユーザーのすべての通知をクリアします。 この方法は注意して使用してください。 すべての通知をクリアする必要があるのは、ウェアラブルまたはサービスにすべての通知が表示される場合のみです。 ウェアラブルまたはサービスが特定の通知のみを表示する場合、ユーザーが [通知のクリア] ボタンをクリックすると、ユーザーはそれらの特定の通知のみが削除されることを期待しています。ただし、 ClearNotifications メソッドを呼び出すと、実際には、ウェアラブルまたはサービスが表示されていない通知を含むすべての通知が削除されます。

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

通知のバックグラウンド タスクの追加/非表示

アプリが通知をリッスンできるようにする一般的な方法は、バックグラウンド タスクを設定して、アプリが現在実行されているかどうかに関係なく、通知がいつ追加または無視されたかを知ることができるようにすることです。

Anniversary Update に追加された single プロセス モデルのおかげで バックグラウンド タスクの追加はかなり簡単です。 メイン アプリのコードで、UserNotificationListener.Current.RequestAccessAsyncBackgroundExecutionManager.RequestAccessAsync をそれぞれ呼び出すことにより、通知リスナーへのユーザー アクセスを取得し、バックグラウンド タスクを実行するためのアクセスを取得した後で、新しいバックグラウンド タスクを登録し、トースト通知の種類を使用して UserNotificationChangedTrigger を設定するだけです。

// 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 メソッドをオーバーライドします (まだ実行していない場合)。

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

バックグラウンド タスクは単なる "ショルダー タップ" です。追加または削除された特定の通知に関する情報は提供されません。 バックグラウンド タスクがトリガーされたら、プラットフォームの通知を反映するように、ウェアラブルで通知を同期する必要があります。 これにより、バックグラウンド タスクが失敗した場合でも、次にバックグラウンド タスクを実行する際にウェアラブルの通知を回復できます。

SyncNotifications は、実装するメソッドです。次のセクションでその方法を説明します。

追加および削除された通知の決定

SyncNotificationsメソッドでは、追加または削除された通知 (ウェアラブルと通知の同期) を決定するには、現在の通知コレクションとプラットフォーム内の通知の間の差分を計算する必要があります。

// 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);
}

通知のフォアグラウンド イベントの追加/無視

重要

既知の問題: ビルド 17763/October 2018 Update/バージョン 1809 以前のビルドでは、フォアグラウンド イベントによって CPU ループが発生するか、動作しませんでした。 これらの以前のビルドでのサポートが必要な場合は、代わりにバックグラウンド タスクを使用します。

メモリ内のイベント ハンドラーからの通知をリッスンすることもできます。

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

バックグラウンド タスクの遅延を修正する方法

アプリをテストするとき、バックグラウンド タスクが遅延し、数分間トリガーされない場合があります。 遅延を修正するには、ユーザーに対して [システム設定] -> [システム] -> [バッテリー] -> [アプリによるバッテリーの使用] に移動して、一覧でアプリを探して選択し、[バックグラウンドで常に許可] に設定するように要求します。この操作を行うと、バックグラウンド タスクは、通知の受信後数秒以内にトリガーされるようになります。