Tutorial: Notificações push para utilizadores específicos com os Hubs de notificação do AzureTutorial: Push notifications to specific users using Azure Notification Hubs

Este tutorial mostra-lhe como utilizar os Hubs de Notificação do Azure para enviar notificações push para um utilizador específico da aplicação num dispositivo específico.This tutorial shows you how to use Azure Notification Hubs to send push notifications to a specific app user on a specific device. Um back-end de ASP.NET WebAPI é utilizado para autenticar clientes e gerar notificações, conforme mostrado no tópico de documentação de orientação registar a partir do seu back-end de aplicação.An ASP.NET WebAPI backend is used to authenticate clients and to generate notifications, as shown in the guidance topic Registering from your app backend.

Neste tutorial, siga os passos seguintes:In this tutorial, you take the following steps:

  • Criar o Projeto WebAPICreate the WebAPI project
  • Autenticar clientes no back-end de WebAPIAuthenticate clients to the WebAPI backend
  • Utilizar o back-end de WebAPI para registar notificaçõesRegister for notifications by using the WebAPI backend
  • Enviar notificações a partir do back-end de WebAPISend notifications from the WebAPI backend
  • Publicar o back-end de WebAPI novoPublish the new WebAPI backend
  • Modificar as suas aplicações iOSModify your iOS app
  • Testar a aplicaçãoTest the application

Pré-requisitosPrerequisites

Este tutorial pressupõe que já criou e configurou o notification hub conforme descrito em introdução aos Hubs de notificação (iOS).This tutorial assumes that you have created and configured your notification hub as described in Getting Started with Notification Hubs (iOS). Este tutorial também é o pré-requisito para o Secure Push (iOS) tutorial.This tutorial is also the prerequisite to the Secure Push (iOS) tutorial. Se pretender utilizar aplicações móveis que o seu serviço de back-end, consulte a Mobile Apps introdução ao Push.If you want to use Mobile Apps as your backend service, see the Mobile Apps Get Started with Push.

Criar o projeto WebAPICreate the WebAPI project

As secções seguintes abordam a criação de um novo back-end de ASP.NET WebAPI.The following sections discuss the creation of a new ASP.NET WebAPI backend. Este processo tem três objetivos principais:This process has three main purposes:

  • Autenticar clientes: Você adiciona um manipulador de mensagens para autenticar solicitações de cliente e associar o usuário à solicitação.Authenticate clients: You add a message handler to authenticate client requests and associate the user with the request.
  • Registre-se para receber notificações usando o back-end WebAPI: Você adiciona um controlador para lidar com novos registros para um dispositivo cliente receber notificações.Register for notifications by using the WebAPI backend: You add a controller to handle new registrations for a client device to receive notifications. O nome de utilizador autenticado é adicionado automaticamente ao registo como uma etiqueta.The authenticated username is automatically added to the registration as a tag.
  • Enviar notificações aos clientes: Você adiciona um controlador para fornecer uma maneira para os usuários dispararem um envio por push seguro para dispositivos e clientes associados à marca.Send notifications to clients: You add a controller to provide a way for users to trigger a secure push to devices and clients associated with the tag.

Crie o novo back-end de ASP.NET WebAPI através das seguintes ações:Create the new ASP.NET WebAPI backend by doing the following actions:

Importante

Se estiver a utilizar o Visual Studio 2015 ou anterior, antes de começar este tutorial, certifique-se que instalou a versão mais recente do Gestor de Pacotes de NuGet para o Visual Studio.If you are using Visual Studio 2015 or earlier, before starting this tutorial, ensure that you have installed the latest version of NuGet Package Manager for Visual Studio.

Para confirmar, inicie o Visual Studio.To check, start Visual Studio. No menu Ferramentas, selecione Extensões e Atualizações.On the Tools menu, select Extensions and Updates. Procure o Gestor de Pacotes de NuGet na sua versão do Visual Studio e verifique se tem a versão mais recente.Search for NuGet Package Manager in your version of Visual Studio, and make sure you have the latest version. Se a sua versão não for a versão mais recente, desinstale-a e, em seguida, reinstale o Gestor de Pacotes de NuGet.If your version is not the latest version, uninstall it, and then reinstall the NuGet Package Manager.

Nota

Verifique que tem instalado o Azure SDK para Visual Studio para implementação de Website.Make sure you have installed the Visual Studio Azure SDK for website deployment.

  1. Inicie o Visual Studio ou o Visual Studio Express.Start Visual Studio or Visual Studio Express.

  2. Selecione Explorador de Servidores e inicie sessão na sua conta do Azure.Select Server Explorer, and sign in to your Azure account. Para criar os recursos do site na sua conta, tem de ter sessão iniciada.To create the web site resources on your account, you must be signed in.

  3. No Visual Studio, clique com o botão direito do rato na solução Visual Studio, aponte para Adicionar e clique em Novo Projeto.In Visual Studio, right-click Visual Studio solution, point to Add, and click New Project.

  4. Expanda Visual C# , selecione Web e clique em Aplicação Web ASP.NET.Expand Visual C#, select Web, and click ASP.NET Web Application.

  5. Na caixa Nome, escreva AppBackend e selecione OK.In the Name box, type AppBackend, and then select OK.

    A janela Novo Projeto

  6. Na janela Novo Projeto ASP.NET, selecione a caixa de verificação API Web e, em seguida, selecione OK.In the New ASP.NET Project window, select the Web API check box, and then select OK.

    A janela Novo Projeto ASP.NET

  7. Na janela Configurar Aplicação Web do Microsoft Azure, selecione uma subscrição e, em seguida, na lista Plano do Serviço de Aplicações, efetue uma das seguintes ações:In the Configure Microsoft Azure Web App window, select a subscription and then, in the App Service plan list, do either of the following actions:

    • Selecione um plano do serviço de aplicações que já tenha criado.Select an app service plan that you've already created.
    • Selecione Criar um novo plano do serviço de aplicações e, em seguida, crie um.Select Create a new app service plan, and then create one.

    Não precisa de uma base de dados para este tutorial.You do not need a database for this tutorial. Depois de selecionar o seu plano do serviço de aplicações, selecione OK para criar o projeto.After you have selected your app service plan, select OK to create the project.

    A janela Configurar Aplicação Web do Microsoft Azure

    Se você não vir esta página para configurar o plano do serviço de aplicativo, continue com o tutorial.If you don't see this page for configure app service plan, continue with the tutorial. Você pode configurá-lo enquanto publica o aplicativo mais tarde.You can configure it while publishing the app later.

