Tutorial: Enviar notificações por push para aplicativos do .NET MAUI usando os Hubs de Notificações do Microsoft Azure por meio de um serviço de back-end
As notificações por push fornecem informações de um sistema de back-end para um aplicativo cliente. Apple, Google e outras plataformas têm seu próprio PNS (Serviço de Notificação por Push). Os Hubs de Notificações do Microsoft Azure permitem centralizar notificações entre plataformas para que seu aplicativo de back-end possa se comunicar com um único hub, que cuida da distribuição de notificações para cada PNS.
Os Hubs de Notificações do Microsoft Azure exigem que os aplicativos se registrem no hub e, opcionalmente, definam modelos e/ou assinem marcas:
- A execução de uma instalação de dispositivo vincula um identificador PNS a um identificador no Hub de Notificações do Microsoft Azure. Para obter mais informações sobre registros, consulte Gerenciamento de registro.
- Os modelos permitem que os dispositivos especifiquem modelos de mensagem parametrizados. As mensagens de entrada podem ser personalizadas por dispositivo. Para obter mais informações, consulte Modelos de hubs de notificação.
- As marcas podem ser usadas para assinar categorias de mensagens, como notícias, esportes e clima. Para saber mais, veja Expressões de marca e de roteamento.
Neste tutorial, você usará Hubs de Notificações do Microsoft Azure para enviar notificações por push para um aplicativo do .NET MAUI (.NET Multi-Platform App UI) direcionado ao Android e ao iOS. Um back-end da API Web do ASP.NET Core é usado para lidar com o registro do dispositivo para o cliente e para iniciar uma notificação por push. Essas operações são tratadas usando o pacote NuGet Microsoft.Azure.NotificationHubs. Para obter mais informações sobre a abordagem geral, consulte Gerenciamento de registro a partir de um back-end.
Neste tutorial, você:
- Configurar serviços de notificação por push e o Hub de Notificações do Microsoft Azure.
- Criar um aplicativo de back-end de API Web do ASP.NET Core.
- Criar um aplicativo .NET.
- Configurar o aplicativo Android para notificações por push.
- Configurar o aplicativo iOS para notificações por push.
- Testar o aplicativo.
- Solucionar problemas de instalação e configuração de domínio.
Pré-requisitos
Neste tutorial, você precisará de:
- Uma conta do Azure com uma assinatura ativa.
- Um PC ou Mac com a versão mais recente do Visual Studio/Visual Studio Code com a carga de trabalho de desenvolvimento da .NET Multi-Platform App UI e as cargas de trabalho de desenvolvimento Web e ASP.NET instaladas.
Para o Android, é preciso ter:
- Um dispositivo físico desbloqueado pelo desenvolvedor ou um emulador executando a API 26+ com o Google Play Services instalado.
Para o iOS, é preciso ter:
- Uma conta de desenvolvedor ativa da Apple.
- Um Mac executando Xcode, juntamente com um certificado de desenvolvedor válido instalado em seu conjunto de chaves.
Em seguida, no iOS, você deverá ter:
Um simulador do iOS 16+ que é executado no macOS 13+ em computadores Mac com processadores Apple Silicon ou T2.
OR
Um dispositivo iOS físico registrado em sua conta de desenvolvedor (executando o iOS 13.0+).
Seu dispositivo físico registrado em sua conta de desenvolvedor da Apple e associado ao seu certificado.
Importante
O simulador iOS suporta notificações remotas no iOS 16+ quando executado no macOS 13+ em computadores Mac com processadores Apple Silicon ou T2. Se você não atender a esses requisitos de hardware, precisará de uma conta de desenvolvedor ativa da Apple e um dispositivo físico.
Para seguir este tutorial, você deve ter familiaridade com:
Embora este tutorial tenha como destino o Visual Studio, é possível segui-lo usando o Visual Studio Code em um PC ou Mac. No entanto, haverá algumas diferenças que precisam ser reconciliadas. Por exemplo, descrições de interface do usuário e fluxos de trabalho, nomes de modelo e configuração de ambiente.
Configurar serviços de notificação por push e o Hub de Notificações do Microsoft Azure
Nesta seção, você configurará o Firebase Cloud Messaging e o Apple Push Notification Service (APNS). Em seguida, você criará e configurará um Hub de Notificações do Microsoft Azure para trabalhar com esses serviços.
Criar um projeto do Firebase
Para criar um projeto do Firebase:
Em um navegador da Web, entre no console do Firebase.
No console do Firebase, selecione o botão Adicionar projeto e crie um novo projeto do Firebase, inserindo PushDemo como o Nome do projeto.
Observação
Um nome exclusivo será gerado para você. Por padrão, isso inclui uma variante minúscula do nome fornecido mais um número gerado separado por um traço. Você pode alterar isso se desejar, desde que suas edições ainda sejam globalmente exclusivas.
Depois que o projeto for criado, selecione o logotipo do Android para adicionar o Firebase a um aplicativo Android:
Na página Adicionar o Firebase ao aplicativo Android, insira um nome para o pacote, opcionalmente um apelido de aplicativo e selecione o botão Registrar aplicativo:
Na página Adicionar o Firebase ao aplicativo Android, selecione o botão Baixar google-services.json e salve o arquivo em uma pasta local antes de selecionar o botão Avançar:
Na página Adicionar o Firebase ao aplicativo Android, selecione o botão Avançar.
Na página Adicionar o Firebase ao aplicativo Android, selecione o botão Continuar para o console.
No console do Firebase, selecione o ícone Visão geral do projeto e selecione Configurações do projeto:
Nas Configurações do projeto, selecione a guia Cloud Messaging. Você verá que a API do Firebase Cloud Messaging (V1) está habilitada:
Nas Configurações do projeto, selecione a guia Contas de Serviço e, em seguida, selecione o botão Gerar nova chave privada.
Na caixa de diálogo Gerar nova chave privada, selecione o botão Gerar chave:
Um arquivo JSON será baixado, que conterá valores que você inserirá no Hub de Notificações do Microsoft Azure.
Registrar seu aplicativo iOS para notificações por push
Para enviar notificações por push para um aplicativo iOS, você precisará registrar seu aplicativo na Apple e registrar-se para notificações por push. Isso pode ser feito executando as etapas na seguinte documentação do Hub de Notificações do Microsoft Azure:
- Gerar o arquivo de solicitação de assinatura de certificado
- Registrar seu aplicativo para notificações por push
- Criar um certificado para o hub de notificações
Se você quiser receber notificações por push em um dispositivo físico, também precisará criar um perfil de provisionamento.
Importante
Para receber notificações em segundo plano no iOS, você deve adicionar o modo em segundo plano de notificações remotas ao seu aplicativo. Para obter mais informações, consulte Habilitar o recurso de notificações remotas em developer.apple.com.
Criar um Hub de Notificações do Microsoft Azure
Para criar um hub de notificações no portal do Azure:
- Em um navegador da Web, entre no portal do Azure.
- No portal do Azure, clique no botão Criar um recurso e, em seguida, pesquise e escolha Hub de Notificações antes de selecionar o botão Criar.
- Na página Hub de Notificações, execute as seguintes etapas:
No campo Assinatura, selecione o nome da assinatura do Azure que você deseja usar e selecione um grupo de recursos existente ou crie um novo.
No campo Detalhes do Namespace, insira um nome exclusivo para o novo namespace.
No campo Detalhes do Hub de Notificações, digite um nome para o hub de notificações. Isso é necessário porque um namespace contém um ou mais hubs de notificação.
Na lista suspensa Localização, selecione um valor que especifica o local no qual você deseja criar o hub de notificações.
Revise a opção Zonas de Disponibilidade. Se você escolher uma região que tenha zonas de disponibilidade, a caixa de seleção será selecionada por padrão.
Observação
As zonas de disponibilidade são um recurso pago, portanto, uma taxa adicional é acrescentada à sua camada de serviço.
Escolha uma opção de Recuperação de desastre: nenhuma, região de recuperação emparelhada ou região de recuperação flexível. Se você escolher Região de recuperação emparelhada, a região de failover será exibida. Se você selecionar Região de recuperação flexível, use a lista suspensa para escolher entre uma lista de regiões de recuperação.
Selecione o botão Criar. O hub de notificações será criado.
- No portal do Azure, navegue até o hub de notificações recém-criado e, em seguida, até a folha Gerenciar > Políticas de Acesso.
- Na folha Políticas de Acesso, anote a cadeia de conexão da política
DefaultFullSharedAccessSignature
. Você precisará disso mais tarde ao criar um serviço de back-end que se comunique com o hub de notificações.
Para obter mais informações sobre como criar um hub de notificações, consulte Criar um hub de notificações do Azure no portal do Azure.
Configurar o Firebase Cloud Messaging no hub de notificações
Para configurar o hub de notificações para se comunicar com o Firebase Cloud Messaging:
No portal do Azure, navegue até o hub de notificações e selecione a folha Configurações> Google (FCM v1).
Na folha Google (FCM v1), insira valores para os campos Chave Privada, Email do Cliente e ID do Projeto. Esses valores podem ser encontrados no arquivo JSON de chave privada baixado do Firebase Cloud Messaging:
Campo do Azure Chave JSON Exemplo de valor JSON Chave privada private_key
Esse valor deve começar com -----BEGIN PRIVATE KEY-----\n
e terminar com-----END PRIVATE KEY-----\n
.Email do Cliente client_email
firebase-adminsdk-55sfg@pushdemo-d6ab2.iam.gserviceaccount.com
ID do projeto project_id
pushdemo-d6ab2
Na folha Google (FCM v1), selecione o botão Salvar.
Configurar o Apple Push Notification Service no hub de notificações
No portal do Azure, navegue até o hub de notificações e selecione a folha Configurações> Apple (APNS). Em seguida, siga as etapas apropriadas com base na abordagem escolhida anteriormente ao criar um certificado para o hub de notificações.
Importante
Ao configurar o Modo de aplicativo, escolha apenas Produção se quiser enviar notificações por push aos usuários que compraram seu aplicativo na loja.
Opção 1 – Usar um certificado push .p12
- Na folha Apple (APNS), selecione o modo de autenticação de Certificado.
- Na folha Apple (APNS), selecione o ícone de arquivo ao lado do campo Certificado de Carregamento. Em seguida, selecione o arquivo .p12 que você exportou anteriormente e carregue-o.
- Na folha Apple (APNS), insira a senha do certificado no campo Senha, se necessário.
- Na folha Apple (APNS), selecione o modo de autenticação de Área restrita.
- Na folha Apple (APNS), selecione o botão Salvar.
Opção 2 – Usar autenticação baseada em token
- Na folha Apple (APNS), selecione o modo de autenticação de Token.
- Na folha Apple (APNS), insira os valores adquiridos anteriormente para os campos ID de Chave, ID do Pacote, ID da Equipe e Token.
- Na folha Apple (APNS), selecione o modo de autenticação de Área restrita.
- Na folha Apple (APNS), selecione o botão Salvar.
Criar um aplicativo de back-end de API Web do ASP.NET Core
Nesta seção, você criará um back-end da API Web do ASP.NET Core para lidar com instalação do dispositivo e enviar notificações para o aplicativo .NET MAUI.
Criar um projeto de API Web
Para criar um projeto de API Web:
No Visual Studio, crie um projeto de API Web do ASP.NET Core:
Na caixa de diálogo Configurar seu novo projeto, nomeie o projeto PushNotificationsAPI.
Na caixa de diálogo Informações adicionais verifique se as caixas de seleção Configurar para HTTPS e Usar controladores estão habilitadas:
Depois que o projeto tiver sido criado, pressione F5 para executar o projeto.
No momento, o aplicativo está configurado para usar o
WeatherForecastController
como olaunchUrl
, que é definido no arquivo Properties\launchSettings.json. O aplicativo será iniciado em um navegador da Web e exibirá alguns dados JSON.Importante
Quando você executa um projeto do ASP.NET Core que usa HTTPS, o Visual Studio detectará se o certificado de desenvolvimento HTTPS do ASP.NET Core está instalado no repositório de certificados do usuário local e se oferecerá para instalá-lo e confiar nele, caso esteja ausente.
Feche o navegador da Web.
No Gerenciador de Soluções, expanda a pasta Controladores e exclua WeatherForecastController.cs.
No Gerenciador de Soluções, na raiz do projeto, exclua WeatherForecast.cs.
Abra uma janela de comando e navegue até o diretório que contém o arquivo de projeto. Em seguida, execute os seguintes comandos:
dotnet user-secrets init dotnet user-secrets set "NotificationHub:Name" <value> dotnet user-secrets set "NotificationHub:ConnectionString" "<value>"
Substitua os valores de espaço reservado por seus próprios valores de cadeia de conexão e nome do Hub de Notificações do Microsoft Azure. Eles podem ser encontrados nos seguintes locais no Hub de Notificações do Microsoft Azure:
Valor de configuração Localidade NotificationHub:Name
Consulte Nome no resumo Essenciais na parte superior da página Visão Geral. NotificationHub:ConnectinString
Consulte DefaultFullSharedAccessSignature* na página Políticas de Acesso. Isso configura valores de configuração locais usando a ferramenta Gerente de Segredo. Isso separa os segredos do Hub de Notificações do Microsoft Azure da solução do Visual Studio para garantir que eles não acabem no controle do código-fonte.
Dica
Para cenários de produção, considere um serviço como Azure KeyVault para armazenar com segurança a cadeia de conexão.
Autenticar clientes com uma chave de API
Para autenticar clientes com uma chave de API:
Abra uma janela de comando e navegue até o diretório que contém o arquivo de projeto. Em seguida, execute os seguintes comandos:
dotnet user-secrets set "Authentication:ApiKey" <value>
Substitua o valor do espaço reservado pela chave de API, que pode ser qualquer valor.
No Visual Studio, adicione uma nova pasta chamada Autenticação ao seu projeto, em seguida, adicione uma nova classe chamada
ApiKeyAuthOptions
à pastaAutenticação e substitua seu código pelo seguinte código:using Microsoft.AspNetCore.Authentication; namespace PushNotificationsAPI.Authentication; public class ApiKeyAuthOptions : AuthenticationSchemeOptions { public const string DefaultScheme = "ApiKey"; public string Scheme => DefaultScheme; public string ApiKey { get; set; } }
No Visual Studio, adicione uma nova classe chamada
ApiKeyAuthHandler
à pasta Autenticação e substitua seu código pelo seguinte código:using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; using System.Security.Claims; using System.Text.Encodings.Web; namespace PushNotificationsAPI.Authentication; public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions> { const string ApiKeyIdentifier = "apikey"; public ApiKeyAuthHandler( IOptionsMonitor<ApiKeyAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder) : base(options, logger, encoder) { } protected override Task<AuthenticateResult> HandleAuthenticateAsync() { string key = string.Empty; if (Request.Headers[ApiKeyIdentifier].Any()) { key = Request.Headers[ApiKeyIdentifier].FirstOrDefault(); } else if (Request.Query.ContainsKey(ApiKeyIdentifier)) { if (Request.Query.TryGetValue(ApiKeyIdentifier, out var queryKey)) key = queryKey; } if (string.IsNullOrWhiteSpace(key)) return Task.FromResult(AuthenticateResult.Fail("No api key provided")); if (!string.Equals(key, Options.ApiKey, StringComparison.Ordinal)) return Task.FromResult(AuthenticateResult.Fail("Invalid api key.")); var identities = new List<ClaimsIdentity> { new ClaimsIdentity("ApiKeyIdentity") }; var ticket = new AuthenticationTicket(new ClaimsPrincipal(identities), Options.Scheme); return Task.FromResult(AuthenticateResult.Success(ticket)); } }
Um manipulador de autenticação é um tipo que implementa o comportamento de um esquema, que nesse caso é um esquema de chave de API personalizado.
No Visual Studio, adicione uma nova classe chamada
AuthenticationBuilderExtensions
à pasta Autenticação e substitua seu código pelo seguinte código:using Microsoft.AspNetCore.Authentication; namespace PushNotificationsAPI.Authentication; public static class AuthenticationBuilderExtensions { public static AuthenticationBuilder AddApiKeyAuth( this AuthenticationBuilder builder, Action<ApiKeyAuthOptions> configureOptions) { return builder .AddScheme<ApiKeyAuthOptions, ApiKeyAuthHandler>( ApiKeyAuthOptions.DefaultScheme, configureOptions); } }
Esse método de extensão será usado para simplificar o código de configuração do middleware no Program.cs.
No Visual Studio, abra Program.cs e atualize o código para configurar a autenticação de chave de API abaixo da chamada para o método
builder.Services.AddControllers
:using PushNotificationsAPI.Authentication; builder.Services.AddControllers(); builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme; options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme; }).AddApiKeyAuth(builder.Configuration.GetSection("Authentication").Bind);
Em Program.cs, atualize o código abaixo do comentário
// Configure the HTTP request pipeline
para chamar os métodos de extensãoUseRouting
,UseAuthentication
eMapControllers
:// Configure the HTTP request pipeline. app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
O método de extensão
UseAuthentication
registra o middleware que usa o esquema de autenticação registrado anteriormente.UseAuthentication
deve ser chamado antes de qualquer middleware que dependa da autenticação dos usuários.Observação
Embora uma chave de API não seja tão segura quanto um token, ela será suficiente para este tutorial e será facilmente configurada por meio do ASP.NET Middleware.
Adicionar e configurar serviços
Para adicionar e configurar serviços em seu aplicativo de back-end da API Web:
No Visual Studio, adicione o pacote NuGet Microsoft.Azure.NotificationHubs ao seu projeto. Esse pacote NuGet é usado para acessar o hub de notificações, encapsulado em um serviço.
No Visual Studio, adicione uma nova pasta chamada Modelos ao seu projeto, em seguida, adicione uma nova classe chamada
PushTemplates
à pastaModelos e substitua seu código pelo seguinte código:namespace PushNotificationsAPI.Models; public class PushTemplates { public class Generic { public const string Android = "{ \"message\" : { \"notification\" : { \"title\" : \"PushDemo\", \"body\" : \"$(alertMessage)\"}, \"data\" : { \"action\" : \"$(alertAction)\" } } }"; public const string iOS = "{ \"aps\" : {\"alert\" : \"$(alertMessage)\"}, \"action\" : \"$(alertAction)\" }"; } public class Silent { public const string Android = "{ \"message\" : { \"data\" : {\"message\" : \"$(alertMessage)\", \"action\" : \"$(alertAction)\"} } }"; public const string iOS = "{ \"aps\" : {\"content-available\" : 1, \"apns-priority\": 5, \"sound\" : \"\", \"badge\" : 0}, \"message\" : \"$(alertMessage)\", \"action\" : \"$(alertAction)\" }"; } }
A classe
PushTemplates
contém conteúdos de notificação tokenizadas para notificações por push genéricas e silenciosas. Esses conteúdos são definidos fora da instalação para permitir a experimentação sem precisar atualizar as instalações existentes por meio do serviço. O tratamento de alterações nas instalações dessa maneira está fora do escopo deste artigo. Em cenários de produto, considere o uso de modelos personalizados.No Visual Studio, adicione uma nova classe chamada
DeviceInstallation
à pasta Modelos e substitua seu código pelo seguinte código:using System.ComponentModel.DataAnnotations; namespace PushNotificationsAPI.Models; public class DeviceInstallation { [Required] public string InstallationId { get; set; } [Required] public string Platform { get; set; } [Required] public string PushChannel { get; set; } public IList<string> Tags { get; set; } = Array.Empty<string>(); }
No Visual Studio, adicione uma nova classe chamada
NotificationRequest
à pasta Modelos e substitua seu código pelo seguinte código:namespace PushNotificationsAPI.Models; public class NotificationRequest { public string Text { get; set; } public string Action { get; set; } public string[] Tags { get; set; } = Array.Empty<string>(); public bool Silent { get; set; } }
No Visual Studio, adicione uma nova classe chamada
NotificationHubOptions
à pasta Modelos e substitua seu código pelo seguinte código:using System.ComponentModel.DataAnnotations; namespace PushNotificationsAPI.Models; public class NotificationHubOptions { [Required] public string Name { get; set; } [Required] public string ConnectionString { get; set; } }
No Visual Studio, adicione uma nova pasta chamada Serviços ao seu projeto, em seguida, adicione uma nova interface chamada
INotificationService
à pastaServiços e substitua seu código pelo seguinte código:using PushNotificationsAPI.Models; namespace PushNotificationsAPI.Services; public interface INotificationService { Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token); Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token); Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token); }
No Visual Studio, adicione uma nova classe chamada
NotificationHubService
à pasta Serviços e substitua seu código pelo seguinte código:using Microsoft.Extensions.Options; using Microsoft.Azure.NotificationHubs; using PushNotificationsAPI.Models; namespace PushNotificationsAPI.Services; public class NotificationHubService : INotificationService { readonly NotificationHubClient _hub; readonly Dictionary<string, NotificationPlatform> _installationPlatform; readonly ILogger<NotificationHubService> _logger; public NotificationHubService(IOptions<NotificationHubOptions> options, ILogger<NotificationHubService> logger) { _logger = logger; _hub = NotificationHubClient.CreateClientFromConnectionString(options.Value.ConnectionString, options.Value.Name); _installationPlatform = new Dictionary<string, NotificationPlatform> { { nameof(NotificationPlatform.Apns).ToLower(), NotificationPlatform.Apns }, { nameof(NotificationPlatform.FcmV1).ToLower(), NotificationPlatform.FcmV1 } }; } public async Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token) { if (string.IsNullOrWhiteSpace(deviceInstallation?.InstallationId) || string.IsNullOrWhiteSpace(deviceInstallation?.Platform) || string.IsNullOrWhiteSpace(deviceInstallation?.PushChannel)) return false; var installation = new Installation() { InstallationId = deviceInstallation.InstallationId, PushChannel = deviceInstallation.PushChannel, Tags = deviceInstallation.Tags }; if (_installationPlatform.TryGetValue(deviceInstallation.Platform, out var platform)) installation.Platform = platform; else return false; try { await _hub.CreateOrUpdateInstallationAsync(installation, token); } catch { return false; } return true; } public async Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token) { if (string.IsNullOrWhiteSpace(installationId)) return false; try { await _hub.DeleteInstallationAsync(installationId, token); } catch { return false; } return true; } public async Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token) { if ((notificationRequest.Silent && string.IsNullOrWhiteSpace(notificationRequest?.Action)) || (!notificationRequest.Silent && (string.IsNullOrWhiteSpace(notificationRequest?.Text)) || string.IsNullOrWhiteSpace(notificationRequest?.Action))) return false; var androidPushTemplate = notificationRequest.Silent ? PushTemplates.Silent.Android : PushTemplates.Generic.Android; var iOSPushTemplate = notificationRequest.Silent ? PushTemplates.Silent.iOS : PushTemplates.Generic.iOS; var androidPayload = PrepareNotificationPayload( androidPushTemplate, notificationRequest.Text, notificationRequest.Action); var iOSPayload = PrepareNotificationPayload( iOSPushTemplate, notificationRequest.Text, notificationRequest.Action); try { if (notificationRequest.Tags.Length == 0) { // This will broadcast to all users registered in the notification hub await SendPlatformNotificationsAsync(androidPayload, iOSPayload, token); } else if (notificationRequest.Tags.Length <= 20) { await SendPlatformNotificationsAsync(androidPayload, iOSPayload, notificationRequest.Tags, token); } else { var notificationTasks = notificationRequest.Tags .Select((value, index) => (value, index)) .GroupBy(g => g.index / 20, i => i.value) .Select(tags => SendPlatformNotificationsAsync(androidPayload, iOSPayload, tags, token)); await Task.WhenAll(notificationTasks); } return true; } catch (Exception e) { _logger.LogError(e, "Unexpected error sending notification"); return false; } } string PrepareNotificationPayload(string template, string text, string action) => template .Replace("$(alertMessage)", text, StringComparison.InvariantCulture) .Replace("$(alertAction)", action, StringComparison.InvariantCulture); Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, CancellationToken token) { var sendTasks = new Task[] { _hub.SendFcmV1NativeNotificationAsync(androidPayload, token), _hub.SendAppleNativeNotificationAsync(iOSPayload, token) }; return Task.WhenAll(sendTasks); } Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, IEnumerable<string> tags, CancellationToken token) { var sendTasks = new Task[] { _hub.SendFcmV1NativeNotificationAsync(androidPayload, tags, token), _hub.SendAppleNativeNotificationAsync(iOSPayload, tags, token) }; return Task.WhenAll(sendTasks); } }
A expressão de marca fornecida ao método
SendTemplateNotificationsAsync
será limitada a 20 marcas se elas contiverem apenas ORs. Caso contrário, elas serão limitadas a 6 marcas. Para saber mais, veja Expressões de marca e de roteamento.No Visual Studio, abra Program.cs e atualize o código para adicionar o
NotificationHubService
como uma implementação singleton deINotificationService
abaixo da chamada para o métodobuilder.Services.AddAuthentication
:using PushNotificationsAPI.Authentication; using PushNotificationsAPI.Services; using PushNotificationsAPI.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme; options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme; }).AddApiKeyAuth(builder.Configuration.GetSection("Authentication").Bind); builder.Services.AddSingleton<INotificationService, NotificationHubService>(); builder.Services.AddOptions<NotificationHubOptions>() .Configure(builder.Configuration.GetSection("NotificationHub").Bind) .ValidateDataAnnotations(); var app = builder.Build();
Criar a API REST de notificações
Para criar a API REST de notificações:
No Visual Studio, adicione um novo Controlador chamado
NotificationsController
à pasta Controladores.Dica
Escolha o modelo Controlador de API com ações de leitura/gravação.
No arquivo NotificationsController.cs, adicione as seguintes instruções
using
na parte superior do arquivo:using System.ComponentModel.DataAnnotations; using System.Net; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using PushNotificationsAPI.Models; using PushNotificationsAPI.Services;
No arquivo NotificationsController.cs, adicione o atributo
Authorize
à classeNotificationsController
:[Authorize] [ApiController] [Route("api/[controller]")] public class NotificationsController : ControllerBase
No arquivo NotificationsController.cs, atualize o construtor
NotificationsContoller
para aceitar a instância registrada deINotificationService
como um argumento e a atribua a um membro somente leitura:readonly INotificationService _notificationService; public NotificationsController(INotificationService notificationService) { _notificationService = notificationService; }
No arquivo NotificationsContoller.cs, substitua todos os métodos pelo seguinte código:
[HttpPut] [Route("installations")] [ProducesResponseType((int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)] public async Task<IActionResult> UpdateInstallation( [Required] DeviceInstallation deviceInstallation) { var success = await _notificationService .CreateOrUpdateInstallationAsync(deviceInstallation, HttpContext.RequestAborted); if (!success) return new UnprocessableEntityResult(); return new OkResult(); } [HttpDelete()] [Route("installations/{installationId}")] [ProducesResponseType((int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)] public async Task<ActionResult> DeleteInstallation( [Required][FromRoute] string installationId) { // Probably want to ensure deletion even if the connection is broken var success = await _notificationService .DeleteInstallationByIdAsync(installationId, CancellationToken.None); if (!success) return new UnprocessableEntityResult(); return new OkResult(); } [HttpPost] [Route("requests")] [ProducesResponseType((int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)] public async Task<IActionResult> RequestPush( [Required] NotificationRequest notificationRequest) { if ((notificationRequest.Silent && string.IsNullOrWhiteSpace(notificationRequest?.Action)) || (!notificationRequest.Silent && string.IsNullOrWhiteSpace(notificationRequest?.Text))) return new BadRequestResult(); var success = await _notificationService .RequestNotificationAsync(notificationRequest, HttpContext.RequestAborted); if (!success) return new UnprocessableEntityResult(); return new OkResult(); }
No arquivo Propriedades/launchSettings.json, altere a propriedade
launchUrl
para cada perfil deweatherforecast
paraapi/notifications
.
Criar um aplicativo de API
Agora você criará um aplicativo de API no Serviço de Aplicativo do Azure para hospedar seu serviço de back-end. Isso pode ser feito diretamente do Visual Studio ou do Visual Studio Code, com a CLI do Azure, o Azure PowerShell, a Azure Developer CLI e por meio do Portal do Azure. Para obter mais informações, confira Publicar um aplicativo Web.
Para criar um aplicativo de API no portal do Azure:
Em um navegador da Web, entre no portal do Azure.
No portal do Azure, clique no botão Criar um recurso e, em seguida, pesquise e escolha Aplicativo de API antes de selecionar o botão Criar.
Na página Criar Aplicativo de API, atualize os seguintes campos antes de selecionar o botão Criar:
Campo Ação Assinatura Escolha a mesma assinatura de destino na qual você criou o hub de notificações. Grupo de recursos Escolha o mesmo grupo de recursos no qual você criou o hub de notificações. Nome Insira um nome globalmente exclusivo. Pilha de runtime Verifique se a versão mais recente do .NET está selecionada. Depois que o Aplicativo de API tiver sido provisionado, navegue até o recurso.
Na página de Visão Geral, anote o valor do domínio padrão. Essa URL é o ponto de extremidade de back-end que será consumido do seu aplicativo .NET MAUI. A URL usará o nome do aplicativo de API especificado, com o formato
https://<app_name>.azurewebsites.net
.No portal do Azure, navegue até a folha Configurações > Variáveis de ambiente e verifique se a guia Configurações do aplicativo está selecionada. Em seguida, use o botão Adicionar para adicionar as seguintes configurações:
Nome Valor Authentication:ApiKey <api_key_value> NotificationHub:Name <hub_name_value> NotificationHub:ConnectionString <hub_connection_string_value> Importante
A configuração do aplicativo
Authentication:ApiKey
foi adicionada para simplificar. Para cenários de produção, considere um serviço como Azure KeyVault para armazenar com segurança a cadeia de conexão.Depois que todas essas configurações tiverem sido inseridas, selecione o botão Aplicar e, em seguida, o botão Confirmar.
Publicar o serviço de back-end
Para publicar seu serviço de back-end no Serviço de Aplicativo do Azure:
- No Visual Studio, clique com o botão direito do mouse no projeto e selecione Publicar.
- No assistente Publicar, selecione Azure e, em seguida, o botão Avançar.
- No assistente Publicar, selecione Serviço de Aplicativo do Azure (Windows) e, em seguida, o botão Avançar.
- No assistente Publicar, siga o fluxo de autenticação para conectar o Visual Studio à sua assinatura do Azure e publicar o aplicativo.
O Visual Studio cria, empacota e publica o aplicativo no Azure e, em seguida, inicia o aplicativo no navegador padrão. Para obter mais informações, confira Publicar um aplicativo Web no ASP.NET.
Dica
Você pode baixar um perfil de publicação para seu aplicativo na folha Visão Geral do aplicativo de API no portal do Azure e, em seguida, usar o perfil no Visual Studio para publicar seu aplicativo.
Validar a API publicada
Para verificar se o aplicativo de API foi publicado corretamente, você deve usar as ferramentas REST de sua escolha para enviar uma solicitação POST
para o seguinte endereço:
https://<app_name>.azurewebsites.net/api/notifications/requests
Observação
O endereço base é https://<app_name>.azurewebsites.net
.
Configure os cabeçalhos de solicitação para incluir a chave apikey
e seu valor, defina o corpo como bruto e use o seguinte conteúdo JSON do espaço reservado:
{}
Você deve receber uma resposta 400 Bad Request
do serviço.
Observação
Ainda não é possível testar a API usando dados de solicitação válidos, pois isso exigirá informações específicas da plataforma do aplicativo .NET MAUI.
Para obter mais informações sobre como chamar APIs REST, consulte Usar arquivos .http no Visual Studio e Testar APIs Web com o Http Repl. No Visual Studio Code, é possível usar o Cliente REST para testar APIs REST.
Criar um aplicativo .NET MAUI
Nesta seção, você criará um aplicativo .NET Multi-Platform App UI (.NET MAUI) que permite que você se registre para receber notificações por push de um hub de notificações por meio do serviço de back-end e cancele o registro.
Para criar seu aplicativo .NET MAUI:
No Visual Studio, crie um novo aplicativo .NET MAUI chamado PushNotificationsDemo, usando o modelo de projeto Aplicativo .NET MAUI.
No Visual Studio, adicione uma nova pasta chamada Modelos ao projeto .NET MAUI e adicione uma nova classe chamada
DeviceInstallation
à pasta Modelos e substitua seu código pelo seguinte código:using System.Text.Json.Serialization; namespace PushNotificationsDemo.Models; public class DeviceInstallation { [JsonPropertyName("installationId")] public string InstallationId { get; set; } [JsonPropertyName("platform")] public string Platform { get; set; } [JsonPropertyName("pushChannel")] public string PushChannel { get; set; } [JsonPropertyName("tags")] public List<string> Tags { get; set; } = new List<string>(); }
No Visual Studio, adicione uma enumeração chamada
PushDemoAction
à pasta Modelos e substitua seu código pelo seguinte código:namespace PushNotificationsDemo.Models; public enum PushDemoAction { ActionA, ActionB }
No Visual Studio, adicione uma nova pasta chamada Serviços ao projeto .NET MAUI e adicione uma nova interface chamada
IDeviceInstallationService
à pasta Serviços e substitua seu código pelo seguinte código:using PushNotificationsDemo.Models; namespace PushNotificationsDemo.Services; public interface IDeviceInstallationService { string Token { get; set; } bool NotificationsSupported { get; } string GetDeviceId(); DeviceInstallation GetDeviceInstallation(params string[] tags); }
Essa interface será implementada em cada plataforma posteriormente, para fornecer as informações de
DeviceInstallation
exigidas pelo serviço de back-end.No Visual Studio, adicione uma interface chamada
INotificationRegistrationService
à pasta Serviços e substitua seu código pelo seguinte código:namespace PushNotificationsDemo.Services; public interface INotificationRegistrationService { Task DeregisterDeviceAsync(); Task RegisterDeviceAsync(params string[] tags); Task RefreshRegistrationAsync(); }
Essa interface lidará com a interação entre o cliente e o serviço de back-end.
No Visual Studio, adicione uma interface chamada
INotificationActionService
à pasta Serviços e substitua seu código pelo seguinte código:namespace PushNotificationsDemo.Services; public interface INotificationActionService { void TriggerAction(string action); }
Essa interface será usada como um mecanismo simples para centralizar o tratamento de ações de notificação.
No Visual Studio, adicione uma interface chamada
IPushDemoNotificationActionService
à pasta Serviços e substitua seu código pelo seguinte código:using PushNotificationsDemo.Models; namespace PushNotificationsDemo.Services; public interface IPushDemoNotificationActionService : INotificationActionService { event EventHandler<PushDemoAction> ActionTriggered; }
O tipo
IPushDemoNotificationActionService
é específico para este aplicativo e usa a enumeraçãoPushDemoAction
para identificar a ação que está sendo disparada usando uma abordagem fortemente tipada.No Visual Studio, adicione uma classe chamada
NotificationRegistrationService
à pasta Serviços e substitua seu código pelo seguinte código:using System.Text; using System.Text.Json; using PushNotificationsDemo.Models; namespace PushNotificationsDemo.Services; public class NotificationRegistrationService : INotificationRegistrationService { const string RequestUrl = "api/notifications/installations"; const string CachedDeviceTokenKey = "cached_device_token"; const string CachedTagsKey = "cached_tags"; string _baseApiUrl; HttpClient _client; IDeviceInstallationService _deviceInstallationService; IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = Application.Current.Windows[0].Page.Handler.MauiContext.Services.GetService<IDeviceInstallationService>()); public NotificationRegistrationService(string baseApiUri, string apiKey) { _client = new HttpClient(); _client.DefaultRequestHeaders.Add("Accept", "application/json"); _client.DefaultRequestHeaders.Add("apikey", apiKey); _baseApiUrl = baseApiUri; } public async Task DeregisterDeviceAsync() { var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey) .ConfigureAwait(false); if (cachedToken == null) return; var deviceId = DeviceInstallationService?.GetDeviceId(); if (string.IsNullOrWhiteSpace(deviceId)) throw new Exception("Unable to resolve an ID for the device."); await SendAsync(HttpMethod.Delete, $"{RequestUrl}/{deviceId}") .ConfigureAwait(false); SecureStorage.Remove(CachedDeviceTokenKey); SecureStorage.Remove(CachedTagsKey); } public async Task RegisterDeviceAsync(params string[] tags) { var deviceInstallation = DeviceInstallationService?.GetDeviceInstallation(tags); await SendAsync<DeviceInstallation>(HttpMethod.Put, RequestUrl, deviceInstallation) .ConfigureAwait(false); await SecureStorage.SetAsync(CachedDeviceTokenKey, deviceInstallation.PushChannel) .ConfigureAwait(false); await SecureStorage.SetAsync(CachedTagsKey, JsonSerializer.Serialize(tags)); } public async Task RefreshRegistrationAsync() { var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey) .ConfigureAwait(false); var serializedTags = await SecureStorage.GetAsync(CachedTagsKey) .ConfigureAwait(false); if (string.IsNullOrWhiteSpace(cachedToken) || string.IsNullOrWhiteSpace(serializedTags) || string.IsNullOrWhiteSpace(_deviceInstallationService.Token) || cachedToken == DeviceInstallationService.Token) return; var tags = JsonSerializer.Deserialize<string[]>(serializedTags); await RegisterDeviceAsync(tags); } async Task SendAsync<T>(HttpMethod requestType, string requestUri, T obj) { string serializedContent = null; await Task.Run(() => serializedContent = JsonSerializer.Serialize(obj)) .ConfigureAwait(false); await SendAsync(requestType, requestUri, serializedContent); } async Task SendAsync(HttpMethod requestType, string requestUri, string jsonRequest = null) { var request = new HttpRequestMessage(requestType, new Uri($"{_baseApiUrl}{requestUri}")); if (jsonRequest != null) request.Content = new StringContent(jsonRequest, Encoding.UTF8, "application/json"); var response = await _client.SendAsync(request).ConfigureAwait(false); response.EnsureSuccessStatusCode(); } }
No Visual Studio, adicione uma classe chamada
PushDemoNotificationActionService
à pasta Serviços e substitua seu código pelo seguinte código:using PushNotificationsDemo.Models; namespace PushNotificationsDemo.Services; public class PushDemoNotificationActionService : IPushDemoNotificationActionService { readonly Dictionary<string, PushDemoAction> _actionMappings = new Dictionary<string, PushDemoAction> { { "action_a", PushDemoAction.ActionA }, { "action_b", PushDemoAction.ActionB } }; public event EventHandler<PushDemoAction> ActionTriggered = delegate { }; public void TriggerAction(string action) { if (!_actionMappings.TryGetValue(action, out var pushDemoAction)) return; List<Exception> exceptions = new List<Exception>(); foreach (var handler in ActionTriggered?.GetInvocationList()) { try { handler.DynamicInvoke(this, pushDemoAction); } catch (Exception ex) { exceptions.Add(ex); } } if (exceptions.Any()) throw new AggregateException(exceptions); } }
No Visual Studio, adicione uma classe chamada
Config
à raiz do projeto e substitua seu código pelo seguinte código:namespace PushNotificationsDemo; public static partial class Config { public static string ApiKey = "API_KEY"; public static string BackendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT"; }
A classe
Config
é usada como uma maneira simples de manter seus segredos fora do controle do código-fonte. Você pode substituir esses valores como parte de um build automatizado ou substituí-los usando uma classe parcial local.Importante
Ao especificar o endereço base no aplicativo .NET MAUI, verifique se ele termina com um
/
.No Visual Studio, adicione uma classe chamada
Config.local_secrets
à raiz do projeto. Em seguida, substitua o código no arquivo Config.local_secrets.cs pelo seguinte código:namespace PushNotificationsDemo; public static partial class Config { static Config() { ApiKey = "<your_api_key>"; BackendServiceEndpoint = "<your_api_app_url>"; } }
Substitua os valores de espaço reservado pelos valores escolhidos ao criar o serviço de back-end. A URL
BackendServiceEndpoint
deve usar o formatohttps://<api_app_name>.azurewebsites.net/
.Dica
Lembre-se de adicionar
*.local_secrets.*
ao arquivo.gitignore
para evitar a confirmação desse arquivo no controle do código-fonte.
Criar a interface do usuário
Para criar a interface do usuário do aplicativo:
No Visual Studio, abra MainPage.xaml e substitua o
VerticalStackLayout
e seus filhos pelo seguinte XAML:<VerticalStackLayout Margin="20" Spacing="6"> <Button x:Name="registerButton" Text="Register" Clicked="OnRegisterButtonClicked" /> <Button x:Name="deregisterButton" Text="Deregister" Clicked="OnDeregisterButtonClicked" /> </VerticalStackLayout>
No Visual Studio, abra MainPage.xaml.cs e adicione uma instrução
using
para o namespacePushNotificationsDemo.Services
:using PushNotificationsDemo.Services;
Em MainPage.xaml.cs, adicione um campo de suporte
readonly
para armazenar uma referência à implementação deINotificationRegistrationService
:readonly INotificationRegistrationService _notificationRegistrationService;
No construtor
MainPage
, resolva a implementação deINotificationRegistrationService
e atribua-a ao campo de suporte_notificationRegistrationService
:public MainPage(INotificationRegistrationService service) { InitializeComponent(); _notificationRegistrationService = service; }
Na classe
MainPage
, implemente os manipuladores de eventosOnRegisterButtonClicked
eOnDeregisterButtonClicked
, chamando os métodos de registro e cancelamento de registro correspondentes no objetoINotificationRegistrationService
:void OnRegisterButtonClicked(object sender, EventArgs e) { _notificationRegistrationService.RegisterDeviceAsync() .ContinueWith((task) => { ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device registered"); }); } void OnDeregisterButtonClicked(object sender, EventArgs e) { _notificationRegistrationService.DeregisterDeviceAsync() .ContinueWith((task) => { ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device deregistered"); }); } void ShowAlert(string message) { MainThread.BeginInvokeOnMainThread(() => { DisplayAlert("Push notifications demo", message, "OK") .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }); }); }
Importante
No aplicativo, o registro e o cancelamento de registro são executados em resposta à entrada do usuário, para permitir que essa funcionalidade seja explorada e testada com mais facilidade. Em um aplicativo de produção, você normalmente executaria as ações de registro e cancelamento de registro durante o ponto apropriado no ciclo de vida do aplicativo, sem a necessidade de entrada explícita do usuário.
No Visual Studio, abra App.xaml.cs e adicione as seguintes instruções
using
:using PushNotificationsDemo.Models; using PushNotificationsDemo.Services;
Em App.xaml.cs, adicione um campo de suporte
readonly
para armazenar uma referência à implementação doIPushDemoNotificationActionService
:readonly IPushDemoNotificationActionService _actionService;
No construtor
App
, resolva a implementação deIPushDemoNotificationActionService
, atribua-a ao campo de suporte_actionService
e assine o eventoIPushDemoNotificationActionService.ActionTriggered
:public App(IPushDemoNotificationActionService service) { InitializeComponent(); _actionService = service; _actionService.ActionTriggered += NotificationActionTriggered; MainPage = new AppShell(); }
No construtor
App
, resolva a implementação deIPushDemoNotificationActionService
, atribua-a ao campo de suporte_actionService
e assine o eventoIPushDemoNotificationActionService.ActionTriggered
:public App(IPushDemoNotificationActionService service) { InitializeComponent(); _actionService = service; _actionService.ActionTriggered += NotificationActionTriggered; }
Na classe
App
, implemente o manipulador de eventos para o eventoIPushDemoNotificationActionService.ActionTriggered
:void NotificationActionTriggered(object sender, PushDemoAction e) { ShowActionAlert(e); } void ShowActionAlert(PushDemoAction action) { MainThread.BeginInvokeOnMainThread(() => { Windows[0].Page?.DisplayAlert("Push notifications demo", $"{action} action received.", "OK") .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }); }); }
O manipulador de eventos do evento
ActionTriggered
demonstra o recebimento e a propagação de ações de notificação por push. Normalmente, eles seriam tratados silenciosamente, por exemplo, navegando para uma exibição específica ou atualizando alguns dados, em vez de exibir um alerta.
Configurar o aplicativo Android
Para configurar seu aplicativo .NET MAUI no Android para receber e processar notificações por push:
No Visual Studio, adicione o pacote NuGet Xamarin.Firebase.Messaging ao seu projeto de aplicativo .NET MAUI.
No Visual Studio, adicione seu arquivo google-services.json à pasta Plataformas/Android do seu projeto de aplicativo .NET MAUI. Depois que o arquivo tiver sido adicionado ao seu projeto, ele deverá ter sido adicionado com uma ação de build de
GoogleServicesJson
:<ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'"> <GoogleServicesJson Include="Platforms\Android\google-services.json" /> </ItemGroup>
Dica
Lembre-se de adicionar
google-services.json
ao arquivo.gitignore
para evitar a confirmação desse arquivo no controle do código-fonte.No Visual Studio, edite o arquivo de projeto (*.csproj) e defina o
SupportedOSPlatformVersion
para Android como 26.0:<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">26.0</SupportedOSPlatformVersion>
O Google fez alterações nos canais de notificação do Android na API 26. Para obter mais informações, confira Canais de notificação em developer.android.com.
Na pasta Plataformas/Android do projeto, adicione uma nova classe chamada
DeviceInstallationService
e substitua seu código pelo seguinte código:using Android.Gms.Common; using PushNotificationsDemo.Models; using PushNotificationsDemo.Services; using static Android.Provider.Settings; namespace PushNotificationsDemo.Platforms.Android; public class DeviceInstallationService : IDeviceInstallationService { public string Token { get; set; } public bool NotificationsSupported => GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Platform.AppContext) == ConnectionResult.Success; public string GetDeviceId() => Secure.GetString(Platform.AppContext.ContentResolver, Secure.AndroidId); public DeviceInstallation GetDeviceInstallation(params string[] tags) { if (!NotificationsSupported) throw new Exception(GetPlayServicesError()); if (string.IsNullOrWhiteSpace(Token)) throw new Exception("Unable to resolve token for FCMv1."); var installation = new DeviceInstallation { InstallationId = GetDeviceId(), Platform = "fcmv1", PushChannel = Token }; installation.Tags.AddRange(tags); return installation; } string GetPlayServicesError() { int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Platform.AppContext); if (resultCode != ConnectionResult.Success) return GoogleApiAvailability.Instance.IsUserResolvableError(resultCode) ? GoogleApiAvailability.Instance.GetErrorString(resultCode) : "This device isn't supported."; return "An error occurred preventing the use of push notifications."; } }
Essa classe fornece uma ID exclusiva, usando o valor
Secure.AndroidId
e o conteúdo de registro do hub de notificações.Na pasta Plataformas/Android do projeto, adicione uma nova classe chamada
PushNotificationFirebaseMessagingService
e substitua seu código pelo seguinte código:using Android.App; using Firebase.Messaging; using PushNotificationsDemo.Services; namespace PushNotificationsDemo.Platforms.Android; [Service(Exported = false)] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] public class PushNotificationFirebaseMessagingService : FirebaseMessagingService { IPushDemoNotificationActionService _notificationActionService; INotificationRegistrationService _notificationRegistrationService; IDeviceInstallationService _deviceInstallationService; int _messageId; IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>()); INotificationRegistrationService NotificationRegistrationService => _notificationRegistrationService ?? (_notificationRegistrationService = IPlatformApplication.Current.Services.GetService<INotificationRegistrationService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>()); public override void OnNewToken(string token) { DeviceInstallationService.Token = token; NotificationRegistrationService.RefreshRegistrationAsync() .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }); } public override void OnMessageReceived(RemoteMessage message) { base.OnMessageReceived(message); if (message.Data.TryGetValue("action", out var messageAction)) NotificationActionService.TriggerAction(messageAction); } }
Essa classe tem um atributo
IntentFilter
que inclui o filtrocom.google.firebase.MESSAGING_EVENT
. Esse filtro permite que o Android passe mensagens de entrada para essa classe para processamento.Para obter informações sobre o formato de mensagem do Firebase Cloud Messaging, consulte Sobre mensagens FCM em developer.android.com.
No Visual Studio, abra o arquivo MainActivity.cs na pasta Plataformas/Android e adicione as seguintes instruções
using
:using Android.App; using Android.Content; using Android.Content.PM; using Android.OS; using PushNotificationsDemo.Services; using Firebase.Messaging;
Na classe
MainActivity
, defina oLaunchMode
comoSingleTop
para que oMainActivity
não seja criado novamente quando aberto:[Activity( Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
Na classe
MainActivity
, adicione campos de backup para armazenar referências às implementações deIPushDemoNotificationActionService
eIDeviceInstallationService
:IPushDemoNotificationActionService _notificationActionService; IDeviceInstallationService _deviceInstallationService;
Na classe
MainActivity
, adicione propriedades privadasNotificationActionService
eDeviceInstallationService
que recuperam suas implementações concretas do contêiner de injeção de dependência do aplicativo:IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
Na classe
MainActivity
, implemente a interfaceAndroid.Gms.Tasks.IOnSuccessListener
para recuperar e armazenar o token do Firebase:public class MainActivity : MauiAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener { public void OnSuccess(Java.Lang.Object result) { DeviceInstallationService.Token = result.ToString(); } }
Na classe
MainActivity
, adicione o métodoProcessNotificationActions
que verificará se um determinadoIntent
tem um valor extra chamadoaction
e, em seguida, disparará condicionalmente esseaction
usando a implementação deIPushDemoNotificationActionService
:void ProcessNotificationsAction(Intent intent) { try { if (intent?.HasExtra("action") == true) { var action = intent.GetStringExtra("action"); if (!string.IsNullOrEmpty(action)) NotificationActionService.TriggerAction(action); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } }
Na classe
MainActivity
, substitua o métodoOnNewIntent
para chamar o métodoProcessNotificationActions
:protected override void OnNewIntent(Intent? intent) { base.OnNewIntent(intent); ProcessNotificationsAction(intent); }
Como o
LaunchMode
doActivity
está definido comoSingleTop
, umIntent
será enviado para a instância deActivity
existente por meio da substituiçãoOnNewIntent
, em vez do métodoOnCreate
. Portanto, você deve lidar com uma intenção de entrada emOnNewIntent
eOnCreate
.Na classe
MainActivity
, substitua o métodoOnCreate
para chamar o métodoProcessNotificationActions
e recupere o token do Firebase, adicionandoMainActivity
como oIOnSuccessListener
:protected override void OnCreate(Bundle? savedInstanceState) { base.OnCreate(savedInstanceState); if (DeviceInstallationService.NotificationsSupported) FirebaseMessaging.Instance.GetToken().AddOnSuccessListener(this); ProcessNotificationsAction(Intent); }
Observação
O aplicativo deve ser registrado novamente sempre que for executado e interrompido em uma sessão de depuração para continuar recebendo notificações por push.
No Visual Studio, adicione a permissão
POST_NOTIFICATIONS
ao arquivo AndroidManifest.xml na pasta Plataformas/Android:<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Para obter mais informações sobre essa permissão, consulte Permissão de runtime de notificação em developer.android.com.
No Visual Studio, abra MainPage.xaml.cs e adicione o seguinte código à classe
MainPage
:#if ANDROID protected override async void OnAppearing() { base.OnAppearing(); PermissionStatus status = await Permissions.RequestAsync<Permissions.PostNotifications>(); } #endif
Esse código é executado no Android quando o
MainPage
é exibido e solicita que o usuário conceda a permissãoPOST_NOTIFICATIONS
. Para obter mais informações sobre as permissões do .NET MAUI, confira Permissões.
Configurar o aplicativo iOS
O simulador iOS suporta notificações remotas no iOS 16+ quando executado no macOS 13+ em computadores Mac com processadores Apple Silicon ou T2. Cada simulador gera tokens de registro exclusivos para a combinação desse simulador e o hardware Mac em que estiver sendo executado.
Importante
O simulador dá suporte ao ambiente de área restrita do Apple Push Notification Service.
As instruções a seguir pressupõem que você esteja usando hardware que dá suporte ao recebimento de notificações remotas em um simulador do iOS. Se esse não for o caso, você precisará executar o aplicativo iOS em um dispositivo físico, o que exigirá que você crie um perfil de provisionamento para seu aplicativo que inclua a funcionalidade de Notificações por Push. Em seguida, você precisará garantir que seu aplicativo seja criado usando seu certificado e perfil de provisionamento. Para obter mais informações sobre como fazer isso, consulte Configurar seu aplicativo iOS para trabalhar com os Hubs de Notificações do Microsoft Azure e siga as instruções abaixo.
Para configurar seu aplicativo .NET MAUI no iOS para receber e processar notificações por push:
No Visual Studio, edite o arquivo de projeto (*.csproj) e defina o
SupportedOSPlatformVersion
para iOS como 13.0:<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">13.0</SupportedOSPlatformVersion>
A Apple fez alterações em seu serviço de push no iOS 13. Para obter mais informações, consulte Atualizações dos Hubs de Notificações do Microsoft Azure para iOS 13.
No Visual Studio, adicione um arquivo Entitlements.plist à pasta Plataformas/iOS do projeto e adicione o seguinte XML ao arquivo:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>aps-environment</key> <string>development</string> </dict> </plist>
Isso define o direito do ambiente APS e especifica o uso do ambiente de desenvolvimento do serviço Apple Push Notification. Em aplicativos de produção, esse valor de direito deve ser definido como
production
. Para obter mais informações sobre esse direito, consulte Direitos de ambiente do APS em developer.apple.com.Para mais informações sobre como adicionar um arquivo de direitos, consulte Direitos do iOS.
No Visual Studio, adicione uma nova classe chamada
DeviceInstallationService
à pasta Plataformas/iOS do projeto e adicione o seguinte código ao arquivo:using PushNotificationsDemo.Services; using PushNotificationsDemo.Models; using UIKit; namespace PushNotificationsDemo.Platforms.iOS; public class DeviceInstallationService : IDeviceInstallationService { const int SupportedVersionMajor = 13; const int SupportedVersionMinor = 0; public string Token { get; set; } public bool NotificationsSupported => UIDevice.CurrentDevice.CheckSystemVersion(SupportedVersionMajor, SupportedVersionMinor); public string GetDeviceId() => UIDevice.CurrentDevice.IdentifierForVendor.ToString(); public DeviceInstallation GetDeviceInstallation(params string[] tags) { if (!NotificationsSupported) throw new Exception(GetNotificationsSupportError()); if (string.IsNullOrWhiteSpace(Token)) throw new Exception("Unable to resolve token for APNS"); var installation = new DeviceInstallation { InstallationId = GetDeviceId(), Platform = "apns", PushChannel = Token }; installation.Tags.AddRange(tags); return installation; } string GetNotificationsSupportError() { if (!NotificationsSupported) return $"This app only supports notifications on iOS {SupportedVersionMajor}.{SupportedVersionMinor} and above. You are running {UIDevice.CurrentDevice.SystemVersion}."; if (Token == null) return $"This app can support notifications but you must enable this in your settings."; return "An error occurred preventing the use of push notifications"; } }
Essa classe fornece uma ID exclusiva, usando o valor
UIDevice.IdentifierForVendor
e o conteúdo de registro do hub de notificações.No Visual Studio, adicione uma nova classe chamada
NSDataExtensions
à pasta Plataformas/iOS do projeto e adicione o seguinte código ao arquivo:using Foundation; using System.Text; namespace PushNotificationsDemo.Platforms.iOS; internal static class NSDataExtensions { internal static string ToHexString(this NSData data) { var bytes = data.ToArray(); if (bytes == null) return null; StringBuilder sb = new StringBuilder(bytes.Length * 2); foreach (byte b in bytes) sb.AppendFormat("{0:x2}", b); return sb.ToString().ToUpperInvariant(); } }
O método de extensão
ToHexString
será consumido pelo código que você adicionará que analisa o token de dispositivo recuperado.No Visual Studio, abra o arquivo AppDelegate.cs na pasta Plataformas/iOS e adicione as seguintes instruções
using
:using System.Diagnostics; using Foundation; using PushNotificationsDemo.Platforms.iOS; using PushNotificationsDemo.Services; using UIKit; using UserNotifications;
Na classe
AppDelegate
, adicione campos de backup para armazenar referências às implementações deIPushDemoNotificationActionService
,INotificationRegistrationService
eIDeviceInstallationService
:IPushDemoNotificationActionService _notificationActionService; INotificationRegistrationService _notificationRegistrationService; IDeviceInstallationService _deviceInstallationService;
Na classe
AppDelegate
, adicione propriedades privadasNotificationActionService
,NotificationRegistrationService
eDeviceInstallationService
que recuperam suas implementações concretas do contêiner de injeção de dependência do aplicativo:IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>()); INotificationRegistrationService NotificationRegistrationService => _notificationRegistrationService ?? (_notificationRegistrationService = IPlatformApplication.Current.Services.GetService<INotificationRegistrationService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
Na classe
AppDelegate
, adicione o métodoCompleteRegistrationAsync
para definir o valor da propriedadeIDeviceInstallationService.Token
:Task CompleteRegistrationAsync(NSData deviceToken) { DeviceInstallationService.Token = deviceToken.ToHexString(); return NotificationRegistrationService.RefreshRegistrationAsync(); }
Esse método também atualiza o registro e armazena em cache o token do dispositivo se ele tiver sido atualizado desde a última vez que foi armazenado.
Na classe
AppDelegate
, adicione o métodoProcessNotificationActions
para processar os dados de notificaçãoNSDictionary
e chamar condicionalmenteNotificationActionService.TriggerAction
:void ProcessNotificationActions(NSDictionary userInfo) { if (userInfo == null) return; try { // If your app isn't in the foreground, the notification goes to Notification Center. // If your app is in the foreground, the notification goes directly to your app and you // need to process the notification payload yourself. var actionValue = userInfo.ObjectForKey(new NSString("action")) as NSString; if (!string.IsNullOrWhiteSpace(actionValue?.Description)) NotificationActionService.TriggerAction(actionValue.Description); } catch (Exception ex) { Debug.WriteLine(ex.Message); } }
Na classe
AppDelegate
, adicione o métodoRegisteredForRemoteNotifications
passando o argumentodeviceToken
ao métodoCompleteRegistrationAsync
:[Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")] public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) { CompleteRegistrationAsync(deviceToken) .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }); }
Esse método será chamado quando o aplicativo for registrado para receber notificação remota e é usado para solicitar o token exclusivo do dispositivo, que é efetivamente o endereço do seu aplicativo no dispositivo.
Na classe
AppDelegate
, adicione o métodoReceivedRemoteNotification
passando o argumentouserInfo
ao métodoProcessNotificationActions
:[Export("application:didReceiveRemoteNotification:")] public void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) { ProcessNotificationActions(userInfo); }
Esse método será chamado quando o aplicativo receber uma notificação remota e for usado para processar a notificação.
Na classe
AppDelegate
, adicione o métodoFailedToRegisterForRemoteNotifications
para registrar os erros em log:[Export("application:didFailToRegisterForRemoteNotificationsWithError:")] public void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error) { Debug.WriteLine(error.Description); }
Esse método será chamado quando o aplicativo não se registrar para receber notificações remotas. O registro poderá falhar se o dispositivo não estiver conectado à rede, se o servidor APNS estiver inacessível ou se o aplicativo estiver configurado incorretamente.
Observação
Para cenários de produção, é necessário implementar o registro adequado e o tratamento de erros no método
FailedToRegisterForRemoteNotifications
.Na classe
AppDelegate
, adicione o métodoFinishedLaunching
para solicitar condicionalmente permissão para usar notificações e registrar-se para notificações remotas:[Export("application:didFinishLaunchingWithOptions:")] public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) { if (DeviceInstallationService.NotificationsSupported) { UNUserNotificationCenter.Current.RequestAuthorization( UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound, (approvalGranted, error) => { if (approvalGranted && error == null) { MainThread.BeginInvokeOnMainThread(() => { UIApplication.SharedApplication.RegisterForRemoteNotifications(); }); } }); } using (var userInfo = launchOptions?.ObjectForKey(UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary) { ProcessNotificationActions(userInfo); } return base.FinishedLaunching(application, launchOptions); }
Para obter informações sobre como solicitar permissão para usar notificações, consulte Solicitar permissão para usar notificações em developer.apple.com.
Para obter informações sobre notificações no iOS, consulte Notificações do Usuário em developer.apple.com.
Registrar tipos com o contêiner de injeção de dependência do aplicativo
No Visual Studio, abra MauiProgram.cs e adicione uma instrução
using
para o namespacePushNotificationsDemo.Services
:using PushNotificationsDemo.Services;
Na classe
MauiProgram
, adicione código para o método de extensãoRegisterServices
que registra os serviçosDeviceInstallationService
em cada plataforma ePushDemoNotificationActionService
eNotificationRegistrationService
multiplataforma e que retorna um objetoMauiAppBuilder
:public static MauiAppBuilder RegisterServices(this MauiAppBuilder builder) { #if IOS builder.Services.AddSingleton<IDeviceInstallationService, PushNotificationsDemo.Platforms.iOS.DeviceInstallationService>(); #elif ANDROID builder.Services.AddSingleton<IDeviceInstallationService, PushNotificationsDemo.Platforms.Android.DeviceInstallationService>(); #endif builder.Services.AddSingleton<IPushDemoNotificationActionService, PushDemoNotificationActionService>(); builder.Services.AddSingleton<INotificationRegistrationService>(new NotificationRegistrationService(Config.BackendServiceEndpoint, Config.ApiKey)); return builder; }
Na classe
MauiProgram
, adicione código para o método de extensãoRegisterViews
que registra o tipoMainPage
como um singleton e que retorna um objetoMauiAppBuilder
:public static MauiAppBuilder RegisterViews(this MauiAppBuilder builder) { builder.Services.AddSingleton<MainPage>(); return builder; }
O tipo
MainPage
é registrado porque requer uma dependênciaINotificationRegistrationService
e todos os tipos que exigem uma dependência devem ser registrados com o contêiner de injeção de dependência.Na classe
MauiProgram
, modifique o métodoCreateMauiApp
para que ele chame os métodos de extensãoRegisterServices
eRegisterViews
:public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }) .RegisterServices() .RegisterViews(); #if DEBUG builder.Logging.AddDebug(); #endif return builder.Build(); }
Para obter mais informações sobre a injeção de dependência em aplicativos .NET MAUI, confira Injeção de dependência.
Testar o aplicativo
Você pode testar seu aplicativo enviando notificações por push para o aplicativo usando o serviço de back-end ou por meio do portal do Azure.
O simulador iOS suporta notificações remotas no iOS 16+ quando executado no macOS 13+ em computadores Mac com processadores Apple Silicon ou T2. Se você não atender a esses requisitos de hardware, precisará testar seu aplicativo iOS em um dispositivo físico. No Android, você pode testar seu aplicativo em um dispositivo físico desbloqueado pelo desenvolvedor ou em um emulador.
Android e iOS exibem notificações por push em nome do aplicativo quando ele está em execução em segundo plano. Se o aplicativo estiver em execução em primeiro plano quando a notificação for recebida, o código do aplicativo determinará o comportamento. Por exemplo, você pode atualizar a interface do aplicativo para refletir as novas informações contidas na notificação.
Testar usando o serviço de back-end
Para enviar uma notificação por push de teste para seu aplicativo por meio do serviço de back-end publicado no Serviço de Aplicativo do Azure:
No Visual Studio, execute o aplicativo PushNotificationsDemo no Android ou iOS e selecione o botão Registrar.
Observação
Se você estiver testando no Android, verifique se não está em execução usando a configuração de depuração. Como alternativa, se o aplicativo tiver sido implantado anteriormente, certifique-se de que ele tenha sido forçado a fechar e inicie-o novamente no inicializador.
Na ferramenta REST de sua escolha, envie uma solicitação
POST
para o seguinte endereço:https://<app_name>.azurewebsites.net/api/notifications/requests
Configure os cabeçalhos de solicitação para incluir a chave
apikey
e seu valor, defina o corpo como bruto e use o seguinte conteúdo JSON do espaço reservado:{ "text": "Message from REST tooling!", "action": "action_a" }
A solicitação geral deve ser semelhante ao seguinte exemplo:
POST /api/notifications/requests HTTP/1.1 Host: https://<app_name>.azurewebsites.net apikey: <your_api_key> Content-Type: application/json { "text": "Message from REST tooling!", "action": "action_a" }
Na ferramenta REST de sua escolha, valide se você receber uma resposta 200 OK.
No aplicativo no Android ou iOS, um alerta deve aparecer mostrando Ação ActionA recebida.
Para obter mais informações sobre como chamar APIs REST, consulte Usar arquivos .http no Visual Studio e Testar APIs Web com o Http Repl. No Visual Studio Code, é possível usar o Cliente REST para testar APIs REST.
Testar usando o portal do Azure
Os Hubs de Notificações do Microsoft Azure permitem verificar se seu aplicativo pode receber notificações por push.
Para enviar uma notificação por push de teste para seu aplicativo por meio do portal do Azure:
No Visual Studio, execute o aplicativo PushNotificationsDemo no Android ou iOS e selecione o botão Registrar.
Observação
Se você estiver testando no Android, verifique se não está em execução usando a configuração de depuração. Como alternativa, se o aplicativo tiver sido implantado anteriormente, certifique-se de que ele tenha sido forçado a fechar e inicie-o novamente no inicializador.
No portal do Azure, navegue até o hub de notificações e selecione o botão Enviar teste na folha Visão Geral.
Na folha Enviar teste, selecione a Plataforma necessária e modifique o conteúdo.
Para Apple, use o seguinte conteúdo:
{ "aps": { "alert": "Message from Notification Hub!" }, "action": "action_a" }
Para Android, use o seguinte conteúdo:
{ "message": { "notification": { "title": "PushDemo", "body": "Message from Notification Hub!" }, "data": { "action": "action_a" } } }
O portal do Azure deve indicar que o envio da notificação foi bem-sucedido.
Para obter informações sobre o formato de mensagem do Firebase Cloud Messaging, consulte Sobre mensagens FCM em developer.android.com.
No aplicativo no Android ou iOS, um alerta deve aparecer mostrando Ação ActionA recebida.
Solução de problemas
As seções a seguir discutem os problemas comuns encontrados ao tentar consumir notificações por push em um aplicativo cliente.
Sem resposta do serviço de back-end
Ao testar localmente, verifique se o serviço de back-end está em execução e está usando a porta correta.
Se estiver testando no aplicativo de API do Azure, verifique se o serviço está em execução e foi implantado e iniciado sem erros.
Verifique se você especificou o endereço base corretamente em suas ferramentas REST ou na configuração do aplicativo .NET MAUI. O endereço base deve ser https://<api_name>.azurewebsites.net
ou https://localhost:7020
ao testar localmente.
Recebimento de um código de status 401 do serviço de back-end
Valide se você está definindo o cabeçalho de solicitação apikey
corretamente e se esse valor corresponde ao que você configurou para o serviço de back-end.
Se você receber esse erro ao testar localmente, verifique se o valor da chave definido em seu aplicativo .NET MAUI corresponde ao valor de segredos do usuário Authentication:ApiKey
usado pelo serviço de back-end.
Se você estiver testando com um aplicativo de API do Azure, verifique se o valor da chave definido em seu aplicativo .NET MAUI corresponde ao valor de configuração de aplicativo Authentication:ApiKey
definido no portal do Azure. Se você criou ou alterou essa configuração de aplicativo depois de implantar o serviço de back-end, será necessário reiniciar o serviço para que o valor entre em vigor.
Recebimento de um código de status 404 do serviço de back-end
Valide se o ponto de extremidade e o método de solicitação HTTP estão corretos:
- PUT -
https://<api_name>.azurewebsites.net/api/notifications/installations
- DELETE -
https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
- POST -
https://<api_name>.azurewebsites.net/api/notifications/requests
Ou, ao testar localmente:
- PUT -
https://localhost:7020/api/notifications/installations
- DELETE -
https://localhost:7020/api/notifications/installations/<installation_id>
- POST -
https://localhost:7020/api/notifications/requests
Importante
Ao especificar o endereço base no aplicativo .NET MAUI, verifique se ele termina com um /
. O endereço base deve ser https://<api_name>.azurewebsites.net
ou https://localhost:7020/
ao testar localmente.
Não recebimento de notificações no Android após iniciar ou parar uma sessão de depuração
Certifique-se de registrar-se sempre que iniciar uma sessão de depuração. O depurador fará com que um novo token do Firebase seja gerado e, portanto, a instalação do hub de notificações deve ser atualizada.
Não é possível registrar e uma mensagem de erro do hub de notificação é exibida
Verifique se o dispositivo de teste tem conectividade de rede. Em seguida, determine o código de status de resposta HTTP definindo um ponto de interrupção para inspecionar a propriedade StatusCode
no HttpResponse
.
Examine as sugestões de solução de problemas anteriores, quando aplicável, com base no código de status.
Defina um ponto de interrupção nas linhas que retornam códigos de status específicos para a respectiva API. Em seguida, tente chamar o serviço de back-end ao depurar localmente.
Valide se o serviço de back-end está funcionando conforme o esperado pelas ferramentas REST de sua escolha e use o conteúdo criado pelo aplicativo .NET MAUI para sua plataforma escolhida.
Examine as seções de configuração específicas da plataforma para garantir que nenhuma etapa tenha sido perdida. Verifique se os valores adequados estão sendo resolvidos para variáveis InstallationId
e Token
para sua plataforma escolhida.
Não é possível resolver uma ID para o dispositivo a mensagem de erro do dispositivo
Examine as seções de configuração específicas da plataforma para garantir que nenhuma etapa tenha sido perdida.