Configurar um app cliente do Firebase Cloud Messaging com C++

Para criar um aplicativo cliente multiplataforma Firebase Cloud Messaging com C++, use a API Firebase Cloud Messaging. O SDK do C++ funciona com as plataformas Android e Apple, sendo necessárias configurações a mais em cada plataforma.

Configurar o Firebase e o SDK do FCM

Android

  1. Adicione o Firebase ao seu projeto para C++ se ainda não tiver feito isso.

    • Nas instruções de configuração vinculadas, revise os requisitos de dispositivo e aplicativo para usar o SDK do Firebase para C++, incluindo a recomendação de usar o CMake para criar seu aplicativo.

    • No arquivo build.gradlepara envolvidos no projeto, inclua o repositório Maven do Google nas seções buildscript e allprojects.

  2. Crie um objeto do app Firebase, transferindo o ambiente JNI e a atividade:

    app = ::firebase::App::Create(::firebase::AppOptions(), jni_env, activity);

  3. Defina uma classe que implementa a interface firebase::messaging::Listener.

  4. Inicialize o FCM, transferindo o app e um Listener construído:

    ::firebase::messaging::Initialize(app, listener);

  5. Os aplicativos que confiam no SDK do Google Play Services devem verificar se há um APK do Google Play Services compatível no dispositivo antes de acessar os recursos. Para saber mais, consulte Verificar APK do Google Play Services.

iOS+

  1. Você precisa de um certificado de APNs válido. Se você ainda não tiver um, crie um no Apple Developer Member Center.
  2. Adicione o Firebase ao seu projeto para C++ se ainda não tiver feito isso. Então, para configurar seu projeto para o FCM:
    1. No Podfile do projeto, adicione a dependência do FCM:
      pod 'FirebaseMessaging'
    2. Arraste os frameworks firebase.framework e firebase_messaging.framework para seu projeto do Xcode usando o SDK do Firebase para C++.
  3. Configure o projeto do Xcode para ativar as notificações push:

    1. Selecione o projeto no Navigator area.
    2. Selecione o destino do projeto em Editor area.
    3. Selecione a guia General em Editor.

      1. Role para baixo até Linked Frameworks and Libraries, depois clique no botão + para adicionar frameworks.
      2. Na janela exibida, role até UserNotifications.framework e clique nessa entrada. Depois, clique em Add.

        Esse framework aparece apenas no Xcode v8 e posterior e é obrigatório por essa biblioteca.

    4. Selecione a guia Capabilities em Editor.

      1. Mude Push Notifications para On.
      2. Role para baixo até Background Modes e mude para On.
      3. Selecione Remote notifications em Background Modes.
  4. Crie um objeto de app Firebase:

    app = ::firebase::App::Create(::firebase::AppOptions());

  5. Defina uma classe que implementa a interface firebase::messaging::Listener.

  6. Inicialize o Firebase Cloud Messaging, transferindo o app e um Listener construído:

    ::firebase::messaging::Initialize(app, listener);

Acessar o token de registro do dispositivo

Na inicialização da biblioteca do Firebase Cloud Messaging, um token de registro é solicitado para a instância do app cliente. O app recebe o token com o callback OnTokenReceived, que deve ser definido na classe que implementa firebase::messaging::Listener.

Para direcionar o app para esse dispositivo específico, você precisará ter acesso a esse token.

Observação sobre entrega de mensagens no Android

Quando o aplicativo não está em execução e um usuário toca em uma notificação, por padrão, a mensagem não é encaminhada por meio dos callbacks incorporados do FCM. Nesse caso, os payloads das mensagens são recebidos por meio de um Intent usado para iniciar o aplicativo. Para que o FCM encaminhe essas mensagens recebidas para o callback da biblioteca C++, é necessário modificar o método onNewIntent na sua atividade e transmitir Intent para MessageForwardingService.

import com.google.firebase.messaging.MessageForwardingService;

class MyActivity extends Activity {
  private static final String TAG = "MyActvity";

  @Override
  protected void onNewIntent(Intent intent) {
    Log.d(TAG, "A message was sent to this app while it was in the background.");
    Intent message = new Intent(this, MessageForwardingService.class);
    message.setAction(MessageForwardingService.ACTION_REMOTE_INTENT);
    message.putExtras(intent);
    message.setData(intent.getData());
    // For older versions of Firebase C++ SDK (< 7.1.0), use `startService`.
    // startService(message);
    MessageForwardingService.enqueueWork(this, message);
  }
}

As mensagens recebidas enquanto o aplicativo está em segundo plano têm o conteúdo do campo de notificação usado para preencher a notificação da bandeja do sistema, mas esse conteúdo não será comunicado ao FCM. Ou seja, Message::notification será nulo.

Em resumo:

Estado do app Notificação Dados Ambos
Primeiro plano OnMessageReceived OnMessageReceived OnMessageReceived
Segundo plano Bandeja do sistema OnMessageReceived Notificação: bandeja do sistema
Dados: nos extras do intent.

Processamento de mensagens personalizadas no Android

Por padrão, as notificações enviadas para o app são transmitidas para ::firebase::messaging::Listener::OnMessageReceived, mas, em alguns casos, talvez você queira modificar o comportamento padrão. Para fazer isso no Android, é necessário gravar classes personalizadas que ampliam com.google.firebase.messaging.cpp.ListenerService além de atualizar os AndroidManifest.xml do projeto.

Modificar os métodos ListenerService.

ListenerService é a classe Java que intercepta as mensagens recebidas enviadas para o app e as encaminha para a biblioteca C ++. Quando o app está em primeiro plano (ou em segundo plano e recebe um payload somente de dados), as mensagens são transmitidas por meio de um dos callbacks fornecidos nessa classe. Para adicionar um comportamento personalizado ao processamento de mensagens, será necessário estender o ListenerService padrão do FCM:

import com.google.firebase.messaging.cpp.ListenerService;

class MyListenerService extends ListenerService {

Ao modificar o método ListenerService.onMessageReceived, é possível realizar ações com base no objeto RemoteMessage recebido e acessar os dados da mensagem:

@Override
public void onMessageReceived(RemoteMessage message) {
  Log.d(TAG, "A message has been received.");
  // Do additional logic...
  super.onMessageReceived(message);
}

ListenerService também tem alguns outros métodos que são usados com menos frequência. Eles também podem ser modificados. Para mais informações, consulte a referência de FirebaseMessagingService.

@Override
public void onDeletedMessages() {
  Log.d(TAG, "Messages have been deleted on the server.");
  // Do additional logic...
  super.onDeletedMessages();
}

@Override
public void onMessageSent(String messageId) {
  Log.d(TAG, "An outgoing message has been sent.");
  // Do additional logic...
  super.onMessageSent(messageId);
}

@Override
public void onSendError(String messageId, Exception exception) {
  Log.d(TAG, "An outgoing message encountered an error.");
  // Do additional logic...
  super.onSendError(messageId, exception);
}

Atualizar AndroidManifest.xml

Com suas classes personalizadas já escritas, é necessário incluí-las no AndroidManifest.xml para que tenham efeito. O manifesto precisa incluir as ferramentas de mesclagem declarando o atributo adequado dentro da tag <manifest> da seguinte maneira:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.firebase.messaging.cpp.samples"
    xmlns:tools="http://schemas.android.com/tools">

No arquivo firebase_messaging_cpp.aar há um arquivo AndroidManifest.xml que declara o ListenerService padrão do FCM. Normalmente, esse manifesto é mesclado com o manifesto específico do projeto, o que permite a execução de ListenerService. Esse ListenerService precisa ser substituído pelo serviço de listener personalizado. Isso é feito com a remoção do ListenerService padrão e a adição do serviço personalizado, o que pode ser feito com as seguintes linhas no arquivo AndroidManifest.xml do projeto:

<service android:name="com.google.firebase.messaging.cpp.ListenerService"
         tools:node="remove" />
<service android:name="com.google.firebase.messaging.cpp.samples.MyListenerService"
         android:exported="false">
  <intent-filter>
    <action android:name="com.google.firebase.MESSAGING_EVENT"/>
  </intent-filter>
</service>

As novas versões do SDK do Firebase para C++ (7.1.0 em diante) usam JobIntentService, que requer modificações adicionais no arquivo AndroidManifest.xml.

<service android:name="com.google.firebase.messaging.MessageForwardingService"
     android:permission="android.permission.BIND_JOB_SERVICE"
     android:exported="false" >
</service>

Impedir a inicialização automática

O FCM gera um token de registro para segmentação por dispositivo. Quando um token é gerado, a biblioteca faz upload dos dados de configuração e do identificador para o Firebase. Se você quiser receber uma confirmação antes de usar o token, é possível impedir a geração dele desativando o FCM (e o Analytics no Android). Para isso, adicione um valor de metadados ao Info.plist, e não ao GoogleService-Info.plist, nas plataformas Apple ou ao AndroidManifest.xml no Android:

Android

<?xml version="1.0" encoding="utf-8"?>
<application>
  <meta-data android:name="firebase_messaging_auto_init_enabled"
             android:value="false" />
  <meta-data android:name="firebase_analytics_collection_enabled"
             android:value="false" />
</application>

Swift

FirebaseMessagingAutoInitEnabled = NO

Para reativar o FCM, é possível fazer uma chamada de ambiente de execução:

::firebase::messaging::SetTokenRegistrationOnInitEnabled(true);

Depois de definido, esse valor persiste às reinicializações do app.

O FCM permite que sejam enviadas mensagens com um link direto para seu aplicativo. Para receber mensagens que contenham um link direto, é necessário adicionar um novo filtro de intent à atividade que processa links diretos para seu aplicativo. O filtro de intent precisa capturar links diretos do seu domínio. Se as suas mensagens não contiverem um link direto, essa configuração não será necessária. No AndroidManifest.xml:

<intent-filter>
  <action android:name="android.intent.action.VIEW"/>
  <category android:name="android.intent.category.DEFAULT"/>
  <category android:name="android.intent.category.BROWSABLE"/>
  <data android:host="CHANGE_THIS_DOMAIN.example.com" android:scheme="http"/>
  <data android:host="CHANGE_THIS_DOMAIN.example.com" android:scheme="https"/>
</intent-filter>

Também é possível especificar um caractere curinga para deixar o filtro de intent mais flexível. Exemplo:

<intent-filter>
  <action android:name="android.intent.action.VIEW"/>
  <category android:name="android.intent.category.DEFAULT"/>
  <category android:name="android.intent.category.BROWSABLE"/>
  <data android:host="*.example.com" android:scheme="http"/>
  <data android:host="*.example.com" android:scheme="https"/>
</intent-filter>

Quando os usuários tocam em uma notificação que contém um link para o esquema e o host especificados por você, seu aplicativo iniciará a atividade com esse filtro de intent para processar o link.

Próximas etapas

Quando o app cliente estiver configurado, estará tudo pronto para começar a enviar mensagens downstream e mensagens de tópico com o Firebase. Para saber mais, veja essa funcionalidade demonstrada no exemplo de início rápido, que você pode transferir por download, executar e avaliar.

Para adicionar outros comportamentos avançados ao seu app, consulte os guias para envio de mensagens de um servidor de app:

Saiba que você precisará de uma implementação de servidor para usar esses recursos.