Partilhar via


Gestão de registo

Este artigo explica como registrar dispositivos nos Hubs de Notificação do Azure para receber notificações por push. O artigo descreve os registros em um alto nível e, em seguida, apresenta os dois padrões principais para registrar dispositivos: registrar do dispositivo diretamente no hub de notificação e registrar por meio de um back-end de aplicativo.

O que é o registo de dispositivos?

O registro do dispositivo em um Hub de Notificação é realizado usando um Registro ou Instalação.

Inscrições

Um registo associa o identificador do Serviço de Notificação da Plataforma (PNS) de um dispositivo a tags e, possivelmente, a um modelo. O identificador PNS pode ser um ChannelURI ou um ID de registro de token de dispositivo. As tags são usadas para rotear notificações para o conjunto correto de identificadores de dispositivo. Para obter mais informações, consulte Roteamento e expressões de tag. Os modelos são usados para implementar a transformação por registro. Para obter mais informações, consulte Modelos.

Observação

Os Hubs de Notificação do Azure dão suporte a um máximo de 60 tags por dispositivo.

Instalações

Uma instalação é um registro aprimorado que inclui um conjunto de propriedades relacionadas a push. É a melhor e mais recente abordagem para registrar seus dispositivos usando o SDK .NET do lado do servidor (SDK do Hub de Notificação para operações de back-end). Você também pode usar a abordagem REST API dos Hubs de Notificação para registrar instalações no próprio dispositivo cliente. Se você estiver usando um serviço de back-end, deverá ser capaz de usar o SDK dos Hubs de Notificação para operações de back-end.

A seguir estão algumas das principais vantagens de usar instalações:

  • Criar ou atualizar uma instalação é totalmente idempotente. Você pode repeti-lo sem qualquer preocupação com registros duplicados.
  • O modelo de instalação suporta um formato de tag especial ($InstallationId:{INSTALLATION_ID}) que permite enviar uma notificação diretamente para o dispositivo específico. Por exemplo, se o código do aplicativo definir uma ID de instalação de joe93developer para este dispositivo específico, um desenvolvedor poderá direcionar esse dispositivo ao enviar uma notificação para a etiqueta $InstallationId:{joe93developer}. Isso permite que você segmente um dispositivo específico sem ter que fazer qualquer codificação adicional.
  • O uso de instalações também permite que você faça atualizações parciais de registro. A atualização parcial de uma instalação é solicitada com um método PATCH usando o padrãoJSON-Patch. Esse método é útil quando você deseja atualizar as tags no registro. Você não precisa puxar para baixo todo o registro e, em seguida, reenviar todas as tags anteriores.

Uma instalação pode conter as seguintes propriedades. Para obter uma lista completa das propriedades de instalação, consulte Criar ou substituir uma instalação com API REST ou Propriedades de instalação.

// 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: [] }
            }
        }
    }
}

Observação

Por padrão, os registros e instalações não expiram.

Os registos e instalações devem conter um identificador PNS válido para cada dispositivo/canal. Como os identificadores PNS só podem ser obtidos em um aplicativo cliente no dispositivo, um padrão é registrar diretamente nesse dispositivo com o aplicativo cliente. Por outro lado, considerações de segurança e lógica de negócios relacionadas a tags podem exigir que você gerencie o registro do dispositivo no back-end do aplicativo.

Quando o push é feito para um identificador que expirou pelo PNS, os Hubs de Notificação do Azure limpam automaticamente o registro de instalação/registro associado com base na resposta recebida do servidor PNS. Para limpar registros expirados de um hub de notificação secundário, adicione uma lógica personalizada que processe os comentários de cada envio. Em seguida, expire a instalação/registro no hub de notificação secundário.

Observação

As APIs de instalação não suportam o serviço Baidu (embora a API de registros o faça).

Modelos

Se você quiser usar modelos, a instalação do dispositivo também mantém todos os modelos associados a esse dispositivo em um formato JSON (consulte o exemplo na seção anterior). Os nomes dos modelos ajudam a direcionar modelos diferentes para o mesmo dispositivo.

Cada nome de modelo é mapeado para um corpo de modelo e um conjunto opcional de tags. Cada plataforma pode ter propriedades de modelo adicionais. No caso de APNs, você pode definir uma propriedade de expiração como uma constante ou uma expressão de modelo. Para obter uma lista completa das propriedades de instalação, consulte o tópico Criar ou substituir uma instalação com REST .

Blocos secundários para aplicações da Microsoft Store

Para aplicativos cliente da Windows Store, enviar notificações para blocos secundários é o mesmo que enviá-los para o principal. Isso também é suportado em instalações. Os blocos secundários têm um ChannelUri diferente, que o SDK em seu aplicativo cliente manipula de forma transparente.

O dicionário SecondaryTiles usa o mesmo TileId usado para criar o objeto SecondaryTiles em seu aplicativo da Windows Store. Tal como acontece com o ChannelUri primário, o ChannelUris de mosaicos secundários pode mudar a qualquer momento. Para manter as instalações no hub de notificação atualizadas, o dispositivo deve atualizá-las com o ChannelUris atual dos blocos secundários.

Gestão de registo a partir do dispositivo

Ao gerenciar o registro de dispositivos de aplicativos cliente, o back-end é responsável apenas pelo envio de notificações. As aplicações cliente mantêm os identificadores PNS up-to-date e registam etiquetas. A imagem a seguir ilustra esse padrão.

Registo a partir do dispositivo

O dispositivo primeiro recupera o identificador PNS do PNS e, em seguida, regista-se diretamente no hub de notificação. Depois que o registro for bem-sucedido, o back-end do aplicativo poderá enviar uma notificação direcionada a esse registro. Para obter mais informações sobre como enviar notificações, consulte Roteamento e expressões de marca.

Nesse caso, você usa apenas os direitos de Escuta para acessar seus hubs de notificação a partir do dispositivo. Para obter mais informações, consulte Security.

O registo a partir do dispositivo é o método mais simples, mas tem algumas desvantagens:

  • Um aplicativo cliente só pode atualizar suas tags quando o aplicativo estiver ativo. Por exemplo, se um usuário tiver dois dispositivos que registram tags relacionadas a equipes esportivas, quando o primeiro dispositivo se registra para uma tag adicional (por exemplo, Seahawks), o segundo dispositivo não recebe as notificações sobre os Seahawks até que o aplicativo no segundo dispositivo seja executado uma segunda vez. Mais geralmente, quando as tags são afetadas por vários dispositivos, o gerenciamento de tags do back-end é uma opção desejável.
  • Como os aplicativos podem ser hackeados, proteger o registro em tags específicas requer cuidados extras, como explicado no artigo Segurança.

Exemplo de código para se registrar em um hub de notificação de um dispositivo usando uma instalação

No momento, isso só é suportado usando a API REST dos Hubs de Notificação.

Você também pode usar o método PATCH usando o padrãoJSON-Patch para atualizar a instalação.

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

Exemplo de código para se registrar em um hub de notificação de um dispositivo usando um registro

Esses métodos criam ou atualizam um registro para o dispositivo no qual são chamados. Isso significa que, para atualizar o identificador ou as etiquetas, você deve substituir o registo completo. Lembre-se de que os registos são transitórios, pelo que deve ter sempre um sistema de armazenamento fiável com as etiquetas atuais que um dispositivo específico necessita.

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

Gestão de registos a partir de um back-end

Gerenciar registros do back-end requer escrever código adicional. O aplicativo do dispositivo deve fornecer o identificador PNS atualizado para o back-end sempre que o aplicativo for iniciado (junto com tags e modelos), e o back-end deve atualizar esse identificador no hub de notificação. A imagem a seguir ilustra esse design.

Gestão de registo

As vantagens de gerenciar registros a partir do back-end incluem a capacidade de modificar tags para registros, mesmo quando o aplicativo correspondente no dispositivo está inativo, e autenticar o aplicativo cliente antes de adicionar uma tag ao seu registro.

Exemplo de código para registrar com um hub de notificação de um back-end usando uma instalação

O dispositivo cliente ainda obtém o seu identificador PNS e as propriedades de instalação relevantes como antes e chama uma API personalizada no backend que pode executar o registo e autorizar etiquetas, etc. O backend pode utilizar o SDK do Notification Hub para operações de backend.

Você também pode usar o método PATCH usando o padrãoJSON-Patch para atualizar a instalação.

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

Exemplo de código para se registrar em um hub de notificação de um back-end usando uma ID de registro

No back-end do aplicativo, você pode executar operações CRUDS básicas em registros. Por exemplo:

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

O back-end deve lidar com a simultaneidade entre as atualizações de registro. Os Hubs de Notificação oferecem um controle de simultaneidade otimista para o gerenciamento de registros. No nível HTTP, isso é implementado com o uso de ETag em operações de gerenciamento de registro. Esse recurso é usado de forma transparente pelos SDKs da Microsoft, que lançam uma exceção se uma atualização for rejeitada por motivos de simultaneidade. O back-end do aplicativo é responsável por lidar com essas exceções e tentar novamente a atualização, se necessário.