Compartilhar via


Notificações remotas com o Google Cloud Messaging

Aviso

O Google preteriu o GCM em 10 de abril de 2018. Os documentos e os projetos de exemplo a seguir podem não ser mais mantidos. As APIs de cliente e servidor GCM do Google serão removidas assim que 29 de maio de 2019. O Google recomenda migrar aplicativos GCM para o Firebase Cloud Messaging (FCM). Para obter mais informações sobre substituição e migração do GCM, consulte Google Cloud Messaging – PRETERIDO.

Para começar a usar notificações remotas usando o Firebase Cloud Messaging com o Xamarin, consulte Notificações remotas com FCM.

Este passo a passo fornece uma explicação passo a passo de como usar o Google Cloud Messaging para implementar notificações remotas (também chamadas de notificações por push) em um aplicativo Xamarin.Android. Ele descreve as várias classes que você deve implementar para se comunicar com o Google Cloud Messaging (GCM), explica como definir permissões no Manifesto do Android para acesso ao GCM e demonstra mensagens de ponta a ponta com um programa de teste de exemplo.

Visão geral das notificações do GCM

Neste passo a passo, criaremos um aplicativo Xamarin.Android que usa o GCM (Google Cloud Messaging) para implementar notificações remotas (também conhecidas como notificações por push). Implementaremos os vários serviços de intenção e ouvinte que usam o GCM para mensagens remotas e testaremos nossa implementação com um programa de linha de comando que simula um servidor de aplicativos.

Antes de prosseguir com este passo a passo, você deve adquirir as credenciais necessárias para usar os servidores GCM do Google; esse processo é explicado no Google Cloud Messaging. Em particular, você precisará de uma Chave de API e uma ID do Remetente para inserir no código de exemplo apresentado neste passo a passo.

Usaremos as seguintes etapas para criar um aplicativo cliente Xamarin.Android habilitado para GCM:

  1. Instale pacotes adicionais necessários para comunicações com servidores GCM.
  2. Configurar permissões de aplicativo para acesso a servidores GCM.
  3. Implemente o código para marcar para a presença do Google Play Services.
  4. Implemente um serviço de intenção de registro que negocia com o GCM para um token de registro.
  5. Implemente um serviço de ouvinte de ID de instância que escuta atualizações de token de registro do GCM.
  6. Implemente um serviço de ouvinte GCM que recebe mensagens remotas do servidor de aplicativos por meio do GCM.

Este aplicativo usará um novo recurso de GCM conhecido como mensagens de tópico. No sistema de mensagens de tópicos, o servidor de aplicativos envia uma mensagem para um tópico, em vez de para uma lista de dispositivos individuais. Os dispositivos que assinam esse tópico podem receber mensagens de tópico como notificações por push.

Quando o aplicativo cliente estiver pronto, implementaremos um aplicativo C# de linha de comando que envia uma notificação por push para nosso aplicativo cliente por meio do GCM.

Passo a passo

Para começar, vamos criar uma nova solução vazia chamada RemoteNotifications. Em seguida, vamos adicionar um novo projeto android a esta solução baseada no modelo de Aplicativo Android . Vamos chamar este projeto de ClientApp. (Se você não estiver familiarizado com a criação de projetos do Xamarin.Android, consulte Hello, Android.) O projeto ClientApp conterá o código do aplicativo cliente Xamarin.Android que recebe notificações remotas por meio do GCM.

Adicionar pacotes obrigatórios

Antes de podermos implementar nosso código de aplicativo cliente, devemos instalar vários pacotes que usaremos para comunicação com o GCM. Além disso, devemos adicionar o aplicativo Google Play Store ao nosso dispositivo se ele ainda não estiver instalado.

Adicionar o pacote GCM do Xamarin Google Play Services

