Abril de 2016

Volume 31, Número 4

Cutting Edge - Notificações por Push nos Aplicativos Móveis

PorDino Esposito | Abril de 2016

Dino EspositoEm minhas últimas colunas, escrevi principalmente sobre arquitetura e design de software. Embora o papel da arquitetura na criação de um sistema de software nunca deva ser subestimado ou negado, em última análise, qualquer aplicativo é o resultado da soma dos recursos individuais. É a mesma filosofia de UXDD (User Experience Driven Development, Desenvolvimento Orientado pela Experiência do Usuário) que diz que a medida de sucesso para um aplicativo de software está na experiência que o usuário obtém ao lidar com o aplicativo. Se seu sistema de software inclui um front-end móvel, você dificilmente pode ignorar um recurso como as notificações por push.

Nesta coluna, resumirei o que é necessário para adicionar uma camada de notificação a aplicativos móveis, independentemente do sistema operacional móvel em si. Ao fazer isso, vou examinar os serviços da plataforma do Hub de Notificação do Microsoft Azure.

Visão Geral das Notificações por Push

Uma notificação por push ocorre quando um dispositivo móvel recebe uma mensagem do back-end do aplicativo sem primeiro enviar uma solicitação explícita. A maioria das interações entre os componentes cliente e servidor de um aplicativo ocorre por meio de uma ação explícita (normalmente, uma ação do usuário) que solicita comentários. De certa forma, uma notificação por push é uma espécie de comentário não solicitado, uma mensagem que o back-end envia quando informações importantes estão disponíveis. Para ser mais preciso, o termo "não solicitado" não é completamente exato aqui. Qualquer aplicativo móvel deve assinar o feed disponível para receber notificações por push. No entanto, após a assinatura do serviço, as notificações chegam de forma não solicitada.

O efeito concreto das notificações por push para um usuário é a entrega de atualizações relevantes quer ele esteja ou não usando ativamente o aplicativo. Por exemplo, a instalação do aplicativo de uma empresa aérea provavelmente o habilita a receber atualizações rápidas e oportunas sobre a agenda e alterações de portão. Em algum momento, o telefone toca ou vibra e comentários visíveis aparecem em algum lugar na interface do telefone. No entanto, o local exato onde eles aparecem depende estritamente da versão do sistema operacional em que o dispositivo se baseia, bem como na configuração do aplicativo e nas configurações do usuário. Dependendo do sistema operacional, uma notificação por push pode ter a forma de um ícone na barra superior, uma mensagem de notificação do sistema, uma atualização de notificação e assim por diante.

O ponto crucial das notificações push é que todos os seus aspectos técnicos são rigorosamente específicos da plataforma. Por exemplo, a maneira como um aplicativo assina um serviço de notificação por push é diferente em aplicativos para iOS, Android, Windows Phone e UWP (Plataforma Universal do Windows). Da mesma forma, cada plataforma usa sua própria carga para entregar mensagens a dispositivos conectados e cada plataforma requer que você configure um mecanismo de envio diferente. Apesar das diferenças significativas na implementação real, ouso dizer que a arquitetura geral de um PNS (sistema de notificação por push) é bastante comum e se parece com o diagrama na Figura 1.

Arquitetura Geral de um Sistema de Notificação por Push Específico de uma Plataforma
Figura 1 Arquitetura Geral de um Sistema de Notificação por Push Específico de uma Plataforma

Trabalhar com Vários Sistemas de Notificação por Push

Não é surpresa que a variedade de plataformas móveis disponíveis também se reflita em uma variedade de plataformas de notificação por push. Um desenvolvedor que cria um aplicativo móvel para várias plataformas deve se familiarizar com vários mecanismos de notificação por push diferentes e deve configurar um ambiente de servidor adequado para cada um deles. A menos que você esteja desenvolvendo um aplicativo para uma única plataforma móvel sem planos previstos de portá-lo para outras plataformas, convém considerar PNSes de plataforma cruzada, como mostrado na Figura 2. Em comparação com o diagrama da Figura 1, a nova arquitetura adiciona mais uma camada e oferece um único ponto de entrada para a programação.

