Firebase onMessageReceived não chamado quando o aplicativo em segundo plano


233

Estou trabalhando com o Firebase e testando o envio de notificações para meu aplicativo do meu servidor enquanto o aplicativo está em segundo plano. A notificação é enviada com êxito, até aparece no centro de notificações do dispositivo, mas quando a notificação aparece ou mesmo se eu clicar nela, o método onMessageReceived dentro de meu FCMessagingService nunca é chamado.

Quando testei isso enquanto meu aplicativo estava em primeiro plano, o método onMessageReceived foi chamado e tudo funcionou bem. O problema ocorre quando o aplicativo está sendo executado em segundo plano.

Esse é o comportamento pretendido ou existe uma maneira de corrigir isso?

Aqui está o meu FBMessagingService:

import android.util.Log;

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

public class FBMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.i("PVL", "MESSAGE RECEIVED!!");
        if (remoteMessage.getNotification().getBody() != null) {
            Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getNotification().getBody());
        } else {
            Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getData().get("message"));
        }
    }
}

Além do corpo do json, onde está o seu código onTokenRefresh ? Você concluiu a configuração do Android ?
Kato

4
Como assim, o corpo json da notificação? Além disso, meu código onTokenRefresh está dentro do meu serviço FirebaseInstanceID.
Cyogenos

Você pode postar a carga útil de amostra que está enviando?
AL.


Você também pode verificar este segmento stackoverflow.com/questions/39046270/…
Md. Sajedul Karim

Respostas:


144

Isso está funcionando conforme o planejado, as mensagens de notificação são entregues ao seu retorno de chamada onMessageReceived somente quando o aplicativo está em primeiro plano. Se o seu aplicativo estiver em segundo plano ou fechado, uma mensagem de notificação será exibida no centro de notificações, e todos os dados dessa mensagem serão transmitidos para a intenção lançada como resultado do toque do usuário na notificação.

Você pode especificar uma ação de clique para indicar a intenção que deve ser iniciada quando a notificação for tocada pelo usuário. A atividade principal é usada se nenhuma ação de clique for especificada.

Quando a intenção é iniciada, você pode usar o

getIntent().getExtras();

recuperar um conjunto que inclua qualquer dado enviado junto com a mensagem de notificação.

Para mais informações sobre a mensagem de notificação, consulte os documentos .


6
Existe uma maneira de definir click_actionquando estou usando o Firebase Notification Console?
Nii Laryea

6
ok, mas e se o aplicativo for morto (sem primeiro plano ou plano de fundo)?
michalu

3
Mas como desativar a notificação de descarte do usuário? Porque se o usuário descartá-lo, significa que todos os dados serão ignorados ... Certo?
Aleksey Timoshchenko 01/09/16

4
Corrigir! Portanto, ao enviar mensagens de notificação para o Android, os dados que acompanham devem ser aqueles que melhoram a experiência de notificação. Não devem ser dados críticos do aplicativo, use mensagens de dados para os dados de que o aplicativo precisa, mesmo que o usuário rejeite a notificação.
Arthur Thompson

3
Isso não é inteiramente correto. Se a mensagem contiver apenas dados e não carga útil de notificação, a mensagem SEMPRE será entregue ao onMessageReceive, se o aplicativo estiver em primeiro plano ou não.
precisa saber é o seguinte

125

Remova o notificationcampo completamente da sua solicitação do servidor. Envie apenasdata e manuseie-o, onMessageReceived()caso contrário o seu onMessageReceived()não será acionado quando o aplicativo estiver em segundo plano ou morto.

Não se esqueça de incluir o "priority": "high"campo na sua solicitação de notificação. De acordo com a documentação: as mensagens de dados são enviadas com prioridade normal e, portanto, não chegam instantaneamente; também poderia ser o problema.

Aqui está o que estou enviando do servidor

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

Para que você possa receber seus dados onMessageReceived(RemoteMessage message)desta maneira .... digamos que eu precise obter uma identificação

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