Para receber mensagens do Google Cloud Messaging, a estrutura do Google Play Services deve estar presente no dispositivo. Sem essa estrutura, um aplicativo Android não pode receber mensagens de servidores GCM. O Google Play Services é executado em segundo plano enquanto o dispositivo Android está ligado, escutando silenciosamente mensagens do GCM. Quando essas mensagens chegam, o Google Play Services converte as mensagens em intenções e, em seguida, transmite essas intenções para aplicativos que se registraram para elas.

No Visual Studio, clique com o botão direito do mouse em Referências Gerenciar Pacotes > NuGet ...; em Visual Studio para Mac, clique com o botão direito do mouse em Pacotes > Adicionar Pacotes.... Pesquise Xamarin Google Play Services – GCM e instale este pacote no projeto ClientApp:

Como instalar o Google Play Services

Quando você instala o Xamarin Google Play Services – GCM, Xamarin Google Play Services – a base é instalada automaticamente. Se você receber um erro, altere a configuração Mínimo do Android do projeto para direcionar para um valor diferente de Compilar usando a versão do SDK e tente instalar o NuGet novamente.

Em seguida, edite MainActivity.cs e adicione as seguintes using instruções:

using Android.Gms.Common;
using Android.Util;

Isso disponibiliza tipos no pacote GMS do Google Play Services para nosso código e adiciona a funcionalidade de registro em log que usaremos para acompanhar nossas transações com o GMS.

Google Play Store

Para receber mensagens do GCM, o aplicativo google play store deve ser instalado no dispositivo. (Sempre que um aplicativo google play é instalado em um dispositivo, o Google Play Store também é instalado, portanto, é provável que ele já esteja instalado em seu dispositivo de teste.) Sem o Google Play, um aplicativo Android não pode receber mensagens do GCM. Se você ainda não tiver o aplicativo Google Play Store instalado em seu dispositivo, visite o site do Google Play para baixar e instalar o Google Play.

Como alternativa, você pode usar um emulador android executando o Android 2.2 ou posterior em vez de um dispositivo de teste (você não precisa instalar o Google Play Store em um emulador android). No entanto, se você usar um emulador, deverá usar Wi-Fi para se conectar ao GCM e deverá abrir várias portas no firewall Wi-Fi, conforme explicado posteriormente neste passo a passo.

Definir o Nome do Pacote

No Google Cloud Messaging, especificamos um nome de pacote para nosso aplicativo habilitado para GCM (esse nome de pacote também serve como a ID do aplicativo associada à nossa chave de API e à ID do Remetente). Vamos abrir as propriedades do projeto ClientApp e definir o nome do pacote para essa cadeia de caracteres. Neste exemplo, definimos o nome do pacote como com.xamarin.gcmexample:

Definindo o nome do pacote

Observe que o aplicativo cliente não poderá receber um token de registro do GCM se esse nome de pacote não corresponder exatamente ao nome do pacote que inserimos no console do Google Developer.

Adicionar permissões ao manifesto do Android

Um aplicativo Android deve ter as seguintes permissões configuradas antes de receber notificações do Google Cloud Messaging:

  • com.google.android.c2dm.permission.RECEIVE – Concede permissão ao nosso aplicativo para registrar e receber mensagens do Google Cloud Messaging. (O que c2dm significa? Isso significa Mensagens de Nuvem para Dispositivo, que agora é o antecessor preterido do GCM. O GCM ainda usa em muitas de suas cadeias c2dm de caracteres de permissão.)

  • android.permission.WAKE_LOCK – (Opcional) Impede que a CPU do dispositivo durma enquanto escuta uma mensagem.

  • android.permission.INTERNET – Concede acesso à Internet para que o aplicativo cliente possa se comunicar com o GCM.

  • Nome_do_pacote.permission.C2D_MESSAGE – Registra o aplicativo com Android e solicita permissão para receber exclusivamente todas as mensagens C2D (nuvem para dispositivo). O prefixo package_name é o mesmo que a ID do aplicativo.