Autenticar clientes no back-end de WebAPIAuthenticate clients to the WebAPI backend

Nesta secção, crie uma nova classe de processadores de mensagens com o nome AuthenticationTestHandler para o back-end novo.In this section, you create a new message-handler class named AuthenticationTestHandler for the new backend. Esta classe é derivada de DelegatingHandler e adicionada como um processador de mensagens, para processar todos os pedidos enviados para o back-end.This class is derived from DelegatingHandler and added as a message handler so that it can process all requests that come into the backend.

  1. No Explorador de Soluções, clique com o botão direito do rato no projeto AppBackend, selecione Adicionar e, em seguida, selecione Classe.In Solution Explorer, right-click the AppBackend project, select Add, and then select Class.

  2. Dê o nome AuthenticationTestHandler.cs à classe e selecione Adicionar para gerar a classe.Name the new class AuthenticationTestHandler.cs, and then select Add to generate the class. Esta classe autentica utilizadores com a Autenticação Básica, para simplicidade.This class authenticates users by using Basic Authentication for simplicity. A sua aplicação pode utilizar qualquer esquema de autenticação.Your app can use any authentication scheme.

  3. No AuthenticationTestHandler.cs, adicione as instruções using seguintes:In AuthenticationTestHandler.cs, add the following using statements:

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. No AuthenticationTestHandler.cs, substitua a definição de classe AuthenticationTestHandler pelo seguinte código:In AuthenticationTestHandler.cs, replace the AuthenticationTestHandler class definition with the following code:

    O processador autoriza o pedido quando se verificarem as três condições seguintes:The handler authorizes the request when the following three conditions are true:

    • O pedido inclui o cabeçalho Autorização.The request includes an Authorization header.
    • O pedido utiliza a autenticação básica.The request uses basic authentication.
    • A cadeia de nome de utilizador e a cadeia de palavra-passe são a mesma cadeia.The user name string and the password string are the same string.

    Caso contrário, o pedido é rejeitado.Otherwise, the request is rejected. Esta autenticação não é uma verdadeira abordagem de autenticação e autorização.This authentication is not a true authentication and authorization approach. É apenas um exemplo simples para este tutorial.It is only a simple example for this tutorial.

    Se AuthenticationTestHandler autenticar e autorizar a mensagem do pedido, o utilizador de autenticação básica é anexado ao pedido atual em HttpContext.If the request message is authenticated and authorized by AuthenticationTestHandler, the basic authentication user is attached to the current request on HttpContext. As informações do utilizador em HttpContext serão utilizadas por outro controlador (RegisterController) mais tarde, para adicionar uma etiqueta ao pedido de registo de notificação.User information in HttpContext will be used by another controller (RegisterController) later to add a tag to the notification registration request.

    public class AuthenticationTestHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var authorizationHeader = request.Headers.GetValues("Authorization").First();
    
            if (authorizationHeader != null && authorizationHeader
                .StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase))
            {
                string authorizationUserAndPwdBase64 =
                    authorizationHeader.Substring("Basic ".Length);
                string authorizationUserAndPwd = Encoding.Default
                    .GetString(Convert.FromBase64String(authorizationUserAndPwdBase64));
                string user = authorizationUserAndPwd.Split(':')[0];
                string password = authorizationUserAndPwd.Split(':')[1];
    
                if (verifyUserAndPwd(user, password))
                {
                    // Attach the new principal object to the current HttpContext object
                    HttpContext.Current.User =
                        new GenericPrincipal(new GenericIdentity(user), new string[0]);
                    System.Threading.Thread.CurrentPrincipal =
                        System.Web.HttpContext.Current.User;
                }
                else return Unauthorized();
            }
            else return Unauthorized();
    
            return base.SendAsync(request, cancellationToken);
        }
    
        private bool verifyUserAndPwd(string user, string password)
        {
            // This is not a real authentication scheme.
            return user == password;
        }
    
        private Task<HttpResponseMessage> Unauthorized()
        {
            var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
            var tsc = new TaskCompletionSource<HttpResponseMessage>();
            tsc.SetResult(response);
            return tsc.Task;
        }
    }
    

    Nota

    Observação de segurança: A AuthenticationTestHandler classe não fornece autenticação verdadeira.Security note: The AuthenticationTestHandler class does not provide true authentication. É utilizada apenas para imitar a autenticação básica e não é segura.It is used only to mimic basic authentication and is not secure. Tem de implementar um mecanismo de autenticação segura nos seus serviços e aplicações de produção.You must implement a secure authentication mechanism in your production applications and services.

  5. Para registar o processador de mensagens, adicione o seguinte código ao fim do método Register na classe App_Start/WebApiConfig.cs:To register the message handler, add the following code at the end of the Register method in the App_Start/WebApiConfig.cs class:

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Guarde as alterações.Save your changes.

Utilizar o back-end de WebAPI para registar notificaçõesRegister for notifications by using the WebAPI backend

Nesta secção, adicione um controlador novo ao back-end de WebAPI para processar pedidos de registo de um utilizador e de um dispositivo para as notificações, através da biblioteca de cliente dos hubs de notificação.In this section, you add a new controller to the WebAPI backend to handle requests to register a user and a device for notifications by using the client library for notification hubs. O controlador adiciona uma etiqueta de utilizador para o utilizador que AuthenticationTestHandler autenticou e anexou a HttpContext.The controller adds a user tag for the user that was authenticated and attached to HttpContext by AuthenticationTestHandler. A etiqueta tem o formato de cadeia "username:<actual username>".The tag has the string format, "username:<actual username>".

  1. No Explorador de Soluções, clique com o botão direito no projeto AppBackend e, em seguida, selecione Gerir Pacotes de NuGet.In Solution Explorer, right-click the AppBackend project and then select Manage NuGet Packages.

  2. No painel esquerdo, selecione Online e, na caixa Procurar, escreva Microsoft.Azure.NotificationHubs.In the left pane, select Online and then, in the Search box, type Microsoft.Azure.NotificationHubs.

  3. Na lista de resultados, selecione Hubs de Notificação do Microsoft Azure e, em seguida, selecione Instalar.In the results list, select Microsoft Azure Notification Hubs, and then select Install. Conclua a instalação e feche a janela Gestor de Pacotes de NuGet.Complete the installation, and then close the NuGet Package Manager window.

    Esta ação adiciona uma referência ao SDK dos Hubs de Notificação do Azure mediante a utilização do Pacote NuGet Microsoft.Azure.Notification Hubs.This action adds a reference to the Azure Notification Hubs SDK by using the Microsoft.Azure.Notification Hubs NuGet package.

  4. Crie um ficheiro de classe novo que represente a ligação ao hub de notificação utilizado para enviar notificações.Create a new class file that represents the connection with the notification hub that's used to send notifications. No Explorador de Soluções, clique com o botão direito do rato na pasta Modelos, selecione Adicionar e, em seguida, selecione Classe.In Solution Explorer, right-click the Models folder, select Add, and then select Class. Dê o nome Notifications.cs à classe nova e selecione Adicionar para gerá-la.Name the new class Notifications.cs, and then select Add to generate the class.

    A janela Adicionar Novo Item

  5. Em Notifications.cs, adicione a instrução using à parte superior do ficheiro:In Notifications.cs, add the following using statement at the top of the file:

    using Microsoft.Azure.NotificationHubs;
    
  6. Substitua a definição de classe Notifications pelo código seguinte e substitua os dois marcadores de posição pela cadeia de ligação (com acesso total) do seu hub de notificação e o nome do hub (disponível no portal do Azure):Replace the Notifications class definition with the following code, and replace the two placeholders with the connection string (with full access) for your notification hub and the hub name (available at Azure portal):

    public class Notifications
    {
        public static Notifications Instance = new Notifications();
    
        public NotificationHubClient Hub { get; set; }
    
        private Notifications() {
            Hub = NotificationHubClient.CreateClientFromConnectionString("<your hub's DefaultFullSharedAccessSignature>",
                                                                            "<hub name>");
        }
    }
    

    Importante

    Insira o nome e o DefaultFullSharedAccessSignature do seu hub antes de continuar.Enter the name and the DefaultFullSharedAccessSignature of your hub before proceeding further.

  7. Em seguida, crie um controlador novo com o nome RegisterController.Next, create a new controller named RegisterController. No Explorador de Soluções, clique com o botão direito do rato na pasta Controladores, selecione Adicionar e, em seguida, selecione Controlador.In Solution Explorer, right-click the Controllers folder, select Add, and then select Controller.

  8. Selecione Controlador da API Web 2 – Vazio e, em seguida, selecione Adicionar.Select Web API 2 Controller - Empty, and then select Add.

    A janela Adicionar Estrutura

  9. Na caixa Nome do controlador, escreva RegisterController para designar a classe nova e selecione Adicionar.In the Controller name box, type RegisterController to name the new class, and then select Add.

    A janela Adicionar Controlador

  10. No RegisterController.cs, adicione as instruções using seguintes:In RegisterController.cs, add the following using statements:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Adicione o código seguinte dentro da definição de classe RegisterController.Add the following code inside the RegisterController class definition. Neste código, adicione uma etiqueta de utilizador para o utilizador que está anexado a HttpContext.In this code, you add a user tag for the user that's attached to HttpContext. O utilizador foi autenticado e anexado a HttpContext através do filtro de mensagem que adicionou, AuthenticationTestHandler.The user was authenticated and attached to HttpContext by the message filter that you added, AuthenticationTestHandler. Também pode adicionar verificações opcionais para confirmar que o utilizador tem direitos para se registar nas etiquetas pedidas.You can also add optional checks to verify that the user has rights to register for the requested tags.

    private NotificationHubClient hub;
    
    public RegisterController()
    {
        hub = Notifications.Instance.Hub;
    }
    
    public class DeviceRegistration
    {
        public string Platform { get; set; }
        public string Handle { get; set; }
        public string[] Tags { get; set; }
    }
    
    // POST api/register
    // This creates a registration id
    public async Task<string> Post(string handle = null)
    {
        string newRegistrationId = null;
    
        // make sure there are no existing registrations for this push handle (used for iOS and Android)
        if (handle != null)
        {
            var registrations = await hub.GetRegistrationsByChannelAsync(handle, 100);
    
            foreach (RegistrationDescription registration in registrations)
            {
                if (newRegistrationId == null)
                {
                    newRegistrationId = registration.RegistrationId;
                }
                else
                {
                    await hub.DeleteRegistrationAsync(registration);
                }
            }
        }
    
        if (newRegistrationId == null) 
            newRegistrationId = await hub.CreateRegistrationIdAsync();
    
        return newRegistrationId;
    }
    
    // PUT api/register/5
    // This creates or updates a registration (with provided channelURI) at the specified id
    public async Task<HttpResponseMessage> Put(string id, DeviceRegistration deviceUpdate)
    {
        RegistrationDescription registration = null;
        switch (deviceUpdate.Platform)
        {
            case "mpns":
                registration = new MpnsRegistrationDescription(deviceUpdate.Handle);
                break;
            case "wns":
                registration = new WindowsRegistrationDescription(deviceUpdate.Handle);
                break;
            case "apns":
                registration = new AppleRegistrationDescription(deviceUpdate.Handle);
                break;
            case "fcm":
                registration = new FcmRegistrationDescription(deviceUpdate.Handle);
                break;
            default:
                throw new HttpResponseException(HttpStatusCode.BadRequest);
        }
    
        registration.RegistrationId = id;
        var username = HttpContext.Current.User.Identity.Name;
    
        // add check if user is allowed to add these tags
        registration.Tags = new HashSet<string>(deviceUpdate.Tags);
        registration.Tags.Add("username:" + username);
    
        try
        {
            await hub.CreateOrUpdateRegistrationAsync(registration);
        }
        catch (MessagingException e)
        {
            ReturnGoneIfHubResponseIsGone(e);
        }
    
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    
    // DELETE api/register/5
    public async Task<HttpResponseMessage> Delete(string id)
    {
        await hub.DeleteRegistrationAsync(id);
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    
    private static void ReturnGoneIfHubResponseIsGone(MessagingException e)
    {
        var webex = e.InnerException as WebException;
        if (webex.Status == WebExceptionStatus.ProtocolError)
        {
            var response = (HttpWebResponse)webex.Response;
            if (response.StatusCode == HttpStatusCode.Gone)
                throw new HttpRequestException(HttpStatusCode.Gone.ToString());
        }
    }
    
  12. Guarde as alterações.Save your changes.

Enviar notificações a partir do back-end de WebAPISend notifications from the WebAPI backend

Nesta secção, irá adicionar um novo controlador que indica uma forma de os dispositivos de cliente enviarem uma notificação.In this section, you add a new controller that exposes a way for client devices to send a notification. A notificação baseia-se na etiqueta de nome de utilizador que utiliza a Biblioteca .NET dos Hubs de Notificação do Azure no back-end de ASP.NET WebAPI.The notification is based on the username tag that uses Azure Notification Hubs .NET Library in the ASP.NET WebAPI backend.

  1. Crie outro controlador novo com o nome NotificationsController da mesma forma que criou o RegisterController na secção anterior.Create another new controller named NotificationsController the same way you created RegisterController in the previous section.

  2. No NotificationsController.cs, adicione as instruções using seguintes:In NotificationsController.cs, add the following using statements:

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. Adicione o método seguinte à classe NotificationsController:Add the following method to the NotificationsController class:

    Este código envia um tipo de notificação com base no parâmetro pns do Serviço de Notificação de Plataforma (PNS).This code sends a notification type that's based on the Platform Notification Service (PNS) pns parameter. O valor de to_tag é utilizado para definir a etiqueta nome de utilizador na mensagem.The value of to_tag is used to set the username tag on the message. Esta etiqueta tem de corresponder a uma etiqueta de nome de utilizador de um registo de hub de notificação ativo.This tag must match a username tag of an active notification hub registration. A mensagem da notificação é retirada do corpo do pedido POST e formatada para o PNS de destino.The notification message is pulled from the body of the POST request and formatted for the target PNS.

    Consoante o PNS que os seus dispositivos suportados utilizam para receber notificações, estas são suportadas com vários formatos.Depending on the PNS that your supported devices use to receive notifications, the notifications are supported by a variety of formats. Por exemplo, em dispositivos Windows, poderá utilizar uma notificação de alerta com WNS que não seja diretamente suportada por outro PNS.For example, on Windows devices, you might use a toast notification with WNS that isn't directly supported by another PNS. Nesse caso, o seu back-end tem de formatar a notificação de modo a que seja suportada pelo PNS dos dispositivos que pretende incluir.In such an instance, your backend needs to format the notification into a supported notification for the PNS of devices you plan to support. Em seguida, utilize a API de envio adequada na classe NotificationHubClient.Then use the appropriate send API on the NotificationHubClient class.

    public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag)
    {
        var user = HttpContext.Current.User.Identity.Name;
        string[] userTag = new string[2];
        userTag[0] = "username:" + to_tag;
        userTag[1] = "from:" + user;
    
        Microsoft.Azure.NotificationHubs.NotificationOutcome outcome = null;
        HttpStatusCode ret = HttpStatusCode.InternalServerError;
    
        switch (pns.ToLower())
        {
            case "wns":
                // Windows 8.1 / Windows Phone 8.1
                var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">" + 
                            "From " + user + ": " + message + "</text></binding></visual></toast>";
                outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag);
                break;
            case "apns":
                // iOS
                var alert = "{\"aps\":{\"alert\":\"" + "From " + user + ": " + message + "\"}}";
                outcome = await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(alert, userTag);
                break;
            case "fcm":
                // Android
                var notif = "{ \"data\" : {\"message\":\"" + "From " + user + ": " + message + "\"}}";
                outcome = await Notifications.Instance.Hub.SendFcmNativeNotificationAsync(notif, userTag);
                break;
        }
    
        if (outcome != null)
        {
            if (!((outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Abandoned) ||
                (outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Unknown)))
            {
                ret = HttpStatusCode.OK;
            }
        }
    
        return Request.CreateResponse(ret);
    }
    
  4. Para executar a aplicação e garantir a precisão do seu trabalho até ao momento, prima a tecla F5.To run the application and ensure the accuracy of your work so far, select the F5 key. A aplicação abre um browser e é apresentada na home page do ASP.NET.The app opens a web browser, and it is displayed on the ASP.NET home page.

Publicar o back-end de WebAPI novoPublish the new WebAPI backend

Em seguida, implemente a aplicação num site do Azure para que seja acessível a partir de todos os dispositivos.Next, you deploy the app to an Azure website to make it accessible from all devices.

  1. Clique com o botão direito do rato no projeto AppBackend e selecione Publicar.Right-click the AppBackend project, and then select Publish.

  2. Selecione Serviço de Aplicações do Microsoft Azure como o destino da publicação e selecione **Publicar.Select Microsoft Azure App Service as your publish target, and then select **Publish. A janela Criar Serviço de Aplicações é aberta.The Create App Service window opens. Aí, pode criar todos os recursos do Azure necessários para executar a aplicação Web ASP.NET no Azure.Here you can create all the necessary Azure resources to run the ASP.NET web app in Azure.

    O mosaico do Serviço de Aplicações do Microsoft Azure

  3. Na janela Criar Serviço de Aplicações, selecione a sua conta do Azure.In the Create App Service window, select your Azure account. Selecione Alterar Tipo > Aplicação Web.Select Change Type > Web App. Mantenha o Nome da Aplicação Web predefinido e, em seguida, selecione a Subscrição, o Grupo de Recursos e o Plano do Serviço de Aplicações.Keep the default Web App Name, and then select the Subscription, Resource Group, and App Service Plan.

  4. Selecione Criar.Select Create.

  5. Anote a propriedade URL do Site, na secção Resumo.Make a note of the Site URL property in the Summary section. Este URL será o seu ponto final de back-end mais adiante no tutorial.This URL is your back-end endpoint later in the tutorial.

  6. Selecione Publicar.Select Publish.

Depois de concluir o assistente, este publica a aplicação Web ASP.NET no Azure e, em seguida, abre a aplicação no browser predefinido.After you've completed the wizard, it publishes the ASP.NET web app to Azure and then opens the app in the default browser. A aplicação é visualizável nos Serviços Aplicacionais do Azure.Your application is viewable in Azure App Services.

O URL utiliza o nome da aplicação Web que especificou anteriormente, com o formato http://<nome_da_aplicação>.azurewebsites.net.The URL uses the web app name that you specified earlier, with the format http://<app_name>.azurewebsites.net.

Modificar as suas aplicações iOSModify your iOS app

  1. Abra a aplicação de vista de página única que criou no introdução aos Hubs de notificação (iOS) tutorial.Open the Single Page view app you created in the Getting Started with Notification Hubs (iOS) tutorial.

    Nota

    Esta secção assume que seu projeto está configurado com um nome de organização vazio.This section assumes that your project is configured with an empty organization name. Caso contrário, terá de preceder o nome da sua organização para todos os nomes de classe.If not, you need to prepend your organization name to all class names.

  2. Na Main.storyboard de ficheiros, adicione os componentes mostrados na captura de ecrã da biblioteca do objeto.In the Main.storyboard file, add the components shown in the screenshot from the object library.

    Editar o storyboard no construtor de interface do Xcode

    • Nome de utilizador: Um UITextField com texto de marcador de posição introduza o nome de utilizador, imediatamente abaixo do envio resultados Etiquetar e restrita para as margens esquerdas e direita e sob a etiqueta de resultados de envio.Username: A UITextField with placeholder text, Enter Username, immediately beneath the send results label and constrained to the left and right margins and beneath the send results label.

    • palavra-passe: Um UITextField com texto de marcador de posição introduza a palavra-passe, imediatamente abaixo do nome de utilizador restrito para as margens esquerdas e direita e sob o campo de texto do nome de utilizador e de campo de texto.Password: A UITextField with placeholder text, Enter Password, immediately beneath the username text field and constrained to the left and right margins and beneath the username text field. Verifique a Secure entrada de texto opção o Inspetor de atributo, em devolver chave.Check the Secure Text Entry option in the Attribute Inspector, under Return Key.

    • Inicie sessão no: Um UIButton etiquetados imediatamente abaixo do campo de texto da palavra-passe e desmarque o Enabled opção o Inspetor de atributos, em conteúdo de controleLog in: A UIButton labeled immediately beneath the password text field and uncheck the Enabled option in the Attributes Inspector, under Control-Content

    • WNS: Etiquetar e alternar para ativar o envio da notificação de serviço de notificação do Windows, se tiver sido configurado no hub.WNS: Label and switch to enable sending the notification Windows Notification Service if it has been set up on the hub. Consulte a introdução ao Windows tutorial.See the Windows Getting Started tutorial.

    • GCM: Etiquetar e alternar para ativar o envio da notificação para a Google Cloud Messaging, se tiver sido configurado no hub.GCM: Label and switch to enable sending the notification to Google Cloud Messaging if it has been set up on the hub. Ver introdução ao Android tutorial.See Android Getting Started tutorial.

    • APNS: Etiqueta e o comutador para permitir o envio da notificação para o serviço de notificação de plataforma da Apple.APNS: Label and switch to enable sending the notification to the Apple Platform Notification Service.

    • Destinatário Username:A UITextField com texto de marcador de posição etiqueta de nome de utilizador do destinatário, imediatamente abaixo do GCM identificar e restrita para as margens esquerdas e direita e sob a etiqueta do GCM.Recipient Username:A UITextField with placeholder text, Recipient username tag, immediately beneath the GCM label and constrained to the left and right margins and beneath the GCM label.

      Alguns componentes foram adicionados na introdução aos Hubs de notificação (iOS) tutorial.Some components were added in the Getting Started with Notification Hubs (iOS) tutorial.

  3. CTRL arraste a partir dos componentes na vista para ViewController.h e adicione essas saídas de novo.Ctrl drag from the components in the view to ViewController.h and add these new outlets.

    @property (weak, nonatomic) IBOutlet UITextField *UsernameField;
    @property (weak, nonatomic) IBOutlet UITextField *PasswordField;
    @property (weak, nonatomic) IBOutlet UITextField *RecipientField;
    @property (weak, nonatomic) IBOutlet UITextField *NotificationField;
    
    // Used to enable the buttons on the UI
    @property (weak, nonatomic) IBOutlet UIButton *LogInButton;
    @property (weak, nonatomic) IBOutlet UIButton *SendNotificationButton;
    
    // Used to enabled sending notifications across platforms
    @property (weak, nonatomic) IBOutlet UISwitch *WNSSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *GCMSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *APNSSwitch;
    
    - (IBAction)LogInAction:(id)sender;
    
  4. Na ViewController.h, adicione o seguinte #define após suas declarações de importação.In ViewController.h, add the following #define after your import statements. Substitua o <Enter Your Backend Endpoint> espaço reservado com o URL de destino que utilizou para implementar o seu back-end de aplicação na secção anterior.Substitute the <Enter Your Backend Endpoint> placeholder with the Destination URL you used to deploy your app backend in the previous section. Por exemplo, http://your_backend.azurewebsites.net.For example, http://your_backend.azurewebsites.net.

    #define BACKEND_ENDPOINT @"<Enter Your Backend Endpoint>"
    
  5. No seu projeto, crie uma nova classe Cocoa Touch com o nome RegisterClient a interface com o back-end ASP.NET que criou.In your project, create a new Cocoa Touch class named RegisterClient to interface with the ASP.NET back-end you created. Criar a classe a herdar de NSObject.Create the class inheriting from NSObject. Em seguida, adicione o seguinte código no RegisterClient.h.Then add the following code in the RegisterClient.h.

    @interface RegisterClient : NSObject
    
    @property (strong, nonatomic) NSString* authenticationHeader;
    
    -(void) registerWithDeviceToken:(NSData*)token tags:(NSSet*)tags
        andCompletion:(void(^)(NSError*))completion;
    
    -(instancetype) initWithEndpoint:(NSString*)Endpoint;
    
    @end
    
  6. Na RegisterClient.m, atualize o @interface secção:In the RegisterClient.m, update the @interface section:

    @interface RegisterClient ()
    
    @property (strong, nonatomic) NSURLSession* session;
    @property (strong, nonatomic) NSURLSession* endpoint;
    
    -(void) tryToRegisterWithDeviceToken:(NSData*)token tags:(NSSet*)tags retry:(BOOL)retry
                andCompletion:(void(^)(NSError*))completion;
    -(void) retrieveOrRequestRegistrationIdWithDeviceToken:(NSString*)token
                completion:(void(^)(NSString*, NSError*))completion;
    -(void) upsertRegistrationWithRegistrationId:(NSString*)registrationId deviceToken:(NSString*)token
                tags:(NSSet*)tags andCompletion:(void(^)(NSURLResponse*, NSError*))completion;
    
    @end
    
  7. Substitua o @implementation secção RegisterClient.m com o código a seguir:Replace the @implementation section in the RegisterClient.m with the following code:

    @implementation RegisterClient
    
    // Globals used by RegisterClient
    NSString *const RegistrationIdLocalStorageKey = @"RegistrationId";
    
    -(instancetype) initWithEndpoint:(NSString*)Endpoint
    {
        self = [super init];
        if (self) {
            NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
            _session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:nil];
            _endpoint = Endpoint;
        }
        return self;
    }
    
    -(void) registerWithDeviceToken:(NSData*)token tags:(NSSet*)tags
                andCompletion:(void(^)(NSError*))completion
    {
        [self tryToRegisterWithDeviceToken:token tags:tags retry:YES andCompletion:completion];
    }
    
    -(void) tryToRegisterWithDeviceToken:(NSData*)token tags:(NSSet*)tags retry:(BOOL)retry
                andCompletion:(void(^)(NSError*))completion
    {
        NSSet* tagsSet = tags?tags:[[NSSet alloc] init];
    
        NSString *deviceTokenString = [[token description]
            stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
        deviceTokenString = [[deviceTokenString stringByReplacingOccurrencesOfString:@" " withString:@""]
                                uppercaseString];
    
        [self retrieveOrRequestRegistrationIdWithDeviceToken: deviceTokenString
            completion:^(NSString* registrationId, NSError *error) {
            NSLog(@"regId: %@", registrationId);
            if (error) {
                completion(error);
                return;
            }
    
            [self upsertRegistrationWithRegistrationId:registrationId deviceToken:deviceTokenString
                tags:tagsSet andCompletion:^(NSURLResponse * response, NSError *error) {
                if (error) {
                    completion(error);
                    return;
                }
    
                NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
                if (httpResponse.statusCode == 200) {
                    completion(nil);
                } else if (httpResponse.statusCode == 410 && retry) {
                    [self tryToRegisterWithDeviceToken:token tags:tags retry:NO andCompletion:completion];
                } else {
                    NSLog(@"Registration error with response status: %ld", (long)httpResponse.statusCode);
    
                    completion([NSError errorWithDomain:@"Registration" code:httpResponse.statusCode
                                userInfo:nil]);
                }
    
            }];
        }];
    }
    
    -(void) upsertRegistrationWithRegistrationId:(NSString*)registrationId deviceToken:(NSData*)token
                tags:(NSSet*)tags andCompletion:(void(^)(NSURLResponse*, NSError*))completion
    {
        NSDictionary* deviceRegistration = @{@"Platform" : @"apns", @"Handle": token,
                                                @"Tags": [tags allObjects]};
        NSData* jsonData = [NSJSONSerialization dataWithJSONObject:deviceRegistration
                            options:NSJSONWritingPrettyPrinted error:nil];
    
        NSLog(@"JSON registration: %@", [[NSString alloc] initWithData:jsonData
                                            encoding:NSUTF8StringEncoding]);
    
        NSString* endpoint = [NSString stringWithFormat:@"%@/api/register/%@", _endpoint,
                                registrationId];
        NSURL* requestURL = [NSURL URLWithString:endpoint];
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"PUT"];
        [request setHTTPBody:jsonData];
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
                                                self.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
        [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    
        NSURLSessionDataTask* dataTask = [self.session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            if (!error)
            {
                completion(response, error);
            }
            else
            {
                NSLog(@"Error request: %@", error);
                completion(nil, error);
            }
        }];
        [dataTask resume];
    }
    
    -(void) retrieveOrRequestRegistrationIdWithDeviceToken:(NSString*)token
                completion:(void(^)(NSString*, NSError*))completion
    {
        NSString* registrationId = [[NSUserDefaults standardUserDefaults]
                                    objectForKey:RegistrationIdLocalStorageKey];
    
        if (registrationId)
        {
            completion(registrationId, nil);
            return;
        }
    
        // request new one & save
        NSURL* requestURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/api/register?handle=%@",
                                _endpoint, token]];
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"POST"];
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
                                                self.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
    
        NSURLSessionDataTask* dataTask = [self.session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
            if (!error && httpResponse.statusCode == 200)
            {
                NSString* registrationId = [[NSString alloc] initWithData:data
                    encoding:NSUTF8StringEncoding];
    
                // remove quotes
                registrationId = [registrationId substringWithRange:NSMakeRange(1,
                                    [registrationId length]-2)];
    
                [[NSUserDefaults standardUserDefaults] setObject:registrationId
                    forKey:RegistrationIdLocalStorageKey];
                [[NSUserDefaults standardUserDefaults] synchronize];
    
                completion(registrationId, nil);
            }
            else
            {
                NSLog(@"Error status: %ld, request: %@", (long)httpResponse.statusCode, error);
                if (error)
                    completion(nil, error);
                else {
                    completion(nil, [NSError errorWithDomain:@"Registration" code:httpResponse.statusCode
                                userInfo:nil]);
                }
            }
        }];
        [dataTask resume];
    }
    
    @end
    

    Esse código implementa a lógica, explicada no artigo de documentação de orientação registar a partir do seu back-end de aplicação utilizando NSURLSession para efetuar o REST é chamado para seu back-end de aplicação e NSUserDefaults para armazenar localmente o registrationId devolvido pela hub de notificação.This code implements the logic explained in the guidance article Registering from your app backend using NSURLSession to perform REST calls to your app backend, and NSUserDefaults to locally store the registrationId returned by the notification hub.

    Essa classe requer sua propriedade authorizationHeader ser definida para que funcionem corretamente.This class requires its property authorizationHeader to be set in order to work properly. Esta propriedade é definida ViewController classe após o início de sessão.This property is set by the ViewController class after the login.

  8. Na ViewController.h, adicione um #import instrução para RegisterClient.h.In ViewController.h, add a #import statement for RegisterClient.h. Em seguida, adicione uma declaração para o token de dispositivo e de referência para um RegisterClient instância no @interface secção:Then add a declaration for the device token and reference to a RegisterClient instance in the @interface section:

    #import "RegisterClient.h"
    
    @property (strong, nonatomic) NSData* deviceToken;
    @property (strong, nonatomic) RegisterClient* registerClient;
    
  9. No ViewController.m, adicione uma declaração do método particular no @interface secção:In ViewController.m, add a private method declaration in the @interface section:

    @interface ViewController () <UITextFieldDelegate, NSURLConnectionDataDelegate, NSXMLParserDelegate>
    
    // create the Authorization header to perform Basic authentication with your app back-end
    -(void) createAndSetAuthenticationHeaderWithUsername:(NSString*)username
                    AndPassword:(NSString*)password;
    
    @end
    

    Nota

    O fragmento seguinte não é um esquema de autenticação segura, deve substituir a implementação do createAndSetAuthenticationHeaderWithUsername:AndPassword: com o mecanismo de autenticação específicos que gera um token de autenticação para serem consumidos por classe de cliente Registre-se, por exemplo, OAuth, do Active Directory.The following snippet is not a secure authentication scheme, you should substitute the implementation of the createAndSetAuthenticationHeaderWithUsername:AndPassword: with your specific authentication mechanism that generates an authentication token to be consumed by the register client class, e.g. OAuth, Active Directory.

  10. Em seguida, no @implementation secção do ViewController.m, adicione o seguinte código, que adiciona a implementação para definir o cabeçalho de token e a autenticação do dispositivo.Then in the @implementation section of ViewController.m, add the following code, which adds the implementation for setting the device token and authentication header.

    -(void) setDeviceToken: (NSData*) deviceToken
    {
        _deviceToken = deviceToken;
        self.LogInButton.enabled = YES;
    }
    
    -(void) createAndSetAuthenticationHeaderWithUsername:(NSString*)username
                    AndPassword:(NSString*)password;
    {
        NSString* headerValue = [NSString stringWithFormat:@"%@:%@", username, password];
    
        NSData* encodedData = [[headerValue dataUsingEncoding:NSUTF8StringEncoding] base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
    
        self.registerClient.authenticationHeader = [[NSString alloc] initWithData:encodedData
                                                    encoding:NSUTF8StringEncoding];
    }
    
    -(BOOL)textFieldShouldReturn:(UITextField *)textField
    {
        [textField resignFirstResponder];
        return YES;
    }
    

    Observe como a definição do token de dispositivo permite que o botão de início de sessão.Notice how setting the device token enables the log in button. É porque como parte da ação de início de sessão, o controlador de vista se registra para notificações push com o back-end de aplicação.It's because as a part of the login action, the view controller registers for push notifications with the app backend. Por conseguinte, não pretende que Log em ação para estar acessível até que o token do dispositivo foi corretamente configurado.Hence, do not want Log In action to be accessible until the device token has been properly set up. É possível desacoplar o início de sessão do registo de push, desde que o primeiro acontece antes do último.You can decouple the login from the push registration as long as the former happens before the latter.

  11. No ViewController.m, utilize os seguintes fragmentos para implementar o método de ação para sua sessão botão e um método para enviar a mensagem de notificação utilizando o back-end ASP.NET.In ViewController.m, use the following snippets to implement the action method for your Log In button and a method to send the notification message using the ASP.NET backend.

    - (IBAction)LogInAction:(id)sender {
        // create authentication header and set it in register client
        NSString* username = self.UsernameField.text;
        NSString* password = self.PasswordField.text;
    
        [self createAndSetAuthenticationHeaderWithUsername:username AndPassword:password];
    
        __weak ViewController* selfie = self;
        [self.registerClient registerWithDeviceToken:self.deviceToken tags:nil
            andCompletion:^(NSError* error) {
            if (!error) {
                dispatch_async(dispatch_get_main_queue(),
                ^{
                    selfie.SendNotificationButton.enabled = YES;
                    [self MessageBox:@"Success" message:@"Registered successfully!"];
                });
            }
        }];
    }
    
    - (void)SendNotificationASPNETBackend:(NSString*)pns UsernameTag:(NSString*)usernameTag
                Message:(NSString*)message
    {
        NSURLSession* session = [NSURLSession
            sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:nil
            delegateQueue:nil];
    
        // Pass the pns and username tag as parameters with the REST URL to the ASP.NET backend
        NSURL* requestURL = [NSURL URLWithString:[NSString
            stringWithFormat:@"%@/api/notifications?pns=%@&to_tag=%@", BACKEND_ENDPOINT, pns,
            usernameTag]];
    
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"POST"];
    
        // Get the mock authenticationheader from the register client
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
            self.registerClient.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
    
        //Add the notification message body
        [request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPBody:[message dataUsingEncoding:NSUTF8StringEncoding]];
    
        // Execute the send notification REST API on the ASP.NET Backend
        NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
            if (error || httpResponse.statusCode != 200)
            {
                NSString* status = [NSString stringWithFormat:@"Error Status for %@: %d\nError: %@\n",
                                    pns, httpResponse.statusCode, error];
                dispatch_async(dispatch_get_main_queue(),
                ^{
                    // Append text because all 3 PNS calls may also have information to view
                    [self.sendResults setText:[self.sendResults.text stringByAppendingString:status]];
                });
                NSLog(status);
            }
    
            if (data != NULL)
            {
                xmlParser = [[NSXMLParser alloc] initWithData:data];
                [xmlParser setDelegate:self];
                [xmlParser parse];
            }
        }];
        [dataTask resume];
    }
    
  12. Atualizar a ação para o Enviar notificação botão para utilizar o back-end ASP.NET e enviar para qualquer PNS ativada por um comutador.Update the action for the Send Notification button to use the ASP.NET backend and send to any PNS enabled by a switch.

    - (IBAction)SendNotificationMessage:(id)sender
    {
        //[self SendNotificationRESTAPI];
        [self SendToEnabledPlatforms];
    }
    
    -(void)SendToEnabledPlatforms
    {
        NSString* json = [NSString stringWithFormat:@"\"%@\"",self.notificationMessage.text];
    
        [self.sendResults setText:@""];
    
        if ([self.WNSSwitch isOn])
            [self SendNotificationASPNETBackend:@"wns" UsernameTag:self.RecipientField.text Message:json];
    
        if ([self.GCMSwitch isOn])
            [self SendNotificationASPNETBackend:@"gcm" UsernameTag:self.RecipientField.text Message:json];
    
        if ([self.APNSSwitch isOn])
            [self SendNotificationASPNETBackend:@"apns" UsernameTag:self.RecipientField.text Message:json];
    }
    
  13. Na ViewDidLoad funcionar, adicione o seguinte para criar uma instância a RegisterClient de instância e defina o delegado para os campos de texto.In the ViewDidLoad function, add the following to instantiate the RegisterClient instance and set the delegate for your text fields.

    self.UsernameField.delegate = self;
    self.PasswordField.delegate = self;
    self.RecipientField.delegate = self;
    self.registerClient = [[RegisterClient alloc] initWithEndpoint:BACKEND_ENDPOINT];
    
  14. Agora na AppDelegate.m, remova todo o conteúdo do método application:didRegisterForPushNotificationWithDeviceToken: e substituí-lo com o seguinte (para se certificar-se de que o controlador de vista contém o token de dispositivo mais recente obtido a partir do APNs):Now in AppDelegate.m, remove all the content of the method application:didRegisterForPushNotificationWithDeviceToken: and replace it with the following (to make sure that the view controller contains the latest device token retrieved from APNs):

    // Add import to the top of the file
    #import "ViewController.h"
    
    - (void)application:(UIApplication *)application
                didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
        ViewController* rvc = (ViewController*) self.window.rootViewController;
        rvc.deviceToken = deviceToken;
    }
    
  15. Por fim no AppDelegate.m, certifique-se de que tem o seguinte método:Finally in AppDelegate.m, make sure you have the following method:

    - (void)application:(UIApplication *)application didReceiveRemoteNotification: (NSDictionary *)userInfo {
        NSLog(@"%@", userInfo);
        [self MessageBox:@"Notification" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"]];
    }
    

Testar a aplicaçãoTest the application

  1. No XCode, execute a aplicação num dispositivo iOS físico (push notificações não funcionam no simulador).In XCode, run the app on a physical iOS device (push notifications do not work in the simulator).

  2. Na aplicação do iOS da interface do Usuário, introduza o mesmo valor para o nome de utilizador e palavra-passe.In the iOS app UI, enter same value for both username and password. Em seguida, clique em sessão.Then click Log In.

    testar a aplicação iOS

  3. Verá um pop-up informando-o de sucesso de registo.You should see a pop-up informing you of registration success. Clique em OK.Click OK.

    notificação apresentada de teste de iOS

  4. Na *etiqueta de nome de utilizador do destinatário texto, insira a etiqueta de nome de utilizador utilizada com o registo a partir de outro dispositivo.In the *Recipient username tag text field, enter the user name tag used with the registration from another device.

  5. Introduza uma mensagem de notificação e clique em Enviar notificação.Enter a notification message and click Send Notification. Apenas os dispositivos que têm um registo com a etiqueta de nome de utilizador destinatários recebem a mensagem de notificação.Only the devices that have a registration with the recipient user name tag receive the notification message. É enviada apenas aos usuários.It is only sent to those users.

    marcado de notificação de teste de iOS

Passos SeguintesNext steps

Neste tutorial, aprendeu a enviar notificações push para utilizadores específicos que têm etiquetas associadas aos respetivos registos.In this tutorial, you learned how to push notifications to specific users that have tags associated with their registrations. Para saber como enviar notificações push com base na localização, avance para o seguinte tutorial:To learn how to push location-based notifications, advance to the following tutorial: