Tutorial: Enviar notificações push para dispositivos iOS específicos com hubs de notificação do Azure

Descrição Geral

Este tutorial mostra-lhe como utilizar os Notification Hubs do Azure para difundir notificações de notícias de última hora para uma aplicação iOS. Quando terminar, pode registar-se nas categorias de notícias de última hora que lhe interessam e receber apenas notificações push para essas categorias. Este é um cenário com um padrão comum para muitas aplicações em que as notificações têm de ser enviadas para grupos de utilizadores que mostraram anteriormente interesse nas mesmas, por exemplo, leitor de RSS, aplicações para fãs de música, etc.

Os cenários de transmissão são ativados ao incluir uma ou mais etiquetas durante a criação de um registo no Hub de Notificação. Quando as notificações são enviadas para uma etiqueta, os dispositivos que se registaram na etiqueta recebem a notificação. Como as etiquetas são simples cadeias, não têm de ser aprovisionadas com antecedência. Para obter mais informações sobre etiquetas, consulte Encaminhamento de Hubs de Notificação e Expressões de Etiqueta.

Neste tutorial, siga os seguintes passos:

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

Pré-requisitos

Este tópico baseia-se na aplicação que criou no Tutorial: Enviar notificações push para aplicações iOS com os Hubs de Notificação do Azure. Antes de iniciar este tutorial, tem de ter concluído o Tutorial: Enviar notificações push para aplicações iOS com os Hubs de Notificação do Azure.

Adicionar a seleção de categorias à aplicação

O primeiro passo é adicionar os elementos da IU ao guião gráfico existente que permitem ao utilizador selecionar categorias para se registar. As categorias selecionadas por um utilizador são armazenadas no dispositivo. Quando a aplicação é iniciada, é criado um registo do dispositivo no seu hub de notificação com as categorias selecionadas como etiquetas.

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

    • Uma etiqueta com texto "Notícias de Última Hora",

    • Etiquetas com textos de categoria "World", "Politics", "Business", "Technology", "Science", "Sports",

    • Seis comutadores, um por categoria, definem cada estado do comutador como Desativado por predefinição .

    • Um botão com o nome "Subscrever"

      O seu guião gráfico deve ter o seguinte aspeto:

      Construtor de interfaces Xcode

  2. No editor assistente, crie pontos de venda para todos os comutadores e chame-lhes "WorldSwitch", "PoliticsSwitch", "BusinessSwitch", "TechnologySwitch", "ScienceSwitch", "SportsSwitch"

  3. Crie uma Ação para o botão denominado subscribe; ViewController.h deve conter o seguinte código:

    @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. Crie uma nova Classe Cocoa Touch chamada Notifications. Copie o seguinte código na secção interface do ficheiro 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 seguinte código na secção de implementação do ficheiro 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];
    }
    

    Esta classe utiliza o armazenamento local para armazenar e obter as categorias de notícias que este dispositivo recebe. Além disso, contém um método para se registar nestas categorias com um registo de Modelo .

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

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

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

    Nota

    Uma vez que, de um modo geral, as credenciais que são distribuídas com uma aplicação cliente não são seguras, só deve distribuir a chave para acesso de escuta com a sua aplicação cliente. O acesso de escuta permite que a sua aplicação seja registada para receber notificações, mas não é possível modificar os registos existentes nem enviar notificações. A chave de acesso total é utilizada num serviço de back-end protegido para o envio de notificações e a alteração de registos existentes.

  9. didRegisterForRemoteNotificationsWithDeviceToken No método em AppDelegate.m, substitua o código no método pelo seguinte código para transmitir o token do dispositivo para a notifications classe . A notifications classe efetua o registo de notificações com as categorias. Se o utilizador alterar as seleções de categorias, chame o subscribeWithCategories método em resposta ao botão subscrever para atualizá-los.

    Nota

    Uma vez que o token de dispositivo atribuído pelo Serviço Apple Push Notification (APNS) pode ser alterado em qualquer altura, deve registar-se para receber notificações com frequência para evitar falhas de notificação. Este exemplo regista-se em notificações sempre que a aplicação é iniciada. Relativamente às aplicações executadas com frequência, ou seja, mais do que uma vez por dia, pode provavelmente ignorar o registo de modo a preservar a largura de banda caso tenha passado menos de um dia desde o registo 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 momento, não deve haver outro código no didRegisterForRemoteNotificationsWithDeviceToken método .

  10. Os seguintes métodos já devem estar presentes na AppDelegate.m 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 processa as notificações recebidas quando a aplicação está em execução ao apresentar um UIAlert simples.

  11. No ViewController.m, adicione uma instrução import para AppDelegate.h e copie o seguinte código para o método gerado pelo subscribe XCode. Este código atualiza o registo de notificação para utilizar as novas etiquetas de categoria que o utilizador escolheu na interface de utilizador.

    #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);
        }
    }];
    

    Este método cria uma NSMutableArray das categorias e utiliza a Notifications classe para armazenar a lista no armazenamento local e regista as etiquetas correspondentes no hub de notificação. Quando as categorias são alteradas, o registo é recriado com as novas categorias.

  12. No ViewController.m, adicione o seguinte código no viewDidLoad método para definir a interface de utilizador com base nas categorias guardadas 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;
    

A aplicação pode agora armazenar um conjunto de categorias no armazenamento local do dispositivo utilizado para se registar no hub de notificação sempre que a aplicação é iniciada. O utilizador pode alterar a seleção de categorias no runtime e clicar no subscribe método para atualizar o registo do dispositivo. Em seguida, atualize a aplicação para enviar as notificações de notícias de última hora diretamente na própria aplicação.

(opcional) Enviar notificações com etiquetas

Se não tiver acesso ao Visual Studio, pode avançar para a secção seguinte e enviar notificações a partir da própria aplicação. Também pode enviar a notificação de modelo adequada a partir do portal do Azure através do separador de depuração do hub de notificação.

Nesta secção, irá enviar notícias de última hora como notificações de modelo etiquetadas a partir da aplicação de consola .NET.

  1. No Visual Studio, crie uma nova aplicação da consola Visual C#

    1. No menu, selecione Ficheiro>Novo>Projeto.
    2. Em Criar um novo projeto, selecione Aplicação de Consola (.NET Framework) para C# na lista de modelos e selecione Seguinte.
    3. Introduza um nome para a aplicação.
    4. Em Solução, selecione Adicionar à solução e selecione Criar para criar o projeto.
  2. Selecione Ferramentas>Consola do Gestor dePacotes NuGet Gestor> de Pacotes e, em seguida, na janela da consola, execute o seguinte comando:

    Install-Package Microsoft.Azure.NotificationHubs
    

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

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

    using Microsoft.Azure.NotificationHubs;
    
  4. Na classe Program, adicione o seguinte método ou substitua-o se 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);
        }
    }
    

    Este código envia uma notificação de modelo para cada uma das seis etiquetas na matriz de cadeias. A utilização de etiquetas assegura que os dispositivos recebem notificações apenas para as categorias registadas.

  5. No código anterior, substitua os marcadores de posição <hub name> e <connection string with full access> pelo nome do seu hub de notificação e pela cadeia de ligação para DefaultFullSharedAccessSignature do dashboard do seu hub de notificação.

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

     SendTemplateNotificationAsync();
     Console.ReadLine();
    
  7. Crie a aplicação de consola.

(opcional) Enviar notificações a partir do dispositivo

Normalmente, as notificações seriam enviadas por um serviço de back-end, mas pode enviar notificações de notícias de última hora diretamente a partir da aplicação. Para tal, atualize o SendNotificationRESTAPI método que definiu no tutorial Introdução aos Hubs de Notificação .

  1. No ViewController.m, atualize o SendNotificationRESTAPI método da seguinte forma para que aceite um parâmetro para a etiqueta 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. No ViewController.m, atualize a ação Send Notification conforme mostrado no código que se segue. Assim, envia as notificações com cada etiqueta individualmente e envia 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 o projeto e certifique-se de que não tem erros de compilação.

Executar a aplicação e gerar notificações

  1. Prima o botão Executar para compilar o projeto e iniciar a aplicação. Selecione algumas opções de notícias de última hora para subscrever e, em seguida, prima o botão Subscrever . Deverá ver uma caixa de diálogo a indicar que as notificações foram subscritas.

    Notificação de exemplo no iOS

    Quando seleciona Subscrever, a aplicação converte as categorias selecionadas em etiquetas e pede um novo registo de dispositivo para as etiquetas selecionadas no hub de notificação.

  2. Introduza uma mensagem a enviar como notícias de última hora e, em seguida, prima o botão Enviar Notificação . Em alternativa, execute a aplicação de consola .NET para gerar notificações.

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

  3. Cada dispositivo subscrito a notícias de última hora recebe as notificações de última hora que acabou de enviar.

Passos seguintes

Neste tutorial, enviou notificações de difusão para dispositivos iOS específicos que se registaram nas categorias. Para saber como emitir notificações localizadas, avance para o tutorial seguinte:

Push localized notifications (Enviar notificações localizadas)