Definiremos essas permissões no manifesto do Android. Vamos editar AndroidManifest.xml e substituir o conteúdo pelo seguinte XML:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="YOUR_PACKAGE_NAME"
    android:versionCode="1"
    android:versionName="1.0"
    android:installLocation="auto">
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" />
    <permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE"
                android:protectionLevel="signature" />
    <application android:label="ClientApp" android:icon="@drawable/Icon">
    </application>
</manifest>

No XML acima, altere YOUR_PACKAGE_NAME para o nome do pacote do projeto do aplicativo cliente. Por exemplo, com.xamarin.gcmexample.

Verificar o Google Play Services

Para este passo a passo, estamos criando um aplicativo bare-bones com um único TextView na interface do usuário. Esse aplicativo não indica diretamente a interação com o GCM. Em vez disso, vamos watch a janela de saída para ver como nosso aplicativo é handshakes com GCM e marcar a bandeja de notificação para novas notificações à medida que elas chegam.

Primeiro, vamos criar um layout para a área de mensagem. Edite Resources.layout.Main.axml e substitua o conteúdo pelo seguinte XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp">
    <TextView
        android:text=" "
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/msgText"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:padding="10dp" />
</LinearLayout>

Salve Main.axml e feche-o.

Quando o aplicativo cliente for iniciado, queremos que ele verifique se o Google Play Services está disponível antes de tentarmos entrar em contato com o GCM. Edite MainActivity.cs e substitua a declaração de count variável de instância pela seguinte declaração de variável de instância:

TextView msgText;

Em seguida, adicione o seguinte método à classe MainActivity :

public bool IsPlayServicesAvailable ()
{
    int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable (this);
    if (resultCode != ConnectionResult.Success)
    {
        if (GoogleApiAvailability.Instance.IsUserResolvableError (resultCode))
            msgText.Text = GoogleApiAvailability.Instance.GetErrorString (resultCode);
        else
        {
            msgText.Text = "Sorry, this device is not supported";
            Finish ();
        }
        return false;
    }
    else
    {
        msgText.Text = "Google Play Services is available.";
        return true;
    }
}

Esse código verifica o dispositivo para ver se o APK do Google Play Services está instalado. Se ele não estiver instalado, uma mensagem será exibida na área de mensagem que instrui o usuário a baixar um APK da Google Play Store (ou habilitá-lo nas configurações do sistema do dispositivo). Como queremos executar esse marcar quando o aplicativo cliente for iniciado, adicionaremos uma chamada a esse método no final de OnCreate.

Em seguida, substitua o OnCreate método pelo seguinte código:

protected override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);

    SetContentView (Resource.Layout.Main);
    msgText = FindViewById<TextView> (Resource.Id.msgText);

    IsPlayServicesAvailable ();
}

Esse código verifica a presença do APK do Google Play Services e grava o resultado na área de mensagem.

Vamos recompilar e executar o aplicativo completamente. Você deverá ver uma tela semelhante à seguinte captura de tela:

O Google Play Services está disponível

Se você não obtiver esse resultado, verifique se o APK do Google Play Services está instalado em seu dispositivo e se o pacote Xamarin Google Play Services – GCM foi adicionado ao seu projeto ClientApp , conforme explicado anteriormente. Se você receber um erro de build, tente limpar a Solução e compilar o projeto novamente.

Em seguida, escreveremos código para entrar em contato com o GCM e obter um token de registro.

Registrar-se no GCM

Antes que o aplicativo possa receber notificações remotas do servidor de aplicativos, ele deve se registrar no GCM e obter de volta um token de registro. O trabalho de registrar nosso aplicativo com o GCM é tratado por um IntentService que criamos. Nosso IntentService executa as seguintes etapas:

  1. Usa a API InstanceID para gerar tokens de segurança que autorizam nosso aplicativo cliente a acessar o servidor de aplicativos. Em troca, recebemos de volta um token de registro do GCM.

  2. Encaminha o token de registro para o servidor de aplicativos (se o servidor de aplicativo exigir).

  3. Assina um ou mais canais de tópico de notificação.

Depois de implementarmos esse IntentService, vamos testá-lo para ver se recuperamos um token de registro do GCM.

Adicione um novo arquivo chamado RegistrationIntentService.cs e substitua o código do modelo pelo seguinte:

using System;
using Android.App;
using Android.Content;
using Android.Util;
using Android.Gms.Gcm;
using Android.Gms.Gcm.Iid;

namespace ClientApp
{
    [Service(Exported = false)]
    class RegistrationIntentService : IntentService
    {
        static object locker = new object();

        public RegistrationIntentService() : base("RegistrationIntentService") { }

        protected override void OnHandleIntent (Intent intent)
        {
            try
            {
                Log.Info ("RegistrationIntentService", "Calling InstanceID.GetToken");
                lock (locker)
                {
                    var instanceID = InstanceID.GetInstance (this);
                    var token = instanceID.GetToken (
                        "YOUR_SENDER_ID", GoogleCloudMessaging.InstanceIdScope, null);

                    Log.Info ("RegistrationIntentService", "GCM Registration Token: " + token);
                    SendRegistrationToAppServer (token);
                    Subscribe (token);
                }
            }
            catch (Exception e)
            {
                Log.Debug("RegistrationIntentService", "Failed to get a registration token");
                return;
            }
        }

        void SendRegistrationToAppServer (string token)
        {
            // Add custom implementation here as needed.
        }

        void Subscribe (string token)
        {
            var pubSub = GcmPubSub.GetInstance(this);
            pubSub.Subscribe(token, "/topics/global", null);
        }
    }
}

No código de exemplo acima, altere YOUR_SENDER_ID para o número da ID do Remetente do projeto do aplicativo cliente. Para obter a ID do remetente para seu projeto:

  1. Faça logon no Console do Google Cloud e selecione o nome do projeto no menu suspenso. No painel Informações do projeto exibido para seu projeto, clique em Ir para as configurações do projeto:

    Selecionando o projeto XamarinGCM

  2. Na página Configurações , localize o Número do projeto – esta é a ID do Remetente do seu projeto:

    Número do projeto exibido

Queremos iniciar nosso RegistrationIntentService quando nosso aplicativo começar a ser executado. Edite MainActivity.cs e modifique o OnCreate método para que seja RegistrationIntentService iniciado depois que marcar para a presença do Google Play Services:

protected override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);

    SetContentView(Resource.Layout.Main);
    msgText = FindViewById<TextView> (Resource.Id.msgText);

    if (IsPlayServicesAvailable ())
    {
        var intent = new Intent (this, typeof (RegistrationIntentService));
        StartService (intent);
    }
}

Agora vamos dar uma olhada em cada seção de RegistrationIntentService para entender como ela funciona.

Primeiro, anotamos nosso RegistrationIntentService com o seguinte atributo para indicar que nosso serviço não deve ser instanciado pelo sistema:

[Service (Exported = false)]

O RegistrationIntentService construtor nomeia o thread de trabalho RegistrationIntentService para facilitar a depuração.

public RegistrationIntentService() : base ("RegistrationIntentService") { }

A funcionalidade principal de RegistrationIntentService reside no OnHandleIntent método . Vamos examinar esse código para ver como ele registra nosso aplicativo com o GCM.

Solicitar um token de registro

OnHandleIntent primeiro chama o método InstanceID.GetToken do Google para solicitar um token de registro do GCM. Encapsulamos esse código em um lock para proteger contra a possibilidade de várias intenções de registro ocorrerem simultaneamente – o lock garante que essas intenções sejam processadas sequencialmente. Se não conseguirmos obter um token de registro, uma exceção será gerada e registraremos um erro. Se o registro for bem-sucedido, token será definido como o token de registro que obtivemos do GCM:

