Como lidar com a notificação quando o aplicativo em segundo plano no Firebase

429

Aqui está o meu manifesto

    <service android:name=".fcm.PshycoFirebaseMessagingServices">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <service android:name=".fcm.PshycoFirebaseInstanceIDService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>

Quando o aplicativo está em segundo plano e a notificação chega, a notificação padrão chega e não executa o meu código de onMessageReceived.

Aqui está o meu onMessageReceivedcódigo. Isso chama se meu aplicativo estiver sendo executado em primeiro plano, não quando o aplicativo estiver em segundo plano. Como executar esse código quando o aplicativo também está em segundo plano?

// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // If the application is in the foreground handle both data and notification messages here.
    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
    data = remoteMessage.getData();
    String title = remoteMessage.getNotification().getTitle();
    String message = remoteMessage.getNotification().getBody();
    String imageUrl = (String) data.get("image");
    String action = (String) data.get("action");
    Log.i(TAG, "onMessageReceived: title : "+title);
    Log.i(TAG, "onMessageReceived: message : "+message);
    Log.i(TAG, "onMessageReceived: imageUrl : "+imageUrl);
    Log.i(TAG, "onMessageReceived: action : "+action);

    if (imageUrl == null) {
        sendNotification(title,message,action);
    } else {
        new BigPictureNotification(this,title,message,imageUrl,action);
    }
}
// [END receive_message]
Parth Patel
fonte
1
Está escrito no exemplo de substituição de onMessageReceived () , diz a segunda linha de comentário Not getting messages here? See why this may be: goo.gl/39bRNJ . A solução, como as respostas abaixo, pode ser encontrada na documentação em Mensagens com cargas de notificação e de dados
fllo
Em poucas palavras, para ativar o aplicativo morto, você sempre deve enviar uma notificação com o objeto de dados para chamar o manipulador de classe do serviço de notificação FirebaseMessagingService.onMessageReceived () em seu aplicativo. Tente também enviá-lo não do console do Firebase, mas publicá-lo de outro lugar (por exemplo, serviço de postagem de testes on-line).
Zon
1
esta solução funcionou para mim stackoverflow.com/a/44150822/6632278 espero que ajude. Boa sorte
Tony Barajas
o que ".fcm." PshycoFirebaseMessagingServices está no seu manifesto? Estou recebendo erro de classe não encontrado .. e não encontrei em lugar nenhum o que é essa primeira parte do parâmetro.
Éder Rocha Bezerra

Respostas:

661

1. Por que isso está acontecendo?

Existem dois tipos de mensagens no FCM (Firebase Cloud Messaging):

  1. Mensagens de exibição : essas mensagens acionam o onMessageReceived()retorno de chamada somente quando seu aplicativo está em primeiro plano
  2. Mensagens de dados : essas mensagens acionam o onMessageReceived()retorno de chamada mesmo que seu aplicativo esteja em primeiro plano / em segundo plano / eliminado

NOTA: A equipe do Firebase ainda não desenvolveu uma interface do usuário para enviar data-messagesaos seus dispositivos. Você deve usar seu servidor para enviar esse tipo!



2. como?

Para conseguir isso, você deve executar uma POSTsolicitação para o seguinte URL:

POST https://fcm.googleapis.com/fcm/send

Cabeçalhos

  • Chave: Content-Type , Valor: application/json
  • Chave: Authorization , Valor: key=<your-server-key>

Corpo usando tópicos

{
    "to": "/topics/my_topic",
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     }
}

Ou se você deseja enviá-lo para dispositivos específicos

{
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     },
    "registration_ids": ["{device-token}","{device2-token}","{device3-token}"]
}


NOTA: Certifique-se de não adicionar a chave JSON. notification
NOTA: Para obter a chave do servidor, você pode encontrá-la no console do firebase:Your project -> settings -> Project settings -> Cloud messaging -> Server Key

3. Como lidar com a mensagem de notificação por push?

É assim que você lida com a mensagem recebida:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();
     String myCustomKey = data.get("my_custom_key");

     // Manage data
}
Antonio
fonte
4
Você pode enviar "dados" e chaves "Notificação" na mesma notificação seguindo estes passos stackoverflow.com/a/42279260/2734021 :)
Daniel S.
15
Firebase team have not developed a UI to send data-messages to your devices, yet.Isso mudou no ano passado?
Hankrecords
2
@ Antonio No oreo, quando o aplicativo é morto, o onMessageReceived não está sendo chamado. eu só tenho carga útil apenas com dados. você tem alguma atualização?
Samir Mangroliya
63
Quando o aplicativo está em segundo plano onMessageReceived, não é chamado e é um problema sério no FCM !!! Atualize também sua resposta.
Muhammad Babar 04/04
2
Bem, para mim, parece que isso acontece em certos dispositivos Android. Passou horas pensando que era um problema real, mas acabou sendo nada. Portanto, meu conselho é testá-lo em diferentes dispositivos. Eu até testei em uma VM e recebi a notificação mesmo quando o aplicativo foi morto. Só estou dizendo isso para economizar o tempo de alguém.
Tarek-Dev
158

Para fazer com que a biblioteca do firebase chame seu onMessageReceived () nos seguintes casos

  1. App em primeiro plano
  2. App em segundo plano
  3. O aplicativo foi morto

você não deve colocar a chave JSON 'notificação' em sua solicitação à API do firebase, mas usar 'dados', veja abaixo.

A mensagem a seguir não chamará seu onMessageReceived () quando seu aplicativo estiver em segundo plano ou morto, e você não poderá personalizar sua notificação.

{
   "to": "/topics/journal",
   "notification": {
   "title" : "title",
   "text": "data!",
   "icon": "ic_notification"
    }
}

mas, em vez disso, usar isso funcionará

{
  "to": "/topics/dev_journal",
   "data": {
       "text":"text",
       "title":"",
       "line1":"Journal",
       "line2":"刊物"
   }
} 

