Trabajando a partir de julio de 2019
Android compileSdkVersion 28, buildToolsVersion 28.0.3 y firebase-messaging: 19.0.1
Después de muchas horas de investigación a través de todas las otras preguntas y respuestas de StackOverflow, y probando innumerables soluciones obsoletas, esta solución logró mostrar notificaciones en estos 3 escenarios:
- La aplicación está en primer plano:
la notificación se recibe mediante el método onMessageReceived en mi clase MyFirebaseMessagingService
- La aplicación ha sido eliminada (no se está ejecutando en segundo plano):
FCM envía automáticamente la notificación a la bandeja de notificaciones. Cuando el usuario toca la notificación, la aplicación se inicia llamando a la actividad que tiene android.intent.category.LAUNCHER en el manifiesto. Puede obtener la parte de datos de la notificación utilizando getIntent (). GetExtras () en el método onCreate ().
- La aplicación está en segundo plano:
FCM envía automáticamente la notificación a la bandeja de notificaciones. Cuando el usuario toca la notificación, la aplicación se pone en primer plano al iniciar la actividad que tiene android.intent.category.LAUNCHER en el manifiesto. Como mi aplicación tiene launchMode = "singleTop" en esa actividad, no se llama al método onCreate () porque ya se ha creado una actividad de la misma clase, sino que se llama al método onNewIntent () de esa clase y obtiene la parte de datos de la notificación allí usando intent.getExtras ().
Pasos: 1- Si define la actividad principal de su aplicación de esta manera:
<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- agrega estas líneas en el método onCreate () de tu 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);
}
}
y estos métodos a la misma clase 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- crea la clase MyFirebase así:
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- crea una nueva clase NotificationActivity.class como esta:
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- Agrega estas líneas al Manifiesto de tu aplicación, dentro de tus etiquetas
<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- agrega estas líneas en tu método Application.java onCreate (), o en el 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));
}
Hecho.
Ahora, para que esto funcione bien en los 3 escenarios mencionados, debe enviar la notificación desde la consola web de Firebase de la siguiente manera:
En la sección Notificación: Título de notificación = Título para mostrar en el cuadro de diálogo de notificación (opcional) Texto de notificación = Mensaje para mostrar al usuario (obligatorio) Luego en la sección Destino: Aplicación = su aplicación de Android y en la sección Opciones adicionales: Canal de notificación de Android = default_channel_id Clave de datos personalizados: valor del título: (el mismo texto aquí que en el campo Título de la sección de notificaciones) clave: valor del cuerpo: (el mismo texto aquí que en el campo Mensaje de la sección de notificaciones) clave: click_action valor: .MainActivity Sound = Deshabilitado
Caduca = 4 semanas
Puede depurarlo en el emulador con API 28 con Google Play.
¡Feliz codificación!
Not getting messages here? See why this may be: goo.gl/39bRNJ
. La solución, como las respuestas a continuación, se puede encontrar en la documentación en Mensajes con notificaciones y cargas de datos