次の方法で共有


登録管理

この記事では、プッシュ通知を受信するためにデバイスを Azure Notification Hubs に登録する方法について説明します。 この記事では、登録について大まかに説明した後、デバイスを登録するための 2 つの主要なパターンについて説明します。デバイスから通知ハブに直接登録する方法と、アプリケーション バックエンドを介して登録するパターンです。

デバイス登録とは

Notification Hub へのデバイスの登録は、 登録 または インストールを使用して行われます。

登録

登録により、デバイスのプラットフォーム通知サービス (PNS) ハンドルがタグとテンプレートに関連付けられます。 PNS ハンドルには、ChannelURI またはデバイス トークン登録 ID を指定できます。 タグは、通知を適切なデバイス ハンドルのセットにルーティングするために使用されます。 詳細については、「ルーティングとタグ式」を参照してください。 テンプレートは、登録ごとの変換を実装するために使用されます。 詳細については、「 テンプレート」を参照してください。

Azure Notification Hubs では、デバイスあたり最大 60 個のタグがサポートされています。

インストール

インストールは、プッシュ関連プロパティのセットを含む拡張登録です。 これは、サーバー側の .NET SDK (バックエンド操作用の Notification Hub SDK) を使用してデバイスを登録するための最新かつ最適なアプローチです。 Notification Hubs REST API アプローチを使用して、クライアント デバイス自体にインストールを登録することもできます。 バックエンド サービスを使用している場合は、 バックエンド操作に Notification Hubs SDK を使用できる必要があります。

インストールを使用する主な利点を次に示します。

  • インストールの作成または更新は、完全にべき等です。 登録の重複を気にせずに再試行できます。
  • インストール モデルでは、特定のデバイスに直接通知を送信できるようにする特殊なタグ形式 ($InstallationId:{INSTALLATION_ID}) がサポートされています。 たとえば、アプリのコードで、この特定のデバイスの joe93developer のインストール ID が設定されている場合、開発者は、 $InstallationId:{joe93developer} タグに通知を送信するときに、このデバイスをターゲットにすることができます。 これにより、追加のコーディングを行わなくても、特定のデバイスをターゲットにすることができます。
  • インストールを使用すると、部分的な登録更新を行うこともできます。 インストールの部分的な更新は、 JSON-Patch 標準を使用して PATCH メソッドを使用して要求されます。 このメソッドは、登録のタグを更新する場合に便利です。 登録全体をプルダウンしてから、前のすべてのタグを再送信する必要はありません。

インストールには、次のプロパティを含めることができます。 インストール・プロパティーの完全なリストについては、REST API またはインストール・プロパティーを使用したインストールの作成または上書きを参照してください。

// Example installation format to show some supported properties
{
    installationId: "",
    expirationTime: "",
    tags: [],
    platform: "",
    pushChannel: "",
    ………
    templates: {
        "templateName1" : {
            body: "",
            tags: [] },
        "templateName2" : {
            body: "",
            // Headers are for Windows Store only
            headers: {
                "X-WNS-Type": "wns/tile" }
            tags: [] }
    },
    secondaryTiles: {
        "tileId1": {
            pushChannel: "",
            tags: [],
            templates: {
                "otherTemplate": {
                    bodyTemplate: "",
                    headers: {
                        ... }
                    tags: [] }
            }
        }
    }
}

既定では、登録とインストールは期限切れになりません。

登録とインストールには、各デバイス/チャネルの有効な PNS ハンドルが含まれている必要があります。 PNS ハンドルはデバイス上のクライアント アプリでのみ取得できるため、1 つのパターンとして、そのデバイス上でクライアント アプリに直接登録します。 一方、タグに関連するセキュリティに関する考慮事項とビジネス ロジックでは、アプリバックエンドでデバイス登録を管理することが必要になる場合があります。

PNS によって期限切れになったハンドルにプッシュが行われると、Azure Notification Hubs は、PNS サーバーから受信した応答に基づいて、関連付けられているインストール/登録レコードを自動的にクリーンアップします。 セカンダリ通知ハブから期限切れのレコードを消去するには、各送信からのフィードバックを処理するカスタム ロジックを追加します。 次に、セカンダリ通知ハブでのインストール/登録の有効期限が切れます。

インストール API は Baidu サービスをサポートしていません (ただし、登録 API ではサポートされます)。

テンプレート

テンプレートを使用する場合、デバイスのインストールでは、そのデバイスに関連付けられているすべてのテンプレートも JSON 形式で保持されます (前のセクションのサンプルを参照)。 テンプレート名は、同じデバイスのさまざまなテンプレートをターゲットにするのに役立ちます。

各テンプレート名は、テンプレート本体とオプションのタグセットにマップされます。 各プラットフォームには、追加のテンプレート プロパティを含めることができます。 APNs の場合は、有効期限プロパティを定数またはテンプレート式に設定できます。 インストール・プロパティーの完全なリストについては、REST を使用した インストールの作成または上書きに関するトピックを 参照してください。

Windows ストア アプリのセカンダリ タイル

Windows ストア クライアント アプリケーションの場合、セカンダリ タイルへの通知の送信は、プライマリ タイルへの通知の送信と同じです。 これは、インストールでもサポートされます。 セカンダリ タイルには異なる ChannelUri があり、クライアント アプリの SDK が透過的に処理します。

SecondaryTiles ディクショナリは、Windows ストア アプリで SecondaryTiles オブジェクトを作成するために使用されるのと同じ TileId を使用します。 プライマリ ChannelUri と同様に、セカンダリ タイルの ChannelUris はいつでも変更できます。 通知ハブのインストールを更新し続けるために、デバイスはセカンダリ タイルの現在の ChannelUris で更新する必要があります。

デバイスからの登録管理

クライアント アプリからデバイス登録を管理する場合、バックエンドは通知の送信のみを担当します。 クライアント アプリは、PNS ハンドル up-to-date を保持し、タグを登録します。 次の図は、このパターンを示しています。

デバイスからの登録

デバイスは最初に PNS から PNS ハンドルを取得し、次に通知ハブに直接登録します。 登録が成功すると、アプリ バックエンドはその登録を対象とする通知を送信できます。 通知を送信する方法の詳細については、「 ルーティングとタグ式」を参照してください。

この場合、デバイスから通知ハブにアクセスするには 、リッスン 権限のみを使用します。 詳細については、「セキュリティ」を参照してください。

デバイスからの登録は最も簡単な方法ですが、いくつかの欠点があります。

  • クライアント アプリは、アプリがアクティブなときにのみタグを更新できます。 たとえば、ユーザーがスポーツ チームに関連するタグを登録する 2 つのデバイスを持っている場合、最初のデバイスが追加のタグ (Seahawks など) に登録されると、2 つ目のデバイスは、2 番目のデバイス上のアプリが 2 回目に実行されるまで Seahawks に関する通知を受け取りません。 より一般的には、タグが複数のデバイスの影響を受ける場合は、バックエンドからタグを管理することが望ましいオプションです。
  • アプリはハッキングされる可能性があるため、 セキュリティに関する記事で説明されているように、特定のタグへの登録をセキュリティで保護するには、特別な注意が必要です。

インストールを使用してデバイスから通知ハブに登録するコード例

現時点では、これは Notification Hubs REST API を使用してのみサポートされています。

インストールを更新するために 、JSON-Patch 標準 を使用して PATCH メソッドを使用することもできます。

class DeviceInstallation
{
    public string installationId { get; set; }
    public string platform { get; set; }
    public string pushChannel { get; set; }
    public string[] tags { get; set; }

    private async Task<HttpStatusCode> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation,
        string hubName, string listenConnectionString)
    {
        if (deviceInstallation.installationId == null)
            return HttpStatusCode.BadRequest;

        // Parse connection string
        ConnectionStringUtility connectionSaSUtil = new ConnectionStringUtility(listenConnectionString);
        string hubResource = "installations/" + deviceInstallation.installationId + "?";
        string apiVersion = "api-version=2015-04";

        // Determine the targetUri that we will sign
        string uri = connectionSaSUtil.Endpoint + hubName + "/" + hubResource + apiVersion;

        //=== Generate SaS Security Token for Authorization header ===
        string SasToken = connectionSaSUtil.getSaSToken(uri, 60);

        using (var httpClient = new HttpClient())
        {
            string json = JsonConvert.SerializeObject(deviceInstallation);

            httpClient.DefaultRequestHeaders.Add("Authorization", SasToken);

            var response = await httpClient.PutAsync(uri, new StringContent(json, System.Text.Encoding.UTF8, "application/json"));
            return response.StatusCode;
        }
    }

    var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();

    string installationId = null;
    var settings = ApplicationData.Current.LocalSettings.Values;

    // If we didn't store an installation ID in application data, create and store as application data.
    if (!settings.ContainsKey("__NHInstallationId"))
    {
        installationId = Guid.NewGuid().ToString();
        settings.Add("__NHInstallationId", installationId);
    }

    installationId = (string)settings["__NHInstallationId"];

    var deviceInstallation = new DeviceInstallation
    {
        installationId = installationId,
        platform = "wns",
        pushChannel = channel.Uri,
        //tags = tags.ToArray<string>()
    };

    var statusCode = await CreateOrUpdateInstallationAsync(deviceInstallation, 
                    "<HUBNAME>", "<SHARED LISTEN CONNECTION STRING>");

    if (statusCode != HttpStatusCode.Accepted)
    {
        var dialog = new MessageDialog(statusCode.ToString(), "Registration failed. Installation Id : " + installationId);
        dialog.Commands.Add(new UICommand("OK"));
        await dialog.ShowAsync();
    }
    else
    {
        var dialog = new MessageDialog("Registration successful using installation Id : " + installationId);
        dialog.Commands.Add(new UICommand("OK"));
        await dialog.ShowAsync();
    }
}

登録を使用してデバイスから通知ハブに登録するコード例

