Управление регистрацией

В этом разделе описывается регистрация устройств в центрах уведомлений для получения push-уведомлений. Сначала приводится общее описание, затем демонстрируются два основных типа регистрации устройств: регистрация с устройства непосредственно в центре уведомлений и регистрация с помощью серверной части приложения.

Регистрация устройств

Регистрация устройств в центре уведомлений осуществляется через регистрацию или установку.

Регистрация

Регистрация связывает маркер службы отправки уведомлений платформы (PNS) для устройства с тегами и, возможно, шаблоном. Дескриптором PNS может быть channelURI или идентификатор регистрации маркера устройства. Теги используются для направления уведомлений правильному набору маркеров устройств. Дополнительные сведения см. в статье Маршрутизация и выражения тегов. Шаблоны используются для преобразований в рамках регистрации. Дополнительные сведения см. в статье Шаблоны.

Примечание

Центры уведомлений Azure поддерживают не более 60 тегов на устройство.

Установки

Установка — это расширенная регистрация, включающая набор свойств, связанных с push-уведомлениями. Это новейший и лучший подход к регистрации устройств с помощью пакета SDK для .NET на стороне сервера (пакет SDK центра уведомлений для серверных операций). Кроме того, можно использовать REST API центров уведомлений для регистрации установленных экземпляров непосредственно на клиентском устройстве. При использовании внутренней службы должна иметься возможность применения пакета SDK концентратора уведомлений для серверных операций.

Ниже приведены некоторые ключевые преимущества регистрации через установку.

  • Создание или обновление установки является полностью идемпотентной операцией. Поэтому его можно повторять, не заботясь о дублирующихся регистрациях.
  • Модель установки поддерживает специальный формат тегов ($InstallationId:{INSTALLATION_ID}), который позволяет отправлять уведомления непосредственно на определенное устройство. Например, если в коде приложения для данного устройства задается идентификатор установки joe93developer, разработчик может выбрать это устройство в качестве целевого при отправке уведомления тегу $InstallationId:{joe93developer}. Так можно организовать отправку для определенного устройства без необходимости создавать дополнительный код.
  • Установка также позволяет частично обновлять регистрацию. Частичное обновление установки запрашивается с помощью метода PATCH из стандарта JSON-Patch. Это удобно в тех случаях, когда нужно обновить теги в регистрации. Нет необходимости удалять всю регистрацию и заново отправлять все прошлые теги.

Установка может содержать следующие свойства. Полный список свойств установки см. в статье об установке или перезаписи установки с помощью REST API или в статье Класс Installation.

// 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 можно получить только в клиентском приложении на устройстве, одним из типовых способов регистрации является регистрация непосредственно на этом устройстве с клиентским приложением. С другой стороны, режим безопасности и бизнес-логика, связанная с тегами, могут требовать, чтобы управление регистрацией устройств осуществлялось в серверной части приложения.

При отправке на дескриптор, срок действия которого истек в PNS, Центры уведомлений Azure автоматически очищают связанную запись установки или регистрации на основе ответа, полученного от PNS-сервера. Чтобы удалить записи с истекшим сроком действия из дополнительного центра уведомлений, добавьте пользовательскую логику, обрабатывающую результаты каждой отправки. Затем завершите срок действия установки или регистрации в дополнительном центре уведомлений.

Примечание

API установки не поддерживает службу Baidu (хотя API регистраций поддерживает).

Шаблоны

Если вы хотите использовать шаблоны, то установка устройства содержит все шаблоны, связанные с этим устройством, в формате JSON (см. пример выше). Названия шаблонов помогают связывать разные шаблоны с одним устройством.

Имя каждого шаблона сопоставляется с текстом шаблона и необязательным набором тегов. Кроме того, каждая платформа может иметь дополнительные свойства шаблонов. Для Магазина Windows (с помощью WNS) дополнительный набор заголовков может быть частью шаблона. Для имени точки доступа (APN) в свойстве окончания срока действия можно задать фиксированное значение или связать его с выражением шаблона. Полный список свойств установки см. в статье о создании или замене установки с помощью REST.

Вспомогательные плитки для приложений из Магазина Windows

Для клиентских приложений из Магазина Windows отправка уведомлений во вспомогательные плитки выполняется аналогично отправке уведомлений в основные плитки. Это также поддерживается в установках. У вспомогательных элементов другое значение ChannelUri, которое автоматически обрабатывается пакетом SDK в клиентском приложении.

В словаре SecondaryTiles используется тот же идентификатор TileId, с помощью которого создается объект SecondaryTiles в приложении Магазина Windows. Как и в случае с основным ChannelUri, идентификаторы ChannelUri вспомогательных плиток можно изменить в любой момент. Для поддержки актуальности установок в центре уведомлений устройство должно обновлять их с использованием текущих ChannelUri вспомогательных плиток.

Управление регистрацией с устройства

При управлении регистрацией устройства из клиентских приложений серверная часть отвечает только за отправку уведомлений. Клиентские приложения поддерживают актуальность дескрипторов PNS и регистрируют теги. На следующем рисунке показана схема работы.

Регистрация с устройства

Сначала устройство извлекает маркер PNS из службы PNS, а затем напрямую регистрируется в центре уведомлений. После успешной регистрации серверная часть приложения может отправить уведомление для этой регистрации. Дополнительные сведения об отправке уведомлений см. в статье Маршрутизация и выражения тегов.

В этом случае для доступа к своим центрам уведомлений с устройства следует использовать только права прослушивания. Дополнительные сведения см. в статье Безопасность.

Регистрация с устройства — это самый простой метод, но у него есть свои недостатки.

  • Клиентское приложение может обновлять свои теги, только когда оно активно. Например, если у пользователя есть два устройства, которые регистрируют теги, связанные со спортивными командами, то когда первое устройство регистрирует дополнительный тег (например Seahawks), второе устройство получит уведомление о теге Seahawks только при следующем запуске приложения на втором устройстве. В целом, если на теги влияют сразу несколько устройств, рекомендуется управлять тегами из серверной части.
  • Поскольку приложения могут подвергаться атаке злоумышленников, защита регистрации конкретными тегами требует особой осторожности, как описано в разделе Безопасность.

Пример кода регистрации в центре уведомлений с устройства с помощью установки

В настоящее время эта процедура поддерживается только с помощью API REST центра уведомлений.

Для обновления установки также можно использовать метод PATCH из стандарта JSON-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 (https://msdn.microsoft.com/library/azure/dn495627.aspx)
        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 ===
        // See https://msdn.microsoft.com/library/azure/dn495627.aspx
        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 have not stored 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 have not stored 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 в серверной части, который может выполнить регистрацию, авторизовать теги и т. д. Серверная часть может использовать пакет SDK центра уведомлений для операций серверной части.

Для обновления установки также можно использовать метод PATCH из стандарта JSON-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);
}

Пример кода для регистрации в центре уведомлений из серверной части с использованием идентификатора регистрации

Из серверной части приложения с регистрациями можно выполнять основные операции 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);

Серверная часть должна обеспечивать параллельность обновлений регистраций. Служебная шина предоставляет управление оптимистичным параллелизмом для управления регистрациями. На уровне HTTP это реализуется посредством использования ETag в операциях управления регистрацией. Эта функция автоматически используется в пакетах Microsoft SDK, которые выдают исключение, если обновление отклоняется по причинам параллелизма. Серверная часть приложения отвечает за обработку этих исключений и перезапуск обновления в случае необходимости.