我的应用前台服务被终止时未收到 FCM 通知

问题描述

当我的应用程序前台服务被终止时未收到 FCM 通知,更清楚地说,我试图让我的应用程序始终在后台运行,并且我使用前台服务来实现这一点,有时应用程序没有被终止ANDROID 系统和前台通知出现超过 15 小时,但其他时候当我的前台通知被杀死并且我发送它没有被我的设备接收到的 FCM 通知时,它会在 1 小时或更短时间或 2 小时或更短时间后被杀死!这里有什么问题!怎么解决

解决方法

在前台处理通知

当应用关闭时,您的通知由 Google 服务进程处理,该进程负责根据需要显示您的通知,包括默认点击操作(打开应用)和通知图标。

当应用程序在前台时,接收到的消息由应用程序处理,由于没有逻辑来处理它,所以什么都不会发生!

要解决此问题,我们需要自己的 FirebaseMessagingService,让我们创建一个。创建一个新类来扩展它并实现 onMessageReceived 方法。然后从 remoteMessage 获取 Notification 对象并创建您自己的 Android 通知。

public class NotificationService extends FirebaseMessagingService { 
  @Override
  public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    Notification notification = new NotificationCompat.Builder(this)
      .setContentTitle(remoteMessage.getNotification().getTitle())
      .setContentText(remoteMessage.getNotification().getBody())
      .setSmallIcon(R.mipmap.ic_launcher)
      .build();
     NotificationManagerCompat manager = NotificationManagerCompat.from(getApplicationContext());
     manager.notify(123,notification);
   }
}

然后在您的 AndroidManifest.xml

中添加服务
<service android:name=”.NotificationService”>
 <intent-filter>
  <action android:name=”com.google.firebase.MESSAGING_EVENT”/>
 </intent-filter>
</service>

现在,如果您再试一次,您将在应用处于前台时显示通知!

在现实生活中,您的 onMessageReceived 内容会稍微复杂一些,根据通知的类型,您需要不同的智能操作,您需要显示更好的大图标(出现在通知上的图标) body) 并确保更改状态栏图标。

您现在遇到的问题是您的 onMessageReceived 仅在应用程序处于前台时调用,如果您的应用程序在后台运行,Google 服务将负责显示您的消息。

解决方案?不要使用“通知”消息有效负载,而是使用“数据”。 使用数据

解决这个前台/后台问题的最后一步是从您的消息负载中丢弃通知对象。

而不是发送:

{
   "to": "the device token"
   "notification":{
     "title":"New Notification!","body":"Test"
   },"priority":10
 }

Send:

{
   "to": "the device token"
   "data":{
     "title":"New Notification!","priority":10
 }

这样,您的通知将始终由应用、您的 NotificationService 处理,而不是由 Google 服务进程处理。

您还需要更改代码以处理数据负载:

// Old Way
//.setContentTitle(remoteMessage.getNotification().get(“title”))
//.setContentText(remoteMessage.getNotification().get(“body”))

// New Way
.setContentTitle(remoteMessage.getData().get(“title”))
.setContentText(remoteMessage.getData().get(“body”))

你的整个 NotificationService 现在看起来像这样:

public class NotificationService extends FirebaseMessagingService { 
  @Override
  public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    Notification notification = new NotificationCompat.Builder(this)
      .setContentTitle(remoteMessage.getData().get(“title”))
      .setContentText(remoteMessage.getData().get(“body”))
      .setSmallIcon(R.mipmap.ic_launcher)
      .build();
     NotificationManagerCompat manager = NotificationManagerCompat.from(getApplicationContext());
     manager.notify(123,notification);
   }
}

使用数据而不是通知对象的另一个优点是您可以在“数据”对象中放入任何您想要的内容。例如,用户 ID、图像的 URL……您可能想要用于构建通知或传递给点击操作的任何信息。请注意,所有内容都将被视为字符串。例如,

"data":{
     "title":"New Notification!","body":"Test","user_id": "1234","avatar_url": "http://www.example.com/avatar.jpg"
 },

本文档的处理消息部分也解释了这种差异: https://firebase.google.com/docs/cloud-messaging/android/receive

结论

请注意,如果您将“通知”对象保留在您的有效负载中,它将像以前一样运行。你需要去掉“通知”,只提供“数据”对象。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...