Basicamente, a mensagem é enviada no argumento RemoteMessage, juntamente com o seu objeto de dados como Map, e você pode gerenciar a notificação no onMessageReceived como no snippet aqui

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();

     //you can get your text message here.
     String text= data.get("text");


     NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
        // optional, this is to make beautiful icon
             .setLargeIcon(BitmapFactory.decodeResource(
                                    getResources(), R.mipmap.ic_launcher))  
        .setSmallIcon(smallIcon)  //mandatory
      .......
    /*You can read more on notification here:
    https://developer.android.com/training/notify-user/build-notification.html
    https://www.youtube.com/watch?v=-iog_fmm6mE
    */
}
Teerakiat Chitawattanarat
fonte
1
É possível conseguir isso no console do Firebase?
koder
@koder, infelizmente o console do Firebase não suporta isso, você precisa usar a ferramenta para enviar uma solicitação de mensagem de postagem para o firebase, como curl ou postman (plugin do chrome), api de mensagens do firebase, consulte o documento aqui - firebase.google.com/docs / cloud-messaging / http-server-ref
Última atualização
1
era isso que eu procurava há mais de um dia ... Muito obrigado, funcionou perfeitamente. e seria melhor se você explicasse como os pares de valores-chave nos dados podem ser tratados em onMessageReceived () para iniciar uma atividade com esses valores.
Boopathi T
25
Seu método funciona bem quando o aplicativo está em segundo plano, no entanto, quando o aplicativo é
encerrado
8
O mesmo problema de Sanzhar. Se o aplicativo for encerrado, não recebo nenhuma mensagem.
Giacomo M
104

Sinto que todas as respostas estão incompletas, mas todas têm algo que você precisa para processar uma notificação com dados quando o aplicativo está em segundo plano.

Siga estas etapas e você poderá processar suas notificações quando o aplicativo estiver em segundo plano.

1. Adicione um filtro de intenção como este:

<activity android:name=".MainActivity">
      <intent-filter>
           <action android:name=".MainActivity" />
           <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
</activity>

para uma atividade que você deseja processar os dados da notificação.

  1. Envie notificações com o próximo formato:

    { 
     "notification" : {
            "click_action" : ".MainActivity", 
            "body" : "new Symulti update !", 
            "title" : "new Symulti update !", 
            "icon" : "ic_notif_symulti" }, 
     "data": { ... },
     "to" : "c9Vaa3ReGdk:APA91bH-AuXgg3lDN2WMcBrNhJZoFtYF9" }

A chave aqui é adicionar

"click_action" : ".MainActivity"

onde .MainActivity é a atividade com o filtro de intenção que você adicionou na etapa 1.

  1. Obtenha informações de "dados" da notificação no onCreate de ".MainActivity":

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //get notification data info
        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
           //bundle must contain all info sent in "data" field of the notification
        }
    }

E isso deve ser tudo o que você precisa fazer. Espero que isso ajude alguém :)

Daniel S.
fonte
5
Essa deve ser a resposta correta. Nenhum dos documentos diz nada sobre exigir uma ação de clique E um filtro de intenção para que a notificação apareça na bandeja. Ambos são necessários.
Airowe
@airowe eles não são necessários para a notificação de aparecer
AlwaysConfused
Tenho blocos de dados e de notificação, mas não consigo receber dados em atividade?
Ashwani
3
Só não entendo como essa não é a resposta aceita. Sem a ação do clique, simplesmente não funcionará. Salvou meu dia
Arun Shankar
4
Obrigado pelo seu apoio @ArunShankar. A resposta aceita foi respondida 7 meses antes da minha e é uma boa resposta. Não consigo entender por que ninguém fala sobre click_action e é por isso que adicionei minha resposta. Estou muito feliz que ele está sendo muito útil para muita gente e é isso que importa no final do dia :)
Daniel S.
42

De acordo com a documentação do firebase em enviar a jusante usando o firebase , há 2 tipos de carga útil:

  1. dados

    Este parâmetro especifica os pares de valores-chave personalizados da carga útil da mensagem. O aplicativo cliente é responsável pelo processamento de mensagens de dados. As mensagens de dados possuem apenas pares de valores-chave personalizados.

  2. notificação

    Este parâmetro especifica os pares de valores-chave predefinidos e visíveis ao usuário da carga útil da notificação. O FCM exibe automaticamente a mensagem para dispositivos do usuário final em nome do aplicativo cliente. As mensagens de notificação têm um conjunto predefinido de chaves visíveis pelo usuário.

Quando você está em primeiro plano, pode obter os dados no FCM usando onMessageReceived () , pode obter os dados da carga útil dos dados .

data = remoteMessage.getData();
String customData = (String) data.get("customData");

Quando você está em segundo plano, o FCM mostra a notificação na bandeja do sistema com base nas informações da carga útil da notificação . O título, a mensagem e o ícone usados ​​para a notificação na bandeja do sistema são obtidos da carga útil da notificação .

{
  "notification": {
        "title" : "title",
        "body"  : "body text",
        "icon"  : "ic_notification",
        "click_action" : "OPEN_ACTIVITY_1"
       }
}

Essa carga útil da notificação é usada quando você deseja mostrar automaticamente a notificação na bandeja do sistema quando o aplicativo está em segundo plano. Para obter dados de notificação quando seu aplicativo estiver em segundo plano, adicione click_action na carga útil da notificação .

Se você deseja abrir o aplicativo e executar uma ação específica [em segundo plano], defina click_action na carga útil da notificação e mapeie-o para um filtro de intenção na Atividade que você deseja iniciar. Por exemplo, defina click_action como OPEN_ACTIVITY_1 para acionar um filtro de intenção como o seguinte:

<intent-filter>
  <action android:name="OPEN_ACTIVITY_1" />
  <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

Coloque esse filtro de intenção em seu manifesto, dentro de uma das tags de atividade. Quando você clica na notificação, ele abre o aplicativo e vai diretamente para a atividade definida em click_action, neste caso "OPEN_ACTIVTY_1". E nessa atividade, você pode obter os dados:

Bundle b = getIntent().getExtras();
String someData = b.getString("someData");

Estou usando o FCM para meu aplicativo para Android e uso a carga útil. Aqui está o exemplo de JSON que estou usando:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification",
    "click_action" : "OPEN_ACTIVITY_1"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}
Hendy Evan
fonte
"Coloque esse filtro de intenção no manifesto, dentro da tag do aplicativo". você não pode colocar o filtro de intenção na tag do aplicativo.
Kyrylo Zapylaiev
suas linhas JSON não mostram para onde a chave click_action vai.
Josh
Esta não é a resposta certa? o que é ação de clique n para onde ela vai? alguém deve votar ou limpar este
rana
1
@KyryloZapylaiev Acabei de corrigir e atualizar a resposta: "Coloque esse filtro de intenção no manifesto, dentro de uma das tags de atividade".
Dika
1
@ Jos atualizado e formatado. você pode conferir novamente
Dika
32

De acordo com documentos

Manipular mensagens em um aplicativo em segundo plano

Quando o aplicativo está em segundo plano, o Android direciona as mensagens de notificação para a bandeja do sistema. Um toque do usuário na notificação abre o iniciador de aplicativos por padrão.

Isso inclui mensagens que contêm notificação e carga útil de dados. Nesses casos, a notificação é entregue na bandeja do sistema do dispositivo e a carga útil dos dados é entregue nos extras da intenção da sua atividade do iniciador.

Se você deseja abrir seu aplicativo e executar uma ação específica, defina click_action na carga útil da notificação e mapeie-o para um filtro de intenção na Atividade que deseja iniciar. Por exemplo, defina click_action como OPEN_ACTIVITY_1 para acionar um filtro de intenção como o seguinte:

 <intent-filter>   <action android:name="OPEN_ACTIVITY_1" />  
 <category android:name="android.intent.category.DEFAULT" />
 </intent-filter>

Editar:

Com base neste tópico :

Você não pode definir a carga útil do click_action usando o Firebase Console. Você pode tentar testar com um comando curl ou um servidor http personalizado

curl --header "Authorization: key=<YOUR_KEY_GOES_HERE>" 
     --header Content-Type:"application/json" https://fcm.googleapis.com/fcm/send  
     -d "{\"to\":\"/topics/news\",\"notification\": 
         {\"title\": \"Click Action Message\",\"text\": \"Sample message\",
            \"click_action\":\"OPEN_ACTIVITY_1\"}}"
Shubhank
fonte
1
você está certo. Eu li os documentos. mas estou confuso onde colocar isso no meu manifesto? Eu tenho que executar o código no onMessageReceived nesse arquivo java, para que o que devo fazer senhor?
Parth Patel
Você não pode fazer com que o aplicativo chame automaticamenteMessageReveiced quando estiver em segundo plano. Em vez disso, você precisa lidar com a intenção recebida e fazer com que o manipulador o chame. Ou provavelmente é melhor implementar uma classe / método separado chamado por onMessageReveiced e seu tratamento de intenção. Adicionei manipulador ao onNewIntent da atividade principal e ele funciona bem para mim.
Diidu
tarde demais para responder a perguntas @Parath Patel, mas talvez isso ajude alguém com os mesmos problemas, dar uma olhada para a minha resposta aqui stackoverflow.com/a/42279260/2734021
Daniel S.
onde teve que colocar essa ação? para minha atividade ou serviço de mensagem de Firebas?
Mahdi
** no redirecionamento de múltiplas notificações não está funcionando? por exemplo: se eu tiver três notificações do fcm em segundo plano usando a primeira notificação "click_action" redirecionada com sucesso e, em seguida, 2 notificações clique no redirecionamento de atividade não está funcionando
prasanthMurugan
24

Em julho de 2019

Android compileSdkVersion 28, buildToolsVersion 28.0.3 e firebase-messaging: 19.0.1

Depois de muitas horas pesquisando todas as outras perguntas e respostas do StackOverflow e tentando inúmeras soluções desatualizadas, essa solução conseguiu mostrar notificações nesses três cenários:

- O aplicativo está em primeiro plano:
a notificação é recebida pelo método onMessageReceived na minha classe MyFirebaseMessagingService

- O aplicativo foi eliminado (não está sendo executado em segundo plano): a notificação é enviada para a bandeja de notificação automaticamente pelo FCM. Quando o usuário toca na notificação, o aplicativo é iniciado chamando a atividade que possui android.intent.category.LAUNCHER no manifesto. Você pode obter a parte dos dados da notificação usando getIntent (). GetExtras () no método onCreate ().

- O aplicativo está em segundo plano: a notificação é enviada para a bandeja de notificação automaticamente pelo FCM. Quando o usuário toca na notificação, o aplicativo é trazido para o primeiro plano iniciando a atividade que possui android.intent.category.LAUNCHER no manifesto. Como meu aplicativo possui launchMode = "singleTop" nessa atividade, o método onCreate () não é chamado porque uma atividade da mesma classe já foi criada. Em vez disso, o método onNewIntent () dessa classe é chamado e você obtém a parte dos dados a notificação lá usando intent.getExtras ().

Etapas: 1- Se você definir a atividade principal do seu aplicativo, assim:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:screenOrientation="portrait"
    android:launchMode="singleTop">
    <intent-filter>
        <action android:name=".MainActivity" />
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

2- adicione essas linhas no método onCreate () da sua classe MainActivity.class

Intent i = getIntent();
Bundle extras = i.getExtras();
if (extras != null) {
    for (String key : extras.keySet()) {
        Object value = extras.get(key);
        Log.d(Application.APPTAG, "Extras received at onCreate:  Key: " + key + " Value: " + value);
    }
    String title = extras.getString("title");
    String message = extras.getString("body");
    if (message!=null && message.length()>0) {
        getIntent().removeExtra("body");
        showNotificationInADialog(title, message);
    }
}

e esses métodos para a mesma MainActivity.class:

@Override
public void onNewIntent(Intent intent){
    //called when a new intent for this class is created.
    // The main case is when the app was in background, a notification arrives to the tray, and the user touches the notification

    super.onNewIntent(intent);

    Log.d(Application.APPTAG, "onNewIntent - starting");
    Bundle extras = intent.getExtras();
    if (extras != null) {
        for (String key : extras.keySet()) {
            Object value = extras.get(key);
            Log.d(Application.APPTAG, "Extras received at onNewIntent:  Key: " + key + " Value: " + value);
        }
        String title = extras.getString("title");
        String message = extras.getString("body");
        if (message!=null && message.length()>0) {
            getIntent().removeExtra("body");
            showNotificationInADialog(title, message);
        }
    }
}


private void showNotificationInADialog(String title, String message) {

    // show a dialog with the provided title and message
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(title);
    builder.setMessage(message);
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();
}

3- crie a classe MyFirebase assim:

package com.yourcompany.app;

import android.content.Intent;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService {


    public MyFirebaseMessagingService() {
        super();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        Log.d(Application.APPTAG, "myFirebaseMessagingService - onMessageReceived - message: " + remoteMessage);

        Intent dialogIntent = new Intent(this, NotificationActivity.class);
        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        dialogIntent.putExtra("msg", remoteMessage);
        startActivity(dialogIntent);

    }

}

4- crie uma nova classe NotificationActivity.class assim:

package com.yourcompany.app;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ContextThemeWrapper;

import com.google.firebase.messaging.RemoteMessage;

public class NotificationActivity extends AppCompatActivity {

private Activity context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context = this;
    Bundle extras = getIntent().getExtras();

    Log.d(Application.APPTAG, "NotificationActivity - onCreate - extras: " + extras);

    if (extras == null) {
        context.finish();
        return;
    }

    RemoteMessage msg = (RemoteMessage) extras.get("msg");

    if (msg == null) {
        context.finish();
        return;
    }

    RemoteMessage.Notification notification = msg.getNotification();

    if (notification == null) {
        context.finish();
        return;
    }

    String dialogMessage;
    try {
        dialogMessage = notification.getBody();
    } catch (Exception e){
        context.finish();
        return;
    }
    String dialogTitle = notification.getTitle();
    if (dialogTitle == null || dialogTitle.length() == 0) {
        dialogTitle = "";
    }

    AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(context, R.style.myDialog));
    builder.setTitle(dialogTitle);
    builder.setMessage(dialogMessage);
    builder.setPositiveButton(getResources().getString(R.string.accept), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();

}

}

5- Adicione essas linhas ao manifesto do seu aplicativo, dentro das suas tags

    <service
        android:name=".MyFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/default_notification_channel_id"/>

    <activity android:name=".NotificationActivity"
        android:theme="@style/myDialog"> </activity>

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/notification_icon"/>

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/color_accent" />

6- adicione essas linhas no método Application.java onCreate () ou no método MainActivity.class onCreate ():

      // notifications channel creation
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      // Create channel to show notifications.
      String channelId = getResources().getString("default_channel_id");
      String channelName = getResources().getString("General announcements");
      NotificationManager notificationManager = getSystemService(NotificationManager.class);
      notificationManager.createNotificationChannel(new NotificationChannel(channelId,
              channelName, NotificationManager.IMPORTANCE_LOW));
  }

Feito.

Agora, para que isso funcione bem nos três cenários mencionados, você deve enviar a notificação do console da web do Firebase da seguinte maneira:

Na seção Notificação: Título da notificação = Título a ser exibido na caixa de diálogo de notificação (opcional) Texto da notificação = Mensagem para mostrar ao usuário (obrigatório) Na seção Destino: Aplicativo = seu aplicativo Android e na seção Opções Adicionais: Canal de Notificação Android = default_channel_id Chave de dados personalizados: valor do título: (o mesmo texto aqui que no campo Título da seção Notificação) chave: valor do corpo: (mesmo texto aqui que no campo Mensagem da seção Notificação) chave: valor da ação do clique: valor da ação do clique: .MainActivity Sound = Desativado
expira = 4 semanas

Você pode depurá-lo no emulador com API 28 no Google Play.

Feliz codificação!

alvaro
fonte
2
Obrigado por esta ótima resposta.
Alex Chengalan 10/10
@alvaro, Se eu quiser abrir Url quando eu receber uma notificação, Como eu posso lidar com isso
engmms
não está funcionando no telefone opp vivo quando o aplicativo é fechado ou morto
Android Developer
Eu não tentei em um telefone Vivo, mas atualmente está funcionando em muitos outros telefones Android. Leia devagar todas as etapas, verifique todos os detalhes e ative os pontos de interrupção de depuração na primeira linha de cada um dos métodos que mencionei aqui, conecte um telefone real ao computador de desenvolvimento com um cabo e depure o aplicativo enquanto envia uma mensagem do FCM. Verifique se você está enviando as mensagens do FCM com todos os parâmetros e o formato que eu mencionei. Boa sorte!
Alvaro #
2
Esta é a resposta mais atualizada, pois a documentação do Firebase agora diz: Quando o aplicativo está em segundo plano, o Android direciona as mensagens de notificação para a bandeja do sistema. Um toque do usuário na notificação abre o iniciador de aplicativos por padrão. Isso inclui mensagens que contêm notificação e carga útil de dados. Nesses casos, a notificação é entregue na bandeja do sistema do dispositivo e a carga útil dos dados é entregue nos extras da intenção da sua atividade do iniciador. ( firebase.google.com/docs/cloud-messaging/android/… ) Muitas respostas antigas estão desatualizadas
Riot Goes Woof
20

Uma vez display-messagesque os que são enviados pela interface do usuário do Firebase Notification só funcionam se o aplicativo estiver em primeiro plano. Para data-messages, é necessário fazer uma chamada POST para o FCM

Passos

  1. Instale a Extensão do Google Chrome do Advanced Rest Client insira a descrição da imagem aqui

  2. Adicione os seguintes cabeçalhos

    Chave : Tipo de Conteúdo, Valor : application / json

    Chave : Autorização, Valor : key = "sua chave do servidor" insira a descrição da imagem aqui

  3. Adicione o corpo

    • Se estiver usando tópicos:

      {
          "to" : "/topics/topic_name",
          "data": {
          "key1" : "value1",
          "key2" : "value2",
          }
      }
    • Se estiver usando o ID de registro:

      {
          "registration_ids" : "[{"id"},{id1}]",
          "data": {
          "key1" : "value1",
          "key2" : "value2",
           }
      }

É isso aí!. Agora ouça o onMessageReceivedretorno de chamada, como de costume.

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();
     String value1 = data.get("key1");
     String value2 = data.get("key2");
}
skynet
fonte
20

Para capturar a mensagem em segundo plano, você precisa usar um BroadcastReceiver

import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.legacy.content.WakefulBroadcastReceiver
import com.google.firebase.messaging.RemoteMessage

class FirebaseBroadcastReceiver : WakefulBroadcastReceiver() {

    val TAG: String = FirebaseBroadcastReceiver::class.java.simpleName

    override fun onReceive(context: Context, intent: Intent) {

        val dataBundle = intent.extras
        if (dataBundle != null)
            for (key in dataBundle.keySet()) {
                Log.d(TAG, "dataBundle: " + key + " : " + dataBundle.get(key))
            }
        val remoteMessage = RemoteMessage(dataBundle)
        }
    }

e adicione isso ao seu manifesto:

<receiver
      android:name="MY_PACKAGE_NAME.FirebaseBroadcastReceiver"
      android:exported="true"
      android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
</receiver>
Romulano
fonte
7
Isso realmente recebe a mensagem de notificação quando o aplicativo está em segundo plano. Mas isso não impede que o receptor Firebase padrão o processe, portanto a mensagem ainda é exibida como um alerta de notificação.
Galya
No momento não funciona, é por isso que estou propondo esta solução. Há um bug arquivado na base de erros do google. Você pode verificar isso.
Romulano 20/10
Você poderia, por favor, postar um link para o bug aqui?
Galya
como obter dados da notificação?
Ravi Vaghela
Claramente, isso não está funcionando quando o aplicativo é encerrado. Eu tentei esta solução por horas. por alguma razão o receptor está a trabalhar enquanto o aplicativo está em segundo plano e não funciona quando o aplicativo é morto
XcodeNOOB
16
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

}

não é chamado toda vez que é chamado somente quando o aplicativo está em forground

existe um método de substituição que esse método é chamado sempre, não importa qual aplicativo esteja em primeiro plano ou em segundo plano ou seja morto, mas esse método esteja disponível nesta versão da API do firebase

esta é a versão que você precisa importar do gradle

compile 'com.google.firebase:firebase-messaging:10.2.1'

este é o método

@Override
public void handleIntent(Intent intent) {
    super.handleIntent(intent);

    // you can get ur data here 
    //intent.getExtras().get("your_data_key") 


}

com a API anterior do firebase, esse método não estava lá; nesse caso, a base de incêndio se autodefine quando o aplicativo está em segundo plano ... agora você tem esse método, o que quer que você queira fazer ... você pode fazê-lo aqui neste método .. ...

se você estiver usando a versão anterior, a atividade padrão iniciará nesse caso, você poderá obter os dados da mesma maneira

if(getIntent().getExtras() != null && getIntent().getExtras().get("your_data_key") != null) {
String strNotificaiton = getIntent().getExtras().get("your_data_key").toString();

// faça o que você quiser ....}

geralmente esta é a estrutura do servidor que recebemos na notificação

{
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon",
        "click_action": "activity name" //optional if required.....
    },
    "data": {
        "product_id": 11,
        "product_details": "details.....",
        "other_info": "......."
    }
}

cabe a você como você deseja fornecer essa chave de dados ou deseja notificar qualquer coisa que você possa fornecer ....... o que você fornecer aqui com a mesma chave, você obterá esses dados ........ .

existem poucos casos se você não enviar ação de clique, nesse caso, quando você clicará na notificação, a atividade padrão será aberta, mas se você desejar abrir sua atividade específica quando o aplicativo estiver em segundo plano, poderá chamar sua atividade a partir desse método on handleIntent, porque isso é chamado toda vez

Avinash Jadaun
fonte
Atualizei o sistema de mensagens da base de firmas para 10.2.1, Dados adicionados à mensagem de notificação e funcionou. Primeiro plano, plano de fundo e morto. Obrigado
Firas Shrourou
em Kotlin, eu recebo este erro: (44, 5) 'handleIntent' em 'FirebaseMessagingService' é final e não pode ser substituído
ugali macia
Ele não está a funcionar acima das versões de firebase 11
venu46
14

De acordo com os documentos: 17 de maio de 2017

Quando o aplicativo está em segundo plano , o Android direciona as mensagens de notificação para a bandeja do sistema. Um toque do usuário na notificação abre o iniciador de aplicativos por padrão .

Isso inclui mensagens que contêm notificação e dados carga útil de (e todas as mensagens enviadas do console de Notificações). Nesses casos, a notificação é entregue na bandeja do sistema do dispositivo e a carga útil dos dados é entregue nos extras da intenção da sua atividade do iniciador.

Portanto, você deve usar a notificação de carga útil + os dados:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}

Não é necessário usar a ação click_action. Você deve obter exras da intenção na atividade LAUNCHER

<activity android:name=".MainActivity">
        <intent-filter>
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>

O código Java deve estar no método onCreate em MainActivity:

Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
    Bundle extras = intent.getExtras();
    String someData= extras.getString("someData");
    String someData2 = extras.getString("someData2");
}

Você pode testar a notificação de carga útil + os dados do Firebase Notifications Console . Não se esqueça de preencher campos de dados personalizados na seção Opções avançadas

Mihuilk
fonte
13

Aqui estão conceitos mais claros sobre a mensagem do firebase. Encontrei na equipe de suporte.

O Firebase possui três tipos de mensagens :

Mensagens de notificação : a mensagem de notificação funciona em segundo plano ou em primeiro plano. Quando o aplicativo está em segundo plano, as mensagens de notificação são entregues na bandeja do sistema. Se o aplicativo estiver em primeiro plano, as mensagens serão tratadas onMessageReceived()ou didReceiveRemoteNotificationretornadas. Essas são essencialmente as chamadas mensagens de exibição.

Mensagens de dados : na plataforma Android, as mensagens de dados podem funcionar em segundo plano e em primeiro plano. A mensagem de dados será tratada por onMessageReceived (). Uma observação específica da plataforma aqui seria: No Android, a carga útil dos dados pode ser recuperada no Intent usado para iniciar sua atividade. Para elaborar, se você tiver "click_action":"launch_Activity_1", você pode recuperar essa intenção getIntent()somente de Activity_1.

Mensagens com carga útil de notificação e de dados : quando em segundo plano, os aplicativos recebem a carga útil de notificação na bandeja de notificação e só lidam com a carga útil de dados quando o usuário toca na notificação. Quando em primeiro plano, seu aplicativo recebe um objeto de mensagem com as duas cargas úteis disponíveis. Em segundo lugar, o click_actionparâmetro é frequentemente usado na carga útil da notificação e não na carga útil dos dados. Se usado dentro da carga útil dos dados, esse parâmetro seria tratado como um par de valor-chave personalizado e, portanto, seria necessário implementar uma lógica personalizada para que funcionasse conforme o planejado.

Além disso, recomendo que você use o onMessageReceivedmétodo (consulte Mensagem de dados) para extrair o pacote de dados. Pela sua lógica, verifiquei o objeto do pacote e não encontrei o conteúdo de dados esperado. Aqui está uma referência a um caso semelhante que pode fornecer mais clareza.

Para mais informações visite o meu tópico

Md. Sajedul Karim
fonte
8

Resumo simples como este

  • se seu aplicativo estiver sendo executado;

    onMessageReceived()

é gatilhos.

  • se o seu aplicativo não estiver em execução (eliminado ao passar o dedo);

    onMessageReceived()

não é acionado e entregue por direclty. Se você tiver algum par de valor-chave específico. Eles não funcionam porque onMessageReceived () não está funcionando.

Eu encontrei este caminho;

Na sua atividade do iniciador, coloque essa lógica,

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState, R.layout.activity_splash);

    if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("PACKAGE_NAME")) {

        // do what you want

        // and this for killing app if we dont want to start
        android.os.Process.killProcess(android.os.Process.myPid());

    } else {

        //continue to app
    }
}

nesse bloco if, procure suas chaves de acordo com a interface do usuário do firebase.

Neste exemplo, minha chave e valor como acima; (desculpe pelo idioma =)) insira a descrição da imagem aqui

Quando meu código funciona, eu recebo "com.rda.note".

android.os.Process.killProcess(android.os.Process.myPid());

com essa linha de código, fechei meu aplicativo e abro o Google Play Market

codificação feliz =)

Arda
fonte
6

Eu descobri os cenários,

Quando o aplicativo está em primeiro plano , o método onMessageReceived () é chamado do FirebaseService . Portanto, o pendingIntent definido na classe de serviço será chamado.

E quando o aplicativo está em segundo plano , a primeira atividade é chamada.

Agora, se você usar uma atividade inicial , em seguida, deve ter em mente o splashactivity será chamado, outra coisa se não houver splashActivity, então qualquer que seja a primeira atividade é, será chamado.

Em seguida, é necessário verificar getIntent () da firstActivity para ver se há algum pacote. Se estiver tudo bem, você verá que o pacote está com os valores preenchidos. Se o valor na tag de dados enviada pelo servidor se parecer com isso,

"data": {
    "user_name": "arefin sajib",
    "value": "user name notification"
  }

Então, na primeira atividade, você verá, há uma intenção válida ( getIntent () não é nula ), pacote válido e pacote interno, haverá todo o JSON mencionado acima com dados como chave .

Nesse cenário, o código para extração de valor terá a seguinte aparência:

    if(getIntent()!=null){
            Bundle bundle = getIntent().getExtras();
            if (bundle != null) {
                try {
                   JSONObject object = new JSONObject(bundle.getStringExtra("data"));
String user_name = object.optString("user_name");

                } catch (JSONException e) {
                    e.printStackTrace();
                }


            }
        }
Shamsul Arefin Sajib
fonte
3

Obrigado a todos por suas respostas. Mas eu resolvi isso enviando uma mensagem de dados em vez de enviar uma notificação . Código do servidor

<?php
$url = "https://fcm.googleapis.com/fcm/send";
$token = "C-l6T_a7HouUK****";
$serverKey = "AAAAaOcKS00:********";
define( 'API_ACCESS_KEY', $serverKey );
$registrationIds = array($token);
// prep the bundle

$msg = array

(
 'message'  => 'here is a message. message',
 'title'        => 'This is a title. title',
 'subtitle' => 'This is a subtitle. subtitle',
 'tickerText'   => 'Ticker text here...Ticker text here...Ticker text 
 here',
 'vibrate'  => 1,
 'sound'        => 1,
 'largeIcon'    => 'large_icon',
 'smallIcon'    => 'small_icon'

);

$fields = array

(
  'registration_ids'    => $registrationIds,
  'data'            => $msg

);
$headers = array

(
  'Authorization: key=' . API_ACCESS_KEY,
 'Content-Type: application/json'

);


$ch = curl_init();

curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' 
);

curl_setopt( $ch,CURLOPT_POST, true );

curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );

curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );

curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );

curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );

$result = curl_exec($ch );

curl_close( $ch );

echo $result;

?>

E capturou os dados no onMessageReceived

public class MyFirebaseMessagingService extends FirebaseMessagingService     {

  private static final String TAG = "MyFirebaseMsgService";

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());

      sendNotification(remoteMessage.getData().get("message"));
     }
   // Check if message contains a notification payload.
    else if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    sendNotification(remoteMessage.getNotification().getBody());
    }


}
   private void sendNotification(String messageBody) {
    Intent intent = new Intent(this, Notify.class).putExtra("msg",messageBody);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);

    String channelId = "idddd";
    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder =
            new NotificationCompat.Builder(MyFirebaseMessagingService.this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle("FCM Message")
                    .setContentText(messageBody)
                    .setAutoCancel(true)
                    .setSound(defaultSoundUri)
                    .setContentIntent(pendingIntent);

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
Android Sanaullah
fonte
1
também está trabalhando com um background?
Tabish Khan
@Tabishkhan Sim irmão que está trabalhando, se você tem qualquer problema de se sentir livre para me perguntar .. obrigado
Sanaullah Android
1
oi @AndroidSanaullah, você pode explicar a primeira parte do código do servidor? Onde você o coloca? Estou enfrentando o mesmo problema, mas não entendo bem a parte do servidor, você está usando carteiro?
Abriu 30/04
onda é utilizado para o pedido e todos os parâmetros são passados para ele @ Shid.
Sanaullah Android
2

Remova completamente a carga útil da notificação da sua solicitação do servidor. Envie apenas dados e trate-os onMessageReceived(), caso contrário, você onMessageReceivednão será acionado quando o aplicativo estiver em segundo plano ou morto.

Aqui está o que estou enviando do servidor:

{
  "data":{
    "id": 1,
    "missedRequests": 5
    "addAnyDataHere": 123
  },
  "to": "fhiT7evmZk8:APA91bFJq7Tkly4BtLRXdYvqHno2vHCRkzpJT8QZy0TlIGs......"
}

Para que você possa receber seus dados onMessageReceived(RemoteMessage message)assim: (digamos que eu precise obter o ID)

Object obj = message.getData().get("id");
        if (obj != null) {
            int id = Integer.valueOf(obj.toString());
        }

Da mesma forma, você pode obter todos os dados que você enviou do servidor onMessageReceived().

Zohab Ali
fonte
2

A maneira mais fácil de enviar mensagens, mesmo que o aplicativo esteja em segundo plano e em primeiro plano, como segue: - Para enviar uma mensagem usando a API, você pode usar uma ferramenta chamada AdvancedREST Client, uma extensão do chrome, e enviar uma mensagem com os seguintes parâmetros.

Link para ferramenta de descanso do cliente: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

use este URL: - https://fcm.googleapis.com/fcm/send Tipo de conteúdo: application / json Autorização: key = Chave do servidor ou chave de Authoization (veja abaixo ref)

{ "data": {
    "image": "https://static.pexels.com/photos/4825/red-love-romantic-flowers.jpg",
    "message": "Firebase Push Message Using API"
    "AnotherActivity": "True"
     },
  "to" : "device id Or Device token"
}

A chave de autorização pode ser obtida visitando o console do desenvolvedor do Google e clique no botão Credenciais no menu à esquerda do seu projeto. Entre as chaves de API listadas, a chave do servidor será sua chave de autorização.

E você precisa colocar o tokenID do receptor na seção "para" da sua solicitação POST enviada usando a API.

Syed Danish Haider
fonte
2

você deseja trabalhar em MessageReceived (RemoteMessage remoteMessage) em segundo plano, envie apenas uma parte da notificação de parte dos dados:

"data":    "image": "",    "message": "Firebase Push Message Using API", 

"AnotherActivity": "True", "to": "ID do dispositivo ou token do dispositivo"

Por isso, onMessageRecivied é o plano de fundo e o primeiro plano da chamada, não é necessário manipular a notificação usando a bandeja de notificação na atividade do iniciador. Manipule a carga útil dos dados usando isso:

  public void onMessageReceived(RemoteMessage remoteMessage)
    if (remoteMessage.getData().size() > 0) 
    Log.d(TAG, "Message data payload: " + remoteMessage.getData());      
user3385125
fonte
1

Junho 2018 Resposta -

Você deve garantir que não haja uma palavra-chave de "notificação" em nenhum lugar da mensagem. Inclua apenas "dados" e o aplicativo poderá manipular a mensagem em onMessageReceived, mesmo se estiver em segundo plano ou morto.

Usando funções da nuvem:

const message = {
    token: token_id,   // obtain device token id by querying data in firebase
    data: {
       title: "my_custom_title",
       body:  "my_custom_body_message"
       }
    }


return admin.messaging().send(message).then(response => {
    // handle response
});

Em seguida, em seu onMessageReceived (), em sua classe, estendendo com.google.firebase.messaging.FirebaseMessagingService:

if (data != null) {
  Log.d(TAG, "data title is: " + data.get("title");
  Log.d(TAG, "data body is: " + data.get("body");
}

// build notification using the body, title, and whatever else you want.
Jeff Padgett
fonte
você tem alguma fonte, é seguro?
Yogesh Rathi
É seguro, eu uso nos meus aplicativos. No entanto, seis meses após a publicação, não me lembro da fonte - imagino que seja a documentação do firebase.
Jeff Padgett
1

De acordo com o OAUTH 2.0:

Haverá um problema de autenticação para este caso, porque o FCM agora está usando OAUTH 2

Então, eu li a documentação do firebase e, de acordo com a documentação, é uma nova maneira de postar uma mensagem de dados;

POST: https://fcm.googleapis.com/v1/projects/YOUR_FIREBASEDB_ID/messages:send

Cabeçalhos

Key: Content-Type, Value: application/json

Auth

Bearer YOUR_TOKEN 

Corpo de exemplo

{
   "message":{
    "topic" : "xxx",
    "data" : {
         "body" : "This is a Firebase Cloud Messaging Topic Message!",
         "title" : "FCM Message"
          }
      }
 }

No URL, há o ID do banco de dados, que você pode encontrar no console do firebase. (Ir configurações do projeto)

E agora vamos pegar nosso token (ele será válido apenas 1 hora):

Primeiro no console do Firebase, abra Configurações> Contas de serviço . Clique em Gerar nova chave privada , armazene com segurança o arquivo JSON que contém a chave. Eu precisava desse arquivo JSON para autorizar solicitações do servidor manualmente. Eu baixei.

Em seguida, crio um projeto node.js e usei essa função para obter meu token;

var PROJECT_ID = 'YOUR_PROJECT_ID';
var HOST = 'fcm.googleapis.com';
var PATH = '/v1/projects/' + PROJECT_ID + '/messages:send';
var MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging';
var SCOPES = [MESSAGING_SCOPE];

  router.get('/', function(req, res, next) {
      res.render('index', { title: 'Express' });
      getAccessToken().then(function(accessToken) {
        console.log("TOKEN: "+accessToken)
      })

    });

function getAccessToken() {
return new Promise(function(resolve, reject) {
    var key = require('./YOUR_DOWNLOADED_JSON_FILE.json');
    var jwtClient = new google.auth.JWT(
        key.client_email,
        null,
        key.private_key,
        SCOPES,
        null
    );
    jwtClient.authorize(function(err, tokens) {
        if (err) {
            reject(err);
            return;
        }
        resolve(tokens.access_token);
    });
});
}

Agora eu posso usar esse token na minha solicitação de postagem. Em seguida, publico minha mensagem de dados e agora ela é tratada pelos meus aplicativos na função Message Message.

Ozan
fonte
Resposta aceitado está funcionando, barer auth token não é o caminho, você precisa ler este para experimentá-lo com Postman: stackoverflow.com/questions/45309674/...
Carlos Jesus Arancibia Taborga
1

Desde 2019, o Google Firebase tem uma grande mudança em suas APIs, quero dizer: 'com.google.firebase:firebase-messaging:18.0.0'

na versão 18.0.0, eles foram removidos MyFirebaseInstanceIDServicee você precisa obter o token, MyFirebaseMessagingServicepara escrever:

@Override
public void onNewToken(String token) {
    Log.d(TAG, "Refreshed token: " + token);

}

e também no seu AndroidManifest.xml, você deve remover:

<service android:name=".service.MyFirebaseInstanceIDService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>

Além disso, é recomendável definir valores padrão para personalizar a aparência das notificações. Você pode especificar um ícone padrão personalizado e uma cor padrão personalizada que serão aplicadas sempre que valores equivalentes não forem definidos na carga útil da notificação.

Adicione estas linhas dentro da tag do aplicativo para definir o ícone padrão personalizado e a cor personalizada:

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_notification" />

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorAccent" />

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/push_channel" />

agora, para lidar com mensagens de notificação em um aplicativo em segundo plano, você deve definir uma Intenção na sua primeira Atividade, mesmo que seja SplashScreen. Quando o aplicativo está em segundo plano, o Android direciona as mensagens de notificação para a bandeja do sistema. Um toque do usuário na notificação abre o iniciador de aplicativos por padrão.

por exemplo, se seu Json é assim:

 "data": {
"message": "2",
"title": "1",
"pushType" : "banner",
"bannerLink": "http://www.google.com",
"image" : "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"}

você só precisa escrever uma intenção simples de obter esses valores:

        Bundle extras = intent.getExtras();
        String bannerLink = extras.getString("bannerLink");
        ...
        String channelId = extras.getString("channelId");
Mohammad Mirzakhani
fonte
0

Além de respostas acima, Se você estiver testando notificações push usando consola FCM , chave e objeto 'dados' é não adicionado ao pacote Push Notification. Portanto, você não receberá uma notificação push detalhada quando o aplicativo estiver em segundo plano ou for morto.

Nesse caso, você deve optar pelo console administrativo de back-end para testar o cenário de segundo plano do aplicativo.

Aqui, você adicionou a chave 'data' ao seu pacote de envio. portanto, o envio detalhado será mostrado conforme o esperado. Espero que isso ajude poucos.

Max Droid
fonte
0

Usando esse código, você pode obter a notificação em segundo plano / primeiro plano e também executar uma ação:

//Data should come in this format from the notification
{
  "to": "/xyz/Notifications",
  "data": {
      "key1": "title notification",
      "key2": "description notification"
  }
}

No aplicativo, use este código:

  @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
      String key1Data = remoteMessage.getData().get("key1");
      // use key1Data to according to your need
    }
Ashish Kumar
fonte
// Os dados devem vir neste formato da notificação {"para": "/ xyz / Notifications", "data": {"key1": "title notification", "key2": "description notification"}} Como escrever esse código no serviço php?
Tabish Khan
-3

Haverá dois tipos de notificações

  1. Exibir notificação - Somente as notificações de exibição serão mostradas, apenas o aplicativo não está aberto e está na pilha de aplicativos.
  2. Notificação de dados - o retorno de chamada entrará no método onMessageReceived de firebasemessagingservice e funcionará quando o aplicativo estiver em segundo plano, em primeiro plano ou em estado morto.

Você deve usar as Notificações de dados para lidar com a notificação quando o aplicativo estiver em segundo plano.

abhi.nalavade
fonte
-5

Eu experimentei o mesmo problema, recompilei a biblioteca do firebase e impedi-a de enviar notificações quando o aplicativo está em segundo plano

* biblioteca https://github.com/erdalceylan/com-google-firebase-messaging

 dependencies {
        compile 'com.google.firebase:firebase-core:11.2.0'
        compile 'com.github.erdalceylan:com-google-firebase-messaging:v1-11.2.0'
    }

*

@WorkerThread
public void onMessageReceived(RemoteMessage var1) {
  //your app is in background or foreground all time calling
}

a esperança ajuda. Boa sorte

Erdal CEYLAN
fonte
2
Resposta não útil
Ankit Patidar
2
Esta é uma sugestão horrível.
vsecades 13/05/19