9
Descobri que, se eu enviar apenas uma mensagem de dados, o aplicativo que é limpo do gerenciador de tarefas não poderá receber notificações. Esse é um comportamento pretendido?
Prabhjot Singh

2
Esta foi a solução para eu receber mensagens em segundo plano!
Ray Hulha

5
No Oreo, quando o aplicativo é encerrado, onMessageReceived não está sendo chamado. eu só tenho carga útil apenas com dados. você tem alguma atualização?
Samir Mangroliya

2
Funciona como um encanto!
ssk

3
Te amo muito por esta resposta: p
Ahmad Arslan

63

esse método handleIntent () foi depreciado, portanto, o processamento de uma notificação pode ser feito da seguinte maneira:

  1. Estado de primeiro plano: O clique da notificação irá para a atividade do Intent pendente que você está fornecendo enquanto cria uma notificação de forma programática, como geralmente criada com a carga útil de dados da notificação.

  2. Background / Killed State - Aqui, o próprio sistema cria uma notificação com base na carga útil da notificação e clicar nessa notificação o levará à atividade do iniciador do aplicativo, onde é possível buscar facilmente dados do Intent em qualquer um dos seus métodos de ciclo de vida.


Obrigado!!! Perdi alguns dias com esse problema e este me salvou.
Igor Janković

realmente a solução perfeita!
EduXavier

4
Estou lidando com a lógica de exibição da notificação em handleIntent (Intent intent), no entanto, quando o aplicativo está em segundo plano, duas notificações são exibidas, uma que eu criei e outra por padrão, que contém toda a mensagem da notificação.
Joyson

5
Impressionante, mas não vejo utilidade OnMessageReceivednesse caso !?
Alaa AbuZarifa 4/17/17

8
Estou tendo com.google.firebase: firebase-messaging: 11.6.2 & handleIntent agora é final.Check stackoverflow.com/questions/47308155/…
Ronak Poriya

31

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 parâmetro click_action é 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, eu recomendo que você use o método onMessageReceived (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.

Do lado do servidor, a notificação da base de firmas deve seguir o formato :

O lado do servidor deve enviar o objeto "notificação" . Falta o objeto "notificação" no meu TargetActivitynão receber mensagem usando getIntent().

O formato correto da mensagem é fornecido abaixo:

{
 "data": {
  "body": "here is body",
  "title": "Title"
 },
"notification": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
 "to": "ffEseX6vwcM:APA91bF8m7wOF MY FCM ID 07j1aPUb"
}

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

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


3
vale ressaltar que "mensagens de dados" não serão recebidas se o dispositivo estiver no modo cochilo profundo (introduzido no Android 7.0). tenha cuidado com aqueles!
Samir J

30

Eu tive o mesmo problema. É mais fácil usar a 'mensagem de dados' em vez da 'notificação'. A mensagem de dados sempre carrega a classe onMessageReceived.

Nessa classe, você pode fazer sua própria notificação com o construtor de notificações.

Exemplo:

 @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        sendNotification(remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
    }

    private void sendNotification(String messageTitle,String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0 /* request code */, intent,PendingIntent.FLAG_UPDATE_CURRENT);

        long[] pattern = {500,500,500,500,500};

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_name)
                .setContentTitle(messageTitle)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setVibrate(pattern)
                .setLights(Color.BLUE,1,1)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }

7
Graças ..eu mudei meu código do servidor e uso "dados" em vez de "notificação" e perfeito agora ele está trabalhando,
Mahesh Kavathiya

5
@Koot funcionará apenas se o aplicativo estiver em primeiro plano e não se estiver em segundo plano. você pode me ajudar a acionar esse evento nos dois casos?
Anant Shah

@AnantShah, como é o seu POST para o servidor Firebase?
Koot

3
Na verdade, existem três casos possíveis aqui. 1) App em primeiro plano. 2) App em segundo plano. 3) O aplicativo não está sendo executado. Como você diz, uma mensagem de 'dados' será recebida nos dois primeiros casos, mas não no terceiro, quando o aplicativo não estiver sendo executado. Para atender aos três casos, você precisa definir o campo 'notificação' na mensagem. (Também uma boa idéia se você quiser dar suporte a clientes Android iOS, bem como)
Steve Moseley

1
Mesmo no aplicativo que não está sendo executado, ainda recebo uma mensagem do servidor na função recebida pela mensagem. Concordo com você que é melhor usar a 'notificação' se você também deseja oferecer suporte ao ios.
27416 Koot

21

Conforme a documentação do Firebase Cloud Messaging - se a atividade estiver em primeiro plano, o onMessageReceived será chamado. Se a Atividade estiver em segundo plano ou fechada, a mensagem de notificação será mostrada no centro de notificações da atividade do iniciador de aplicativos. Você pode chamar sua atividade personalizada com um clique de notificação se o aplicativo estiver em segundo plano, chamando a API do serviço de repouso para mensagens do firebase como:

URL - https://fcm.googleapis.com/fcm/send

Tipo de método - POST

Header- Content-Type:application/json
Authorization:key=your api key

Corpo / Carga útil:

{ "notification": {
    "title": "Your Title",
    "text": "Your Text",
     "click_action": "OPEN_ACTIVITY_1" // should match to your intent filter
  },
    "data": {
    "keyname": "any value " //you can get this data as extras in your activity and this data is optional
    },
  "to" : "to_id(firebase refreshedToken)"
} 

E com isso no seu aplicativo, você pode adicionar o código abaixo na sua atividade a ser chamado:

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

Onde eu criaria a intenção e a abriria uma atividade específica? Sei que isso registra a intenção OPEN_ACTIVITY_1 no manifesto, mas onde eu realmente o chamo?
Cyogenos


Devemos chamar uma atividade de filtros de intenção? Ou iniciá-lo manualmente onMessageReceived?
CoolMind

14

Método onMessageReceived (RemoteMessage remoteMessage) chamado com base nos seguintes casos.

  • Resposta FCM Com notificação e bloco de dados :
{
  
"to": "device token list",
  "notification": {
    "body": "Body of Your Notification",
    "title": "Title of Your Notification"
  },
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}
  1. Aplicativo em primeiro plano:

onMessageReceived (RemoteMessage remoteMessage) chamado, mostra LargeIcon e BigPicture na barra de notificação. Podemos ler o conteúdo da notificação e do bloco de dados

  1. Aplicativo em segundo plano:

onMessageReceived (RemoteMessage remoteMessage) não chamado, a bandeja do sistema receberá a mensagem e lerá o corpo e o título do bloco de notificação e mostra a mensagem e o título padrão na barra de notificação.

  • Resposta FCM Com apenas bloco de dados :

Nesse caso, removendo os blocos de notificação do json

{
  
"to": "device token list",
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}

Solução para chamar onMessageReceived ()

  1. Aplicativo em primeiro plano:

onMessageReceived (RemoteMessage remoteMessage) chamado, mostra LargeIcon e BigPicture na barra de notificação. Podemos ler o conteúdo da notificação e do bloco de dados

  1. Aplicativo em segundo plano:

chamado onMessageReceived (RemoteMessage remoteMessage) chamado, a bandeja do sistema não receberá a mensagem porque a chave de notificação não está na resposta. Mostra LargeIcon e BigPicture na barra de notificação

Código

 private void sendNotification(Bitmap bitmap,  String title, String 
    message, PendingIntent resultPendingIntent) {

    NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
    style.bigPicture(bitmap);

    Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    String NOTIFICATION_CHANNEL_ID = mContext.getString(R.string.default_notification_channel_id);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);

        notificationManager.createNotificationChannel(notificationChannel);
    }
    Bitmap iconLarge = BitmapFactory.decodeResource(mContext.getResources(),
            R.drawable.mdmlogo);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID)
            .setSmallIcon(R.drawable.mdmlogo)
            .setContentTitle(title)
            .setAutoCancel(true)
            .setSound(defaultSound)
            .setContentText(message)
            .setContentIntent(resultPendingIntent)
            .setStyle(style)
            .setLargeIcon(iconLarge)
            .setWhen(System.currentTimeMillis())
            .setPriority(Notification.PRIORITY_MAX)
            .setChannelId(NOTIFICATION_CHANNEL_ID);


    notificationManager.notify(1, notificationBuilder.build());


}

Link de referência:

https://firebase.google.com/docs/cloud-messaging/android/receive


A parte mais importante para pessoas que sofrem de problemas em segundo plano é remover a propriedade "notification" do JSON que está sendo enviada pelo servidor. isso resolve o problema. Muito obrigado.
Ramy M. Mousa

13

Eu tenho o mesmo problema. Se o aplicativo estiver em primeiro plano, ele acionará meu serviço em segundo plano, onde eu posso atualizar meu banco de dados com base no tipo de notificação. Mas, o aplicativo fica em segundo plano - o serviço de notificação padrão terá o cuidado de mostrar a notificação ao usuário.

Aqui está minha solução para identificar aplicativos em segundo plano e acionar seu serviço em segundo plano,

public class FirebaseBackgroundService extends WakefulBroadcastReceiver {

  private static final String TAG = "FirebaseService";

  @Override
  public void onReceive(Context context, Intent intent) {
    Log.d(TAG, "I'm in!!!");

    if (intent.getExtras() != null) {
      for (String key : intent.getExtras().keySet()) {
        Object value = intent.getExtras().get(key);
        Log.e("FirebaseDataReceiver", "Key: " + key + " Value: " + value);
        if(key.equalsIgnoreCase("gcm.notification.body") && value != null) {
          Bundle bundle = new Bundle();
          Intent backgroundIntent = new Intent(context, BackgroundSyncJobService.class);
          bundle.putString("push_message", value + "");
          backgroundIntent.putExtras(bundle);
          context.startService(backgroundIntent);
        }
      }
    }
  }
}

No manifest.xml

<receiver android:exported="true" android:name=".FirebaseBackgroundService" android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </receiver>

Testou esta solução na versão mais recente do Android 8.0. obrigado


whare para usar esta classe FirebaseBackgroundService ?? @Nagendra Badiganti

onde usar esse código classe pública FirebaseBackgroundService estende WakefulBroadcastReceiver @Nagendra Badiganti

crie uma classe de serviço no seu pacote e registre-se no seu manifest.xml. Verifique se você tem o filtro para suas notificações. Como o serviço é acionado para todas as notificações do GCM.
Nagendra Badiganti

firebase.google.com/docs/cloud-messaging/android/… estou seguindo este link, preciso adicionar esta classe para receber uma notificação. apenas o envio de mensagens a partir da primeira mensagem firebase .. ele diz concluída, mas a notificação não receber @Nagendra Badiganti

1
WakefulBroadcastReceiverfoi descontinuado desde o nível da API 26.1.0.
Minoru

12

Se o aplicativo estiver no modo de plano de fundo ou inativo (eliminado) e você clicar em Notificação , verifique a carga útil no LaunchScreen (no meu caso, a tela de inicialização é MainActivity.java).

Portanto, em MainActivity.java, no onCreate, verifique os extras :

    if (getIntent().getExtras() != null) {
        for (String key : getIntent().getExtras().keySet()) {
            Object value = getIntent().getExtras().get(key);
            Log.d("MainActivity: ", "Key: " + key + " Value: " + value);
        }
    }

Como posso obter título, corpo e dados da notificação?
Md.Tarikul Islam

1
Obrigado, esta é a resposta. @ Md.Tarikul Islam usando onMessageReceived () como mencionado nesta pergunta.
Felixwcf 26/01

7

Substitua o handleIntentmétodo dos FirebaseMessageServicetrabalhos para mim.

aqui o código em C # (Xamarin)

public override void HandleIntent(Intent intent)
{
    try
    {
        if (intent.Extras != null)
        {
            var builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            foreach (string key in intent.Extras.KeySet())
            {
                builder.AddData(key, intent.Extras.Get(key).ToString());
            }

            this.OnMessageReceived(builder.Build());
        }
        else
        {
            base.HandleIntent(intent);
        }
    }
    catch (Exception)
    {
        base.HandleIntent(intent);
    }
}

e isso é o código em Java

public void handleIntent(Intent intent)
{
    try
    {
        if (intent.getExtras() != null)
        {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            for (String key : intent.getExtras().keySet())
            {
                builder.addData(key, intent.getExtras().get(key).toString());
            }

            onMessageReceived(builder.build());
        }
        else
        {
            super.handleIntent(intent);
        }
    }
    catch (Exception e)
    {
        super.handleIntent(intent);
    }
}

handleIntent () é final
Ettore

@Ettore Como posso chamar a função handleIntent?
Hiroto

O método é chamado quando você recebe a mensagem do Firebase, mas você não pode substituir porque o método é declarado final. (Firebase 11.6.0)
Ettore

5

Por padrão, a Atividade do iniciador no seu aplicativo será iniciada quando o aplicativo estiver em segundo plano e você clicar na notificação. Se houver alguma parte dos dados com sua notificação, você poderá manipulá-la na mesma atividade a seguir,

if(getIntent().getExtras()! = null){
  //do your stuff
}else{
  //do that you normally do
}

Se eu navegar de mainActivity, como navegar de volta para determinada Atividade funcionará?
Mac_Play

. @Uzair getIntent () getExtras () sempre recebendo nulo, Você tem alguma outra solução Quando aplicativo vai bacground onMessageReceived método não chamar?
user2025187

3

Se o aplicativo estiver em segundo plano Base de fogo por notificação de manipulação padrão, mas se queremos nossa notificação personalizada, precisamos alterar o lado do servidor, responsável por enviar nossos dados personalizados (carga útil dos dados)

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

agora, seu formato de código no servidor se parece,

{
  "collapse_key": "CHAT_MESSAGE_CONTACT",
  "data": {
    "loc_key": "CHAT_MESSAGE_CONTACT",
    "loc_args": ["John Doe", "Contact Exchange"],
    "text": "John Doe shared a contact in the group Contact Exchange",
    "custom": {
      "chat_id": 241233,
      "msg_id": 123
    },
    "badge": 1,
    "sound": "sound1.mp3",
    "mute": true
  }
}

NOTA : veja esta linha no código acima
"text": "John Doe compartilhou um contato no grupo Contact Exchange" na carga útil dos dados, você deve usar o parâmetro "text" em vez dos parâmetros "body" ou "message" para a descrição da mensagem ou o que você quiser. quer usar texto.

onMessageReceived ()

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.e(TAG, "From: " + remoteMessage.getData().toString());

        if (remoteMessage == null)
            return;

        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
           /* Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());*/
            Log.e(TAG, "Data Payload: " + remoteMessage);

            try {

                Map<String, String> params = remoteMessage.getData();
                JSONObject json = new JSONObject(params);
                Log.e("JSON_OBJECT", json.toString());


                Log.e(TAG, "onMessageReceived: " + json.toString());

                handleDataMessage(json);
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }
    }

2

Basta chamar isso no método onCreate do MainActivity:

if (getIntent().getExtras() != null) {
           // Call your NotificationActivity here..
            Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
            startActivity(intent);
        }

Se eu navegar de mainActivity, como navegar de volta para determinada Atividade funcionará?
11388 Mac_Play

2

de acordo com a solução da t3h Exi, gostaria de postar o código limpo aqui. Basta colocá-lo no MyFirebaseMessagingService e tudo funcionará bem se o aplicativo estiver no modo de segundo plano. Você precisa pelo menos compilar com.google.firebase: firebase-messaging: 10.2.1

 @Override
public void handleIntent(Intent intent)
{
    try
    {
        if (intent.getExtras() != null)
        {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            for (String key : intent.getExtras().keySet())
            {
                builder.addData(key, intent.getExtras().get(key).toString());
            }



           onMessageReceived(builder.build());
        }
        else
        {
            super.handleIntent(intent);
        }
    }
    catch (Exception e)
    {
        super.handleIntent(intent);
    }
}

Eu estou tentando implementar a sua solução, mas o método handleIntent () é final na minha SDK versão (SDK 27), por isso não posso substituí-lo no meu serviço ...
matdev

Sim, mas isso não é culpa minha ou qualquer motivo para dar -1 !!! Muito arrogante. Funciona até o firebase 11.4.2 e, em seguida, o Google mudou (tornou este método final). Então agora você deve programar sua própria solução com notificação.
Frank

Eu não dei um -1, mas um +1!
matdev

Você salva meu trabalho: P
amitabha2715 26/02

2

Tente o seguinte:

public void handleIntent(Intent intent) {
    try {
        if (intent.getExtras() != null) {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
            for (String key : intent.getExtras().keySet()) {
            builder.addData(key, intent.getExtras().get(key).toString());
        }
            onMessageReceived(builder.build());
        } else {
            super.handleIntent(intent);
        }
    } catch (Exception e) {
        super.handleIntent(intent);
    }
}

handleIntent não é mais usado no firebase: 11.8.0 e superior.
Shihab Uddin

1

Eu tive esse problema (o aplicativo não deseja abrir ao clicar em notificação, se o aplicativo estiver em segundo plano ou fechado) e o problema era inválido click_actionno corpo da notificação, tente removê-lo ou alterá-lo para algo válido.


1

O ponto que merece destaque é que você precisa usar a mensagem de dados - apenas chave de dados - para obter o manipulador onMessageReceived chamado mesmo quando o aplicativo está em segundo plano. Você não deve ter nenhuma outra chave de mensagem de notificação em sua carga, caso contrário, o manipulador não será acionado se o aplicativo estiver em segundo plano.

É mencionado (mas não tão enfatizado na documentação do FCM) aqui:

https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

Use o servidor de aplicativos e a API do servidor FCM: defina apenas a chave de dados . Pode ser dobrável ou não dobrável.


1

O back-end com o qual estou trabalhando está usando mensagens de notificação e não mensagens de dados. Então, depois de ler todas as respostas, tentei recuperar os extras do pacote da intenção que vem para a atividade lançada. Mas, independentemente de quais chaves eu tentei recuperar getIntent().getExtras();, o valor sempre foi nulo.

No entanto, finalmente encontrei uma maneira de enviar dados usando mensagens de notificação e recuperá-los da intenção.

A chave aqui é adicionar a carga útil dos dados à mensagem de notificação.

Exemplo:

{
    "data": {
        "message": "message_body",
        "title": "message_title"
    },
    "notification": {
        "body": "test body",
        "title": "test title"
    },
    "to": "E4An.."
}

Depois de fazer isso, você poderá obter suas informações desta maneira:

intent.getExtras().getString("title") será message_title

e intent.getExtras().getString("message") serámessage_body

Referência


1

Se o seu problema estiver relacionado à exibição de imagem grande, ou seja, se você estiver enviando uma notificação por push com uma imagem do console do firebase, ela será exibida apenas se o aplicativo estiver em primeiro plano. A solução para esse problema é enviar uma mensagem push apenas com o campo de dados. Algo assim:

{ "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" }

você perdeu vírgula antes de "AnotherActivity". Meu android vibra, mas na verdade nada é mostrado (sem texto, sem imagem, sem push).
jekaby

1

Quando a mensagem é recebida e seu aplicativo está em segundo plano, a notificação é enviada para a intenção extra da atividade principal.

Você pode verificar o valor extra na função oncreate () ou onresume () da atividade principal.

Você pode verificar os campos como dados, tabela etc. (o especificado na notificação)

por exemplo, enviei usando dados como a chave

public void onResume(){
    super.onResume();
    if (getIntent().getStringExtra("data")!=null){
            fromnotification=true;
            Intent i = new Intent(MainActivity.this, Activity2.class);
            i.putExtra("notification","notification");
            startActivity(i);
        }

}

0

Eu estava tendo o mesmo problema e fiz mais algumas investigações sobre isso. Quando o aplicativo está em segundo plano, uma mensagem de notificação é enviada para a bandeja do sistema, MAS uma mensagem de dados é enviada para onMessageReceived()
Consulte https://firebase.google.com/docs/cloud-messaging/downstream#monitor-token-generation_3
e https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java

Para garantir que a mensagem que você está enviando, os documentos digam: " Use o servidor de aplicativos e a API do servidor FCM: defina apenas a chave de dados. Pode ser recolhível ou não recolhível " .
Consulte https://firebase.google.com/ docs / cloud-messaging / concept-options # Notifications_and_data_messages


0

Existem dois tipos de mensagens: mensagens de notificação e mensagens de dados. Se você enviar apenas uma mensagem de dados, isso não terá um objeto de notificação na sequência de mensagens. Seria invocado quando seu aplicativo em segundo plano.


0

Verifique a resposta de @Mahesh Kavathiya. Para o meu caso, no código do servidor tem apenas assim:

{
"notification": {
  "body": "here is body",
  "title": "Title",
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}

Você precisa mudar para:

{
 "data": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
"notification": {
  "body": "here is body",
  "title": "Title"
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}

Em seguida, no caso do aplicativo em segundo plano, a intenção padrão da atividade extra obterá "dados"

Boa sorte!


-1

Basta substituir o método OnCreate do FirebaseMessagingService. É chamado quando o aplicativo está em segundo plano:

public override void OnCreate()
{
    // your code
    base.OnCreate();
}

Esta resposta pode ser mais útil se você puder adicionar uma explicação e criar um link para alguma documentação. Você pode nos dizer como isso deve ajudar?
kilokahn

@kilokahn Você pode me explicar o que não entende? o método indicado deve ser inserido no código que faz parte da pergunta e responde totalmente à pergunta. O código é para o Xamarin, mas você pode simplesmente converter em java.
Renzo Ciot #

AFAIK A documentação oficial ( firebase.google.com/docs/cloud-messaging/android/client ) não fala sobre substituir o OnCreate em um serviço que estende o FirebaseMessagingService - se você tiver acesso à documentação que possui, talvez possa compartilhar um link? Além disso, pela sua resposta, não está claro como a substituição de onCreate resolve o problema de onMessageReceived não ser chamado quando a notificação é clicada - daí a solicitação de mais informações.
kilokahn

A documentação não menciona a substituição do método OnCreate, mas funciona porque estou usando-o na produção. O código que você deseja inserir no método onMessageReceived e que obviamente serve para executar algumas operações em segundo plano pode ser executado no OnCreate.
Renzo Ciot

Nesse caso, elaborar o fato de que de alguma forma funcionou para você pode ser mais útil do que apenas listar a solução. Além disso, é provável que o comportamento não documentado pare arbitrariamente de trabalhar com atualizações, e alguém que as usa precisa estar preparado para refazer seu código quando isso acontecer. Isso precisa disclaimer para ser colocado em.
kilokahn

-1

Existem 2 tipos de notificações push do Firebase :

1- Mensagem de notificação (Mensagem de exibição) -> - 1.1 Se você escolher essa variante, o sistema operacional criará uma notificação automática se o aplicativo estiver em segundo plano e passará os dados para o intent. Cabe ao cliente lidar com esses dados.

- 1.2 Se o aplicativo estiver em primeiro plano , a notificação será recebida callback-functionno FirebaseMessagingServicee cabe ao cliente lidar com isso.

2- Mensagens de dados (até 4k dados) -> Essas mensagens são usadas para enviar apenas dados ao cliente (silenciosamente) e cabe ao cliente lidar com os dois casos em segundo plano / primeiro plano por meio da função de retorno de chamada em FirebaseMessagingService

Isso está de acordo com os documentos oficiais: https://firebase.google.com/docs/cloud-messaging/concept-options

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.