Arquitetura Geral de um Sistema de Notificação por Push de Plataforma Cruzada
Figura 2 Arquitetura Geral de um Sistema de Notificação por Push de Plataforma Cruzada

O aplicativo móvel se registra no hub de notificação por push genérico e o back-end do aplicativo enfileira as mensagens no hub. Em seguida, o hub envia mensagens físicas à plataforma móvel específica usando a carga e o protocolo apropriados. Usando um desses sistemas de notificação móvel de plataforma cruzada, você pode usar uma única API para enviar mensagens por push a dispositivos Android, iOS e Windows Phone de uma só vez.

O Hub de Notificação do Azure é apenas um desses sistemas de notificação de plataforma cruzada. Vamos ver como isso funciona.

O Hub de Notificação do Azure

A primeira etapa para usar o Hub de Notificação do Azure é a configuração de um plano do Azure. O serviço é oferecido em três níveis, o menor dos quais é gratuito e define um limite para o número de dispositivos que podem ser acessados (500) e o máximo de notificações que você pode enviar (um milhão). Para obter mais informações, confira bit.ly/1Tbimew. Para começar, basta ter uma conta gratuita para criar um Hub de Notificação e namespace nele. Essas informações serão úteis mais tarde para estabelecer a conexão entre o back-end do aplicativo e a fila de mensagens dos dispositivos.

A parte mais complicada ao se usar notificações por push não é lidar com um hub de plataforma cruzada, mas atender aos requisitos de cada plataforma móvel que você deseja acessar. Por exemplo, para enviar atualizações a dispositivos iOS ou Android, primeiro você deve configurar totalmente os aplicativos com os respectivos PNSes nativos. Para obter mais informações, acesse bit.ly/1o15uv2. Como você deve saber, apenas aplicativos para iOS registrados podem receber notificações por push. Para registrar o aplicativo no serviço de Notificação por Push nativo da Apple, primeiro você deve obter um certificado da Apple que atenda ao propósito de identificar com exclusividade as notificações provenientes de seu aplicativo. Em vez disso, a mesma tarefa para Android requer uma chave de API que você obtém por meio da interface do Android Studio. Para aplicativos UWP, primeiro você deve se registar na Windows Store. Todas as etapas específicas da plataforma devem ser cumpridas para qualquer plataforma à qual você queira dar suporte. As informações de registro que você obtiver deverão ser inseridas no Hub de Notificação do Azure, que atuará em seu nome com relação aos PNSes nativos.

Registrar o Aplicativo no Hub

Digamos que você mantenha um arquivo de certificado .p12 e um perfil de provisionamento atualizado de seu aplicativo para iOS que está habilitado para receber notificações do sistema da Apple. Você já teria concluído quase tudo se não estivesse usando o Hub de Notificação do Azure. Você realmente deveria usar um sistema de hub intermediário?

A questão é que qualquer PNS específico de plataforma ainda deixa muito trabalho para que o desenvolvedor realize tarefas comumente solicitadas, como a difusão simples para todos os dispositivos conectados ou apenas para grupos específicos de usuários, como aqueles que utilizam o dispositivo em uma localidade específica. A difusão, em particular, não é uma tarefa trivial, pois pode gerar problemas de escalabilidade não triviais quando o número de dispositivos aumenta. Por isso, é um grande benefício ter uma infraestrutura escalonável no meio, que separa os serviços específicos da plataforma de núcleo do código que você escreve. No entanto, para usar o Hub de Notificação do Azure,você também precisa carregar o certificado .p12 da Apple e registrar o aplicativo de forma programática no Hub do Azure. Se você está usando o Xamarin.iOS para escrever o aplicativo para iOS, um excelente tutorial passo a passo está disponível em bit.ly/1KaySJ3.

O aplicativo móvel tem duas responsabilidades principais. Em primeiro lugar, ele precisa incorporar o código que assina o feed de notificações do Azure. Em segundo lugar, ele precisa incluir código para processar todas as notificações recebidas de alguma forma. Um aplicativo para iOS recebe notificações por push fisicamente do serviço da Apple e, portanto, precisa inscrevê-lo. Isso é feito por meio do método UIApplication.SharedApplication.RegisterForRemoteNotifications. Ao sair, esse método chama um método substituível na classe de representante de aplicativo chamada RegisteredForRemoteNotifications. Aqui, você inscreve o Hub do Azure. Esse método recebe o token de dispositivo do sistema operacional e o código apenas o encaminha para o Hub. O Hub do Azure é identificado pela cadeia de conexão e caminho, da seguinte forma:

var hub = new SBNotificationHub(connectionString, hubPath);
hub.RegisterNativeAsync(deviceToken, null);

Em seguida, quando uma notificação é realmente recebida, outro método substituível na classe de representante do aplicativo é invocado: ReceivedRemote­Notification. O método recebe do sistema operacional o conteúdo real da mensagem enviada por push na forma de um dicionário de cadeias de caracteres (possivelmente aninhado). A substituição do método é responsável por extrair a mensagem real e exibi-la por meio daquilo que funcionar para o aplicativo: notificação, som ou alerta.

Enfileirar Mensagens para o Hub do Azure

Todo o trabalho feito até agora é apenas metade do esforço. Resta descobrir como enviar mensagens ao Hub do Azure e, de lá, para os dispositivos conectados. Em outras palavras, você precisa ter um back-end de aplicativo que conheça os detalhes da conexão ao Hub e passe a mensagem ao usuário. Esse back-end de aplicativo pode ser qualquer tipo de aplicativo .NET, inclusive um aplicativo ASP.NET. Se você tem um motivo de negócios para que um aplicativo móvel receba notificações por push, algo no domínio de negócios está gerando mensagens relacionadas. Pode ser um gatilho de software para enviar uma mensagem ou a ação de um usuário administrador, como mostrado na Figura 3.

Um Back-end ASP.NET para Enviar Mensagens Específicas de uma Localidade a um Aplicativo para iOS e Android por meio do Hub do Azure
Figura 3 Um Back-end ASP.NET para Enviar Mensagens Específicas de uma Localidade a um Aplicativo para iOS e Android por meio do Hub do Azure

Para incorporar notificações por push a um back-end ASP.NET, basta ter o pacote Nuget NotificationHubs do Microsoft Azure. Além disso, o código é responsável pela construção da cadeia de conexão adequada. A cadeia de conexão contém informações sobre o ponto de extremidade da URL do Barramento de Serviço do Azure relacionado e um token criptografado. O ponto de extremidade do Barramento de Serviço contém o nome do namespace criado quando você configurou o serviço do Azure. É algo como sb://your-ns.servicebus.windows.net. O token criptografado é lido a partir da página de configuração do namespace sob o rótulo "Cadeia de Conexão". Veja o código necessário para criar uma instância do Hub válida:

var hub = NotificationHubClient.CreateClientFromConnectionString(
  connString, hubName);

A próxima etapa consiste em criar a carga adequada para cada uma das plataformas que você deseja acessar. A carga é uma cadeia de caracteres JSON que segue um padrão fixo. Você pode compilar a cadeia de caracteres JSON da maneira que preferir. No exemplo a seguir, $ é um espaço reservado para a mensagem real a ser enviada:

const string iosFormat = "{\"aps\":{\"alert\":\"$\"}}";
const string androidFormat = "{\"data\":{\"message\":\"$\"}}";
var iosAlert = iosFormat.Replace("$", actualMessage);
var androidAlert = androidFormat.Replace("$", actualMessage);

Depois que a carga é criada, enviá-la ao hub é tão fácil quanto o seguinte código:

var task1 = hub.SendAppleNativeNotificationAsync(iosAlert);
var outcome1 = task1.Result;
var task2 = hub.SendGcmNativeNotificationAsync(androidAlert);
var outcome2 = task2.Result;

As variáveis de resultado no trecho de código são instâncias do tipo NotificationOutcome e retornam informações detalhadas sobre o resultado da operação.

Enviar Mensagens com Base em Modelo

O exemplo de código anterior mostra apenas a maneira mais simples de enviar notificações por push, uma cadeia de caracteres simples de texto que será transmitida inalterada a todos os dispositivos conectados. Além disso, é necessário formatá-la para cada plataforma móvel de seu interesse. Um cenário muito mais comum é o envio de mensagens baseadas em modelo. Uma mensagem baseada em modelo é entregue ao Azure na forma de um dicionário de cadeias de caracteres e o Hub do Azure garante que ela seja entregue a qualquer plataforma móvel que a conta tenha configurado. A ideia-chave por trás das mensagens baseadas em modelo é que o aplicativo pretende usar um formato mais avançado do que o padrão. Por exemplo, vamos ver como enviar mensagens diferentes aos usuários em localidades diferentes:

var locale = "EN";
var template = String.Format("{{\"aps\":{{\"alert\":\"$(News_{0})\"}}}}", locale);

O exemplo mostra o modelo para registrar no Apple PNS qualquer mensagem baseada em modelo recebida chamada News_XX, em que XX são as duas letras iniciais de uma localidade. A vantagem dos modelos aqui é que o back-end do aplicativo pode enviar várias entradas em um único dicionário, mas cada dispositivo recebe apenas a mensagem para a qual foi registrado. Esse é apenas um dos serviços adicionais fornecidos por um hub intermediário, como o Hub de Notificação do Azure. Para enviar mensagens a uma localidade específica, você precisa do seguinte código:

var messages = new Dictionary<string, string>
{
  {"News_EN", "..."},
  {"News_ES", "..."},  {"News_PT", "..."},
  {"News_IT", "..."}
};var task = hub.SendTemplateNotificationAsync(messages);
var outcome = task.Result;

Com uma simples mensagem por push, você acessa dispositivos em diferentes plataformas com a garantia de que cada usuário verá apenas a notificação apropriada para a localidade que selecionou no telefone. Observe que esse é um recurso ligeiramente diferente da localização automática de mensagens, que está disponível, por exemplo, em dispositivos iOS. Em dispositivos iOS, de fato, você pode enviar mensagens com um espaço reservado que é mapeado para entradas no dicionário de cadeias de caracteres localizadas e o sistema operacional se encarrega de traduzir automaticamente a mensagem antes de emitir o alerta. Em vez disso, as mensagens de modelo são um recurso do Azure que permite enviar mensagens diferentes a grupos segmentados de usuários e decidir como segmentar esses grupos.

Mensagens Agendadas

Outro recurso interessante que você encontrará no Hub de Notificação do Azure são as mensagens agendadas. As mensagens agendadas são notificações entregues ao Azure, mas enviadas a dispositivos conectados somente em determinado momento. Para enviar notificações agendadas, você usa apenas uma API ligeiramente diferente:

var notification = new TemplateNotification(messages);
var task = hub.ScheduleNotificationAsync(notification, new DateTime(...));
var outcome = task.Result;

É importante notar que as notificações agendadas exigem uma assinatura de Nível Padrão e não estão disponíveis na assinatura de teste gratuito.

Seja um Bom Cidadão

Além dos meros aspectos técnicos de como se registrar e enviar notificações por push por meio do Hub do Azure, a dificuldade real das notificações por push é usá-las no contexto de uma comunicação bem-sucedida com o usuário.

Você não quer incomodar o usuário dia e noite com notificações meramente informativas. Como se trata de uma notificação por "push", convém garantir que haja um interesse real por parte do usuário que está sendo contatado. Nesse aspecto, os grupos segmentados de usuários são um ótimo recurso para se usar. O tamanho da mensagem também é importante. Sugiro que você mantenha as mensagens com tamanhos próximos ao de um tweet. Até o iOS 8, por exemplo, o tamanho máximo das notificações por push era de 256 bytes e aumentou para 2 K em sistemas mais recentes. O limite é de 4 K no Android. Por último, mas não menos importante, verifique se o sistema operacional que você está direcionando facilita a recusa de todo o recurso. Isso se aplica principalmente à maioria dos sistemas operacionais mais recentes, mas é melhor verificar.


Dino Espositoé o autor de “Microsoft .NET: Architecting Applications for the Enterprise” (Microsoft Press, 2014) e de “Modern Web Applications” (Microsoft Press, 2016). Evangelista técnico das plataformas .NET e Android no JetBrains e palestrante frequente em eventos do setor no mundo todo, Esposito compartilha sua visão de software em software2cents@wordpress.com e, no Twitter, em @despos.

Agradecemos ao seguinte especialista técnico da Microsoft pela revisão deste artigo: Jon Arne Saeteras