これらのメソッドは、呼び出されるデバイスの登録を作成または更新します。 つまり、ハンドルまたはタグを更新するには、登録全体を上書きする必要があります。 登録は一時的なものなので、特定のデバイスに必要な現在のタグを持つ信頼できるストアを常に用意する必要があります。

// Initialize the notification hub
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString(listenConnString, hubName);

// The Device ID from the PNS
var pushChannel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();

// If you are registering from the client itself, then store this registration ID in device
// storage. Then when the app starts, you can check if a registration ID already exists or not before
// creating.
var settings = ApplicationData.Current.LocalSettings.Values;

// If we didn't store a registration ID in application data, store in application data.
if (!settings.ContainsKey("__NHRegistrationId"))
{
    // Make sure there are no existing registrations for this push handle (used for iOS and Android)    
    string newRegistrationId = null;
    var registrations = await hub.GetRegistrationsByChannelAsync(pushChannel.Uri, 100);
    foreach (RegistrationDescription registration in registrations)
    {
        if (newRegistrationId == null)
        {
            newRegistrationId = registration.RegistrationId;
        }
        else
        {
            await hub.DeleteRegistrationAsync(registration);
        }
    }

    newRegistrationId = await hub.CreateRegistrationIdAsync();

    settings.Add("__NHRegistrationId", newRegistrationId);
}

string regId = (string)settings["__NHRegistrationId"];

RegistrationDescription registration = new WindowsRegistrationDescription(pushChannel.Uri);
registration.RegistrationId = regId;
registration.Tags = new HashSet<string>(YourTags);

try
{
    await hub.CreateOrUpdateRegistrationAsync(registration);
}
catch (Microsoft.WindowsAzure.Messaging.RegistrationGoneException e)
{
    settings.Remove("__NHRegistrationId");
}

バックエンドからの登録管理

バックエンドからの登録を管理するには、追加のコードを記述する必要があります。 デバイスのアプリは、アプリが起動するたびに (タグとテンプレートと共に) 更新された PNS ハンドルをバックエンドに提供する必要があり、バックエンドは通知ハブでこのハンドルを更新する必要があります。 次の図は、この設計を示しています。

登録管理

バックエンドから登録を管理する利点には、デバイス上の対応するアプリが非アクティブな場合でも、登録にタグを変更する機能や、登録にタグを追加する前にクライアント アプリを認証する機能があります。

インストールを使用してバックエンドから通知ハブに登録するコード例

クライアント デバイスは、以前と同様に PNS ハンドルと関連するインストール プロパティを取得し、登録や承認タグなどを実行できるカスタム API をバックエンドで呼び出します。バックエンドは、 バックエンド操作に Notification Hub SDK を利用できます。

インストールを更新するために 、JSON-Patch 標準 を使用して PATCH メソッドを使用することもできます。

// Initialize the Notification Hub
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString(listenConnString, hubName);

// Custom API on the backend
public async Task<HttpResponseMessage> Put(DeviceInstallation deviceUpdate)
{

    Installation installation = new Installation();
    installation.InstallationId = deviceUpdate.InstallationId;
    installation.PushChannel = deviceUpdate.Handle;
    installation.Tags = deviceUpdate.Tags;

    switch (deviceUpdate.Platform)
    {
        case "wns":
            installation.Platform = NotificationPlatform.Wns;
            break;
        case "apns":
            installation.Platform = NotificationPlatform.Apns;
            break;
        case "fcm":
            installation.Platform = NotificationPlatform.Fcm;
            break;
        default:
            throw new HttpResponseException(HttpStatusCode.BadRequest);
    }


    // In the backend we can control if a user is allowed to add tags
    //installation.Tags = new List<string>(deviceUpdate.Tags);
    //installation.Tags.Add("username:" + username);

    await hub.CreateOrUpdateInstallationAsync(installation);

    return Request.CreateResponse(HttpStatusCode.OK);
}

登録 ID を使用してバックエンドから通知ハブに登録するコード例

アプリ バックエンドから、登録に対して基本的な CRUDS 操作を実行できます。 例えば次が挙げられます。

var hub = NotificationHubClient.CreateClientFromConnectionString("{connectionString}", "hubName");

// create a registration description object of the correct type, e.g.
var reg = new WindowsRegistrationDescription(channelUri, tags);

// Create
await hub.CreateRegistrationAsync(reg);

// Get by ID
var r = await hub.GetRegistrationAsync<RegistrationDescription>("id");

// update
r.Tags.Add("myTag");

// update on hub
await hub.UpdateRegistrationAsync(r);

// delete
await hub.DeleteRegistrationAsync(r);

バックエンドは、登録更新間のコンカレンシーを処理する必要があります。 Notification Hubs には、登録管理のためのオプティミスティック コンカレンシー制御が用意されています。 HTTP レベルでは、これは登録管理操作で ETag を使用して実装されます。 この機能は Microsoft SDK によって透過的に使用されます。これにより、コンカレンシー上の理由で更新が拒否された場合に例外がスローされます。 アプリ バックエンドは、これらの例外を処理し、必要に応じて更新を再試行する役割を担います。