Tutorial: Enviar notificações por push para especificar os dispositivos iOS usando Hubs de Notificação do Azure

Visão geral

Este tutorial mostra como usar os Hubs de Notificação do Azure para difundir notificações de últimas notícias a um aplicativo iOS. Ao concluir, você poderá se registrar nas categorias de últimas notícias que desejar e receber notificações por push apenas para essas categorias. Esse cenário é um padrão comum para muitos aplicativos nos quais as notificações precisam ser enviadas para grupos de usuários que tenham anteriormente expressado seu interesse por elas, por exemplo, leitor de RSS, aplicativos para fãs de música, etc.

Os cenários de transmissão são habilitados por meio da inclusão de uma ou mais marcas durante a criação de um registro no hub de notificação. Quando as notificações são enviadas para uma marcação, os dispositivos que foram registrados para a marcação recebem a notificação. Como os rótulos são simplesmente cadeias de caracteres, eles não precisam ser provisionados com antecedência. Para obter mais informações sobre marcações, consulte Roteamento e expressões de marcação dos Hubs de Notificação.

Neste tutorial, você deve executar as seguintes etapas:

  • Adicionar a seleção de uma categoria ao aplicativo
  • Enviar notificações marcadas
  • Enviar notificações do dispositivo
  • Executar o aplicativo e gerar notificações

Pré-requisitos

Este tópico se baseia no aplicativo que você criou no Tutorial: Notificações por push para aplicativos iOS usando Hubs de Notificação do Azure. Antes de iniciar este tutorial, você já deve ter concluído Tutorial: Notificações por push para aplicativos iOS usando Hubs de Notificação do Azure.

Adicionar a seleção de categorias ao aplicativo

A primeira etapa é adicionar os elementos da interface do usuário a seu storyboard existente que permite que o usuário selecione as categorias a serem registradas. As categorias selecionadas por um usuário são armazenadas no dispositivo. Quando o aplicativo é iniciado, o registro do dispositivo é criado no seu hub de notificação com as categorias selecionadas como rótulos.

  1. No MainStoryboard_iPhone.storyboard, adicione os seguintes componentes da biblioteca de objetos:

    • Um rótulo com o texto "Breaking News",

    • Rótulos com os textos das categorias "World", "Politics", "Business", "Technology", "Science", "Sports",

    • Seis comutadores, um por categoria, defina cada comutador Estado para estar Desligado por padrão.

    • Um botão rotulado "Assinar"

      O storyboard deve ter a seguinte aparência:

      Interface Builder do Xcode

  2. No editor do assistente, crie saídas para todos os comutadores e chame-os de "WorldSwitch", "PoliticsSwitch", "BusinessSwitch", "TechnologySwitch", "ScienceSwitch", "SportsSwitch"

  3. Criar uma Ação para o botão chamado subscribe; seu ViewController.h deve conter o código a seguir:

    @property (weak, nonatomic) IBOutlet UISwitch *WorldSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *PoliticsSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *BusinessSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *TechnologySwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *ScienceSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *SportsSwitch;
    
    - (IBAction)subscribe:(id)sender;
    
  4. Criar um novo Cocoa Touch Class chamado Notifications. Copie o código a seguir na seção da interface do arquivo Notifications.h:

    @property NSData* deviceToken;
    
    - (id)initWithConnectionString:(NSString*)listenConnectionString HubName:(NSString*)hubName;
    
    - (void)storeCategoriesAndSubscribeWithCategories:(NSArray*)categories
                completion:(void (^)(NSError* error))completion;
    
    - (NSSet*)retrieveCategories;
    
    - (void)subscribeWithCategories:(NSSet*)categories completion:(void (^)(NSError *))completion;
    
  5. Adicione a seguinte diretiva de importação a Notifications.m:

    #import <WindowsAzureMessaging/WindowsAzureMessaging.h>
    
  6. Copie o código a seguir na seção de implementação do arquivo Notifications.m.

    SBNotificationHub* hub;
    
    - (id)initWithConnectionString:(NSString*)listenConnectionString HubName:(NSString*)hubName{
    
        hub = [[SBNotificationHub alloc] initWithConnectionString:listenConnectionString
                                    notificationHubPath:hubName];
    
        return self;
    }
    
    - (void)storeCategoriesAndSubscribeWithCategories:(NSSet *)categories completion:(void (^)(NSError *))completion {
        NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
        [defaults setValue:[categories allObjects] forKey:@"BreakingNewsCategories"];
    
        [self subscribeWithCategories:categories completion:completion];
    }
    
    - (NSSet*)retrieveCategories {
        NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    
        NSArray* categories = [defaults stringArrayForKey:@"BreakingNewsCategories"];
    
        if (!categories) return [[NSSet alloc] init];
        return [[NSSet alloc] initWithArray:categories];
    }
    
    - (void)subscribeWithCategories:(NSSet *)categories completion:(void (^)(NSError *))completion
    {
        NSString* templateBodyAPNS = @"{\"aps\":{\"alert\":\"$(messageParam)\"}}";
    
        [hub registerTemplateWithDeviceToken:self.deviceToken name:@"simpleAPNSTemplate" 
            jsonBodyTemplate:templateBodyAPNS expiryTemplate:@"0" tags:categories completion:completion];
    }
    

    Essa classe usa o armazenamento local para armazenar as categorias de notícias que esse dispositivo precisa receber. Além disso, ela contém um método para se registrar nessas categorias usando um registro de Modelo .

  7. No arquivo AppDelegate.h, adicione uma instrução de importação a Notifications.h e adicione uma propriedade a uma instância da classe Notifications:

    #import "Notifications.h"
    
    @property (nonatomic) Notifications* notifications;
    
  8. No método didFinishLaunchingWithOptions em AppDelegate.m, adicione o código para inicializar a instância de notificações no início do método.
    HUBNAME e HUBLISTENACCESS (definidos em hubinfo.h) já devem ter os espaços reservados <hub name> e <connection string with listen access>substituídos pelo nome de seu hub de notificação e a cadeia de conexão para DefaultListenSharedAccessSignature obtidos anteriormente

    self.notifications = [[Notifications alloc] initWithConnectionString:HUBLISTENACCESS HubName:HUBNAME];
    

    Observação

    Como as credenciais que são distribuídas com um aplicativo cliente não são geralmente seguras, você só deve distribuir a chave para acesso de escuta com o aplicativo cliente. O acesso de escuta permite que seu aplicativo se registre para receber notificações, mas os registros existentes não podem ser modificados e as notificações não podem ser enviadas. A chave de acesso completo é usada em um serviço back-end protegido para enviar notificações e alterar os registros existentes.

  9. No método didRegisterForRemoteNotificationsWithDeviceToken em AppDelegate.m, substitua o código no método pelo seguinte código ao passar o token do dispositivo para a classe notifications. A classe notifications executa o registro para notificações nas categorias. Se o usuário altera as seleções de categoria, chame o método subscribeWithCategories em resposta ao botão assinar para atualizá-los.

    Observação

    Como o token do dispositivo atribuído pelo APNS (Apple Push Notification Service) pode ser alterado a qualquer momento, você deve se registrar para receber notificações com frequência para evitar falhas de notificação. Este exemplo registra a notificação a cada vez que o aplicativo é iniciado. Para os aplicativos que são executados com frequência, mais de uma vez por dia, é possível ignorar o registro para preservar a largura de banda se tiver passado menos de um dia desde o registro anterior.

    self.notifications.deviceToken = deviceToken;
    
    // Retrieves the categories from local storage and requests a registration for these categories
    // each time the app starts and performs a registration.
    
    NSSet* categories = [self.notifications retrieveCategories];
    [self.notifications subscribeWithCategories:categories completion:^(NSError* error) {
        if (error != nil) {
            NSLog(@"Error registering for notifications: %@", error);
        }
    }];
    

    Neste ponto, não deve haver nenhum outro código no método didRegisterForRemoteNotificationsWithDeviceToken.

  10. Os métodos a seguir já devem estar presentes no AppDelegate.m com a conclusão do tutorial Introdução aos Hubs de Notificação. Caso contrário, adicione-os.

    - (void)MessageBox:(NSString *)title message:(NSString *)messageText
    {
    
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:messageText delegate:self
            cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert show];
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:
       (NSDictionary *)userInfo {
       NSLog(@"%@", userInfo);
       [self MessageBox:@"Notification" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"]];
     }
    

    Este método trata as notificações recebidas quando o aplicativo está em execução exibindo um simples UIAlert.

  11. Em ViewController.m, adicione uma instrução import para AppDelegate.h e copie o código a seguir para o método subscribe gerado por XCode. Esse código atualiza o registro de notificação para usar as novas marcas de categoria que o usuário escolheu na interface do usuário.

    #import "Notifications.h"
    
    NSMutableArray* categories = [[NSMutableArray alloc] init];
    
    if (self.WorldSwitch.isOn) [categories addObject:@"World"];
    if (self.PoliticsSwitch.isOn) [categories addObject:@"Politics"];
    if (self.BusinessSwitch.isOn) [categories addObject:@"Business"];
    if (self.TechnologySwitch.isOn) [categories addObject:@"Technology"];
    if (self.ScienceSwitch.isOn) [categories addObject:@"Science"];
    if (self.SportsSwitch.isOn) [categories addObject:@"Sports"];
    
    Notifications* notifications = [(AppDelegate*)[[UIApplication sharedApplication]delegate] notifications];
    
    [notifications storeCategoriesAndSubscribeWithCategories:categories completion: ^(NSError* error) {
        if (!error) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:"Notification" message:"Subscribed" delegate:self
            cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];
        } else {
            NSLog(@"Error subscribing: %@", error);
        }
    }];
    

    Esse método cria uma NSMutableArrayde categorias e usa a classe Notifications para armazenar a lista no armazenamento local e registra as marcas correspondentes com o hub de notificação. Quando as categorias são alteradas, o registro é recriado com as novas categorias.

  12. Em ViewController.m, adicione o seguinte código no método viewDidLoad para definir a interface do usuário com base em categorias salvas anteriormente.

    // This updates the UI on startup based on the status of previously saved categories.
    
    Notifications* notifications = [(AppDelegate*)[[UIApplication sharedApplication]delegate] notifications];
    
    NSSet* categories = [notifications retrieveCategories];
    
    if ([categories containsObject:@"World"]) self.WorldSwitch.on = true;
    if ([categories containsObject:@"Politics"]) self.PoliticsSwitch.on = true;
    if ([categories containsObject:@"Business"]) self.BusinessSwitch.on = true;
    if ([categories containsObject:@"Technology"]) self.TechnologySwitch.on = true;
    if ([categories containsObject:@"Science"]) self.ScienceSwitch.on = true;
    if ([categories containsObject:@"Sports"]) self.SportsSwitch.on = true;
    

Agora, o aplicativo pode armazenar um conjunto de categorias no armazenamento local do dispositivo usado para se registrar no hub de notificação sempre que o aplicativo é iniciado. O usuário pode alterar a seleção de categorias no runtime e clicar no método subscribe para atualizar o registro do dispositivo. Em seguida, você atualiza o aplicativo para enviar as notificações de últimas notícias diretamente nele.

(opcional) Enviar notificações marcadas

Se você não tiver acesso ao Visual Studio, você pode pular para a próxima seção e enviar notificações do próprio aplicativo. Você também pode enviar a notificação de modelo apropriada do Portal do Azure usando a guia depurar hub de notificação.

Nesta seção, você envia as últimas notícias como notificações de modelo marcadas, de um aplicativo de console do .NET.

  1. No Visual Studio, crie um novo aplicativo de console em Visual C#:

    1. No menu, selecione Arquivo>Novo>Projeto.
    2. Em Criar um projeto, selecione Aplicativo de Console (.NET Framework) para C# na lista de modelos e selecione Avançar.
    3. Insira um nome do aplicativo.
    4. Para Solução, escolha Adicionar à solução e selecione Criar para criar o projeto.
  2. Selecione Ferramentas>Gerenciador de Pacotes NuGet>Console do Gerenciador do NuGet e, em seguida, na janela do console, execute o seguinte comando:

    Install-Package Microsoft.Azure.NotificationHubs
    

    Essa ação adiciona uma referência ao SDK dos Hubs de Notificação do Azure usando o pacote NuGet Microsoft.Azure.NotificationHubs.

  3. Abra o arquivo Program.cs e adicione a seguinte instrução using:

    using Microsoft.Azure.NotificationHubs;
    
  4. Na classe Program , adicione o seguinte método ou substitua-o, se ele já existir:

    private static async void SendTemplateNotificationAsync()
    {
        // Define the notification hub.
        NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString("<connection string with full access>", "<hub name>");
    
        // Apple requires the apns-push-type header for all requests
        var headers = new Dictionary<string, string> {{"apns-push-type", "alert"}};
    
        // Create an array of breaking news categories.
        var categories = new string[] { "World", "Politics", "Business", "Technology", "Science", "Sports"};
    
        // Send the notification as a template notification. All template registrations that contain
        // "messageParam" and the proper tags will receive the notifications.
        // This includes APNS, GCM/FCM, WNS, and MPNS template registrations.
    
        Dictionary<string, string> templateParams = new Dictionary<string, string>();
    
        foreach (var category in categories)
        {
            templateParams["messageParam"] = "Breaking " + category + " News!";
            await hub.SendTemplateNotificationAsync(templateParams, category);
        }
    }
    

    Esse código envia uma notificação de modelo para cada uma das seis marcas na matriz de cadeia de caracteres. O uso de marcas garante que os dispositivos recebam notificações somente para as categorias de marcas.

  5. No código anterior, substitua os espaços reservados <hub name> e <connection string with full access> pelo nome do hub de notificação e a cadeia de conexão por DefaultFullSharedAccessSignature do painel do hub de notificação.

  6. No método Main(), adicione as seguintes linhas:

     SendTemplateNotificationAsync();
     Console.ReadLine();
    
  7. Compile o aplicativo de console.