static object locker = new object ();
...
try
{
    lock (locker)
    {
        var instanceID = InstanceID.GetInstance (this);
        var token = instanceID.GetToken (
            "YOUR_SENDER_ID", GoogleCloudMessaging.InstanceIdScope, null);
        ...
    }
}
catch (Exception e)
{
    Log.Debug ...

Encaminhar o token de registro para o Servidor de Aplicativos

Se recebermos um token de registro (ou seja, nenhuma exceção foi gerada), chamaremos SendRegistrationToAppServer para associar o token de registro do usuário à conta do lado do servidor (se houver) mantida pelo nosso aplicativo. Como essa implementação depende do design do servidor de aplicativos, um método vazio é fornecido aqui:

void SendRegistrationToAppServer (string token)
{
    // Add custom implementation here as needed.
}

Em alguns casos, o servidor de aplicativos não precisa do token de registro do usuário; nesse caso, esse método pode ser omitido. Quando um token de registro é enviado para o servidor de aplicativos, SendRegistrationToAppServer deve manter um booliano para indicar se o token foi enviado ao servidor. Se esse booliano for false, SendRegistrationToAppServer enviará o token para o servidor de aplicativos ; caso contrário, o token já foi enviado ao servidor de aplicativos em uma chamada anterior.

Assinar o Tópico de Notificação

Em seguida, chamamos nosso Subscribe método para indicar ao GCM que queremos assinar um tópico de notificação. No Subscribe, chamamos a API GcmPubSub.Subscribe para assinar nosso aplicativo cliente para todas as mensagens em /topics/global:

void Subscribe (string token)
{
    var pubSub = GcmPubSub.GetInstance(this);
    pubSub.Subscribe(token, "/topics/global", null);
}

O servidor de aplicativos deve enviar mensagens de notificação para /topics/global se quisermos recebê-las. Observe que o nome do tópico em /topics pode ser o que você quiser, desde que o servidor de aplicativos e o aplicativo cliente concordem com esses nomes. (Aqui, escolhemos o nome global para indicar que queremos receber mensagens em todos os tópicos compatíveis com o servidor de aplicativos.)

Implementar um serviço de ouvinte de ID de instância

Os tokens de registro são exclusivos e seguros; no entanto, o aplicativo cliente (ou GCM) pode precisar atualizar o token de registro no caso de reinstalação do aplicativo ou de um problema de segurança. Por esse motivo, devemos implementar um InstanceIdListenerService que responda às solicitações de atualização de token do GCM.

Adicione um novo arquivo chamado InstanceIdListenerService.cs e substitua o código do modelo pelo seguinte:

using Android.App;
using Android.Content;
using Android.Gms.Gcm.Iid;

namespace ClientApp
{
    [Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]
    class MyInstanceIDListenerService : InstanceIDListenerService
    {
        public override void OnTokenRefresh()
        {
            var intent = new Intent (this, typeof (RegistrationIntentService));
            StartService (intent);
        }
    }
}

Anote InstanceIdListenerService com o seguinte atributo para indicar que o serviço não deve ser instanciado pelo sistema e que ele pode receber solicitações de atualização do token de registro do GCM (também chamado de ID da instância):

[Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]

O OnTokenRefresh método em nosso serviço inicia o RegistrationIntentService para que ele possa interceptar o novo token de registro.

Registro de teste com GCM

Vamos recompilar completamente e executar o aplicativo. Se você receber com êxito um token de registro do GCM, o token de registro deverá ser exibido na janela de saída. Por exemplo:

D/Mono    ( 1934): Assembly Ref addref ClientApp[0xb4ac2400] -> Xamarin.GooglePlayServices.Gcm[0xb4ac2640]: 2
I/RegistrationIntentService( 1934): Calling InstanceID.GetToken
I/RegistrationIntentService( 1934): GCM Registration Token: f8LdveCvXig:APA91bFIsjUAbP-V8TPQdLR89qQbEJh1SYG38AcCbBUf34z5gSdUc5OsXrgs93YFiGcRSRafPfzkz23lf3-LvYV1CwrFheMjHgwPeFSh12MywnRIhz

Manipular mensagens downstream

O código que implementamos até agora é apenas o código de "configuração"; ele verifica se o Google Play Services está instalado e negocia com o GCM e o servidor de aplicativos para preparar nosso aplicativo cliente para receber notificações remotas. No entanto, ainda não implementamos o código que realmente recebe e processa mensagens de notificação downstream. Para fazer isso, devemos implementar um Serviço de Ouvinte do GCM. Esse serviço recebe mensagens de tópico do servidor de aplicativos e as transmite localmente como notificações. Depois de implementarmos esse serviço, criaremos um programa de teste para enviar mensagens ao GCM para que possamos ver se nossa implementação funciona corretamente.

Adicionar um ícone de notificação

Primeiro, vamos adicionar um pequeno ícone que aparecerá na área de notificação quando nossa notificação for iniciada. Você pode copiar esse ícone para seu projeto ou criar seu próprio ícone personalizado. Nomearemos o arquivo de ícone ic_stat_button_click.png e o copiaremos para a pasta Recursos/desenháveis . Lembre-se de usar Adicionar > Item Existente ... para incluir esse arquivo de ícone em seu projeto.

Implementar um serviço de ouvinte do GCM

Adicione um novo arquivo chamado GcmListenerService.cs e substitua o código do modelo pelo seguinte:

using Android.App;
using Android.Content;
using Android.OS;
using Android.Gms.Gcm;
using Android.Util;

namespace ClientApp
{
    [Service (Exported = false), IntentFilter (new [] { "com.google.android.c2dm.intent.RECEIVE" })]
    public class MyGcmListenerService : GcmListenerService
    {
        public override void OnMessageReceived (string from, Bundle data)
        {
            var message = data.GetString ("message");
            Log.Debug ("MyGcmListenerService", "From:    " + from);
            Log.Debug ("MyGcmListenerService", "Message: " + message);
            SendNotification (message);
        }

        void SendNotification (string message)
        {
            var intent = new Intent (this, typeof(MainActivity));
            intent.AddFlags (ActivityFlags.ClearTop);
            var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);

            var notificationBuilder = new Notification.Builder(this)
                .SetSmallIcon (Resource.Drawable.ic_stat_ic_notification)
                .SetContentTitle ("GCM Message")
                .SetContentText (message)
                .SetAutoCancel (true)
                .SetContentIntent (pendingIntent);

            var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
            notificationManager.Notify (0, notificationBuilder.Build());
        }
    }
}

Vamos dar uma olhada em cada seção da nossa GcmListenerService para entender como ela funciona.

Primeiro, anotamos GcmListenerService com um atributo para indicar que esse serviço não deve ser instanciado pelo sistema e incluímos um filtro de intenção para indicar que ele recebe mensagens GCM:

[Service (Exported = false), IntentFilter (new [] { "com.google.android.c2dm.intent.RECEIVE" })]

Quando GcmListenerService recebe uma mensagem do GCM, o OnMessageReceived método é invocado. Esse método extrai o conteúdo da mensagem do passado, registra o conteúdo da mensagem (para que possamos exibi-lo Bundlena janela de saída) e chama SendNotification para iniciar uma notificação local com o conteúdo da mensagem recebida:

var message = data.GetString ("message");
Log.Debug ("MyGcmListenerService", "From:    " + from);
Log.Debug ("MyGcmListenerService", "Message: " + message);
SendNotification (message);

O SendNotification método usa Notification.Builder para criar a notificação e, em seguida, usa o NotificationManager para iniciar a notificação. Efetivamente, isso converte a mensagem de notificação remota em uma notificação local a ser apresentada ao usuário. Para obter mais informações sobre como usar Notification.Builder e NotificationManager, consulte Notificações locais.

Declarar o receptor no manifesto

Antes de podermos receber mensagens do GCM, devemos declarar o ouvinte do GCM no manifesto do Android. Vamos editar AndroidManifest.xml e substituir a <application> seção pelo seguinte XML:

<application android:label="RemoteNotifications" android:icon="@drawable/Icon">
    <receiver android:name="com.google.android.gms.gcm.GcmReceiver"
              android:exported="true"
              android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="YOUR_PACKAGE_NAME" />
        </intent-filter>
    </receiver>
</application>

No XML acima, altere YOUR_PACKAGE_NAME para o nome do pacote do projeto do aplicativo cliente. Em nosso exemplo passo a passo, o nome do pacote é com.xamarin.gcmexample.

Vamos examinar o que cada configuração neste XML faz:

Configuração Descrição
com.google.android.gms.gcm.GcmReceiver Declara que nosso aplicativo implementa um receptor GCM que captura e processa mensagens de notificação por push recebidas.
com.google.android.c2dm.permission.SEND Declara que somente servidores GCM podem enviar mensagens diretamente para o aplicativo.
com.google.android.c2dm.intent.RECEIVE Publicidade de filtro de intenção que nosso aplicativo manipula mensagens de transmissão do GCM.
com.google.android.c2dm.intent.REGISTRATION Anúncio de filtro de intenção de que nosso aplicativo lida com novas intenções de registro (ou seja, implementamos um Serviço de Ouvinte de ID de Instância).

Como alternativa, você pode decorar GcmListenerService com esses atributos em vez de especificá-los em XML; aqui, os especificamos em AndroidManifest.xml para que os exemplos de código sejam mais fáceis de seguir.

Criar um remetente de mensagens para testar o aplicativo

Vamos adicionar um projeto de aplicativo de console da área de trabalho C# à Solução e chamá-lo de MessageSender. Usaremos esse aplicativo de console para simular um servidor de aplicativos – ele enviará mensagens de notificação ao ClientApp por meio do GCM.

Adicionar o pacote Json.NET

Neste aplicativo de console, estamos criando um conteúdo JSON que contém a mensagem de notificação que desejamos enviar ao aplicativo cliente. Usaremos o pacote Json.NET no MessageSender para facilitar a compilação do objeto JSON exigido pelo GCM. No Visual Studio, clique com o botão direito do mouse em Referências Gerenciar Pacotes > NuGet ...; em Visual Studio para Mac, clique com o botão direito do mouse em Pacotes > Adicionar Pacotes....

Vamos pesquisar o pacote Json.NET e instalá-lo no projeto:

Instalando o pacote Json.NET

Adicionar uma referência ao System.Net.Http

Também precisaremos adicionar uma referência a para System.Net.Http que possamos instanciar um HttpClient para enviar nossa mensagem de teste ao GCM. No projeto MessageSender , clique com o botão direito do mouse em Referências > Adicionar Referência e role para baixo até ver System.Net.Http. Coloque uma marca de marcar ao lado de System.Net.Http e clique em OK.

Implementar o código que envia uma mensagem de teste

No MessageSender, edite Program.cs e substitua o conteúdo pelo seguinte código:

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace MessageSender
{
    class MessageSender
    {
        public const string API_KEY = "YOUR_API_KEY";
        public const string MESSAGE = "Hello, Xamarin!";

        static void Main (string[] args)
        {
            var jGcmData = new JObject();
            var jData = new JObject();

            jData.Add ("message", MESSAGE);
            jGcmData.Add ("to", "/topics/global");
            jGcmData.Add ("data", jData);

            var url = new Uri ("https://gcm-http.googleapis.com/gcm/send");
            try
            {
                using (var client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Accept.Add(
                        new MediaTypeWithQualityHeaderValue("application/json"));

                    client.DefaultRequestHeaders.TryAddWithoutValidation (
                        "Authorization", "key=" + API_KEY);

                    Task.WaitAll(client.PostAsync (url,
                        new StringContent(jGcmData.ToString(), Encoding.Default, "application/json"))
                            .ContinueWith(response =>
                            {
                                Console.WriteLine(response);
                                Console.WriteLine("Message sent: check the client device notification tray.");
                            }));
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Unable to send GCM message:");
                Console.Error.WriteLine(e.StackTrace);
            }
        }
    }
}

No código acima, altere YOUR_API_KEY para a Chave de API do projeto do aplicativo cliente.

Esse servidor de aplicativos de teste envia a seguinte mensagem formatada em JSON para o GCM:

{
  "to": "/topics/global",
  "data": {
    "message": "Hello, Xamarin!"
  }
}

O GCM, por sua vez, encaminha essa mensagem para o aplicativo cliente. Vamos criar o MessageSender e abrir uma janela do console em que podemos executá-lo na linha de comando.

Experimente!

Agora estamos prontos para testar nosso aplicativo cliente. Se você estiver usando um emulador ou se o dispositivo estiver se comunicando com o GCM por Wi-Fi, você deverá abrir as seguintes portas TCP no firewall para mensagens GCM passarem: 5228, 5229 e 5230.

Inicie o aplicativo cliente e watch a janela de saída. Depois que o RegistrationIntentService receber com êxito um token de registro do GCM, a janela de saída deverá exibir o token com a saída de log semelhante ao seguinte:

I/RegistrationIntentService(16103): GCM Registration Token: eX9ggabZV1Q:APA91bHjBnQXMUeBOT6JDiLpRt8m2YWtY ...

Neste ponto, o aplicativo cliente está pronto para receber uma mensagem de notificação remota. Na linha de comando, execute o programa MessageSender.exe para enviar uma mensagem de notificação "Olá, Xamarin" para o aplicativo cliente. Se você ainda não criou o projeto MessageSender , faça isso agora.

Para executar MessageSender.exe no Visual Studio, abra um prompt de comando, altere para o diretório MessageSender/bin/Debug e execute o comando diretamente:

MessageSender.exe

Para executar MessageSender.exe em Visual Studio para Mac, abra uma sessão do Terminal, altere para MessageSender/bin/Depurar o diretório e use mono para executar MessageSender.exe

mono MessageSender.exe

Pode levar até um minuto para a mensagem se propagar por meio do GCM e voltar para o aplicativo cliente. Se a mensagem for recebida com êxito, veremos uma saída semelhante à seguinte na janela de saída:

D/MyGcmListenerService(16103): From:    /topics/global
D/MyGcmListenerService(16103): Message: Hello, Xamarin!

Além disso, você deve observar que um novo ícone de notificação apareceu na bandeja de notificação:

O ícone de notificação é exibido no dispositivo

Ao abrir a bandeja de notificação para exibir notificações, você deverá ver nossa notificação remota:

A mensagem de notificação é exibida

Parabéns, seu aplicativo recebeu sua primeira notificação remota!

Observe que as mensagens GCM não serão mais recebidas se o aplicativo for interrompido à força. Para retomar as notificações após uma parada forçada, o aplicativo deve ser reiniciado manualmente. Para obter mais informações sobre essa política do Android, consulte Iniciar controles em aplicativos parados e esta postagem de estouro de pilha.

Resumo

Este passo a passo detalhou as etapas para implementar notificações remotas em um aplicativo Xamarin.Android. Ele descreveu como instalar pacotes adicionais necessários para comunicações do GCM e explicou como configurar permissões de aplicativo para acesso a servidores GCM. Ele forneceu um código de exemplo que ilustra como marcar para a presença do Google Play Services, como implementar um serviço de intenção de registro e um serviço de ouvinte de ID de instância que negocia com o GCM para um token de registro e como implementar um serviço ouvinte do GCM que recebe e processa mensagens de notificação remotas. Por fim, implementamos um programa de teste de linha de comando para enviar notificações de teste para nosso aplicativo cliente por meio do GCM.