(Opcional) Enviar notificações do dispositivo

Normalmente, as notificações podem ser enviadas por um serviço de back-end, mas você pode enviar notificações de últimas notícias diretamente do aplicativo. Para isso, atualize o método SendNotificationRESTAPI que você definiu no tutorial Introdução aos Hubs de Notificação.

  1. No ViewController.m, atualize o método SendNotificationRESTAPI como mostrado a seguir, para que ele aceite um parâmetro para a marca de categoria e envie a notificação de modelo adequada.

    - (void)SendNotificationRESTAPI:(NSString*)categoryTag
    {
        NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration
                                    defaultSessionConfiguration] delegate:nil delegateQueue:nil];
    
        NSString *json;
    
        // Construct the messages REST endpoint
        NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@/messages/%@", HubEndpoint,
                                            HUBNAME, API_VERSION]];
    
        // Generated the token to be used in the authorization header.
        NSString* authorizationToken = [self generateSasToken:[url absoluteString]];
    
        //Create the request to add the template notification message to the hub
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        [request setHTTPMethod:@"POST"];
    
        // Add the category as a tag
        [request setValue:categoryTag forHTTPHeaderField:@"ServiceBusNotification-Tags"];
    
        // Template notification
        json = [NSString stringWithFormat:@"{\"messageParam\":\"Breaking %@ News : %@\"}",
                categoryTag, self.notificationMessage.text];
    
        // Signify template notification format
        [request setValue:@"template" forHTTPHeaderField:@"ServiceBusNotification-Format"];
    
        // JSON Content-Type
        [request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    
        //Authenticate the notification message POST request with the SaS token
        [request setValue:authorizationToken forHTTPHeaderField:@"Authorization"];
    
        //Add the notification message body
        [request setHTTPBody:[json dataUsingEncoding:NSUTF8StringEncoding]];
    
        // Send the REST request
        NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request
                    completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
            {
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
                if (error || httpResponse.statusCode != 200)
                {
                    NSLog(@"\nError status: %d\nError: %@", httpResponse.statusCode, error);
                }
                if (data != NULL)
                {
                    //xmlParser = [[NSXMLParser alloc] initWithData:data];
                    //[xmlParser setDelegate:self];
                    //[xmlParser parse];
                }
            }];
    
        [dataTask resume];
    }
    
  2. Em ViewController.m, atualize a ação Send Notification conforme mostrado no código a seguir. Para que ele envie as notificações usando cada marca individualmente e para várias plataformas.

    - (IBAction)SendNotificationMessage:(id)sender
    {
        self.sendResults.text = @"";
    
        NSArray* categories = [NSArray arrayWithObjects: @"World", @"Politics", @"Business",
                                @"Technology", @"Science", @"Sports", nil];
    
        // Lets send the message as breaking news for each category to WNS, FCM, and APNS
        // using a template.
        for(NSString* category in categories)
        {
            [self SendNotificationRESTAPI:category];
        }
    }
    
  3. Recrie seu projeto e verifique se não há nenhum erro de compilação.

Executar o aplicativo e gerar notificações

  1. Pressione o botão Executar para compilar o projeto e iniciar o aplicativo. Selecione algumas opções de notícias recentes para assinar e pressione o botão Assinar . Você deve ver uma caixa de diálogo indicando que assinou as notificações.

    Notificação de exemplo no iOS

    Quando você escolher Subscribe, o aplicativo converterá as categorias selecionadas em marcas e solicitará um novo registro de dispositivo para as marcas selecionadas no hub de notificação.

  2. Digite uma mensagem a ser enviada como últimas notícias e pressione o botão Enviar Notificação . Como alternativa, execute o aplicativo de console do .NET para gerar notificações.

    Alterar preferências de notificação de email no iOS

  3. Cada dispositivo que assinou as últimas notícias recebe as notificações de últimas notícias que você acabou de enviar.

Próximas etapas

Neste tutorial, você enviou notificações de notícias a dispositivos iOS específicos que foram registrados para as categorias. Para saber como enviar notificações localizadas por push, avance para o seguinte tutorial: