firebase_messaging 如何清除通知?

Posted

技术标签:

【中文标题】firebase_messaging 如何清除通知?【英文标题】:firebase_messaging how to clear notification? 【发布时间】:2019-09-26 04:51:12 【问题描述】:

我正在使用firebase_messaging 当通知到来时,我正在显示警报对话框。下面是我的代码。

showNotification(BuildContext context) 
    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async 
        print('on message $message');
        _showPushNotificationDialog(message['notification']['title'],
            message['notification']['body'], context);
      ,
      onResume: (Map<String, dynamic> message) async 
        print('on resume $message');
        _showPushNotificationDialog(
            message['data']['title'], message['data']['body'], context);
      ,
      onLaunch: (Map<String, dynamic> message) async 
        print('on launch $message');
        _showPushNotificationDialog(
            message['data']['title'], message['data']['body'], context);
      ,
    );
  

onMessageonResumeonLaunch方法调用时,每次调用_showPushNotificationDialog方法。

面临的问题,例如当我的应用程序处于后台或终止模式时,会出现通知并点击通知托盘,一切正常。但是当我转到其他页面并一直返回到上一个时,_firebaseMessaging.configure(.... 方法调用并且它有数据,所以每次我的警报对话框都会弹出。

那么如何清除被通知托盘点击的通知呢?

【问题讨论】:

你找到解决方案了吗,我也有同样的问题@govaadiyo 对不起,不行@EvripidesKyriacou 【参考方案1】:

我也遇到了这个问题。我有这个解决方法: 我所做的是用静态布尔和静态方法创建一个类:

class MessagingWidget 

  static bool _isConfigured = false;


  static void configuringFirebase(User currentUser, BuildContext context)
      

      final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
      if (!_isConfigured) 
      _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async 
        print("onMessage: $message");
        final notification = message['notification'];
      ,
      onLaunch: (Map<String, dynamic> message) async 
        print("onLaunch: $message");

        final notification = message['data'];
        if(notification['title']!=null)
            if(notification['title']=="Testo")
              goToAppointmentsScreen(currentUser,context);

            
          
      ,
      onResume: (Map<String, dynamic> message) async 
        print("onResume: $message");

        final notification = message['data'];
        if(notification['title']!=null)
            if(notification['title']=="Testo")
              goToAppointmentsScreen(currentUser,context);

            
          
      ,
    );
    _isConfigured = true;
    

  
    
    
  

  void goToAppointmentsScreen(User currentUser1, BuildContext context1) async 
    final bool backFromAppointmentsScreen=await Navigator.push(
            context1,
            MaterialPageRoute(builder: (context) => Appointment( 
              currentUser1),
            ),
            );
  

然后我在路由小部件的 init 中调用了这个方法:

@override
  void initState()
    super.initState();
    refreshServices();
    getDirectionBasedOnLocation();
    MessagingWidget.configuringFirebase(currentUser, context);

希望对你有帮助

【讨论】:

这不是最好的解决方案,但它有效,谢谢【参考方案2】:

为了防止 onLaunch 和 onResume 方法一次又一次地运行,我所做的是检查当前通知与最后一个通知(我使用 shared_preferences)

这是sn-p:

_firebaseMessaging.configure(
    onMessage: (Map<String, dynamic> message) async 
      print('on message $message');
      onMessageReceived(context, message);
    ,
    onResume: (Map<String, dynamic> message) async 
      print('on resume $message');
      onLaunch(context, message);
    ,
    onLaunch: (Map<String, dynamic> message) async 
      print('on launch $message');
      onLaunch(context, message);
    ,
  );

.
.
.

void onLaunch(BuildContext context, Map<String, dynamic> remoteMessage) async 
  var pref = SharedPreferences.getInstance();

  var data = remoteMessage['data'] ?? remoteMessage;
  String lastData = '';

  await pref.then((prefs) 
    lastData = prefs.get('remote_message');
  );

  if ((data['type'] != null || data['id'] != null) &&
      data.toString() != lastData) 

    toDetailPageFromPush(
      context,
      data['type'],
      data['id'],
    );
    pref.then((prefs) 
      prefs.setString('remote_message', data.toString());
    );
   else 
    print('on launch error $remoteMessage');
  

【讨论】:

【参考方案3】:

这是另一种解决方案,使用通知中的唯一值 message_id,因此我们可以使用共享偏好保存通知的最后一个 id 并与当前通知进行比较:

processNotification(message, BuildContext context) async 
 try 

  SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
 
  String lastMessageId = sharedPreferences.getString('last_message_id');
  String currentMessageId = message['data']['google.message_id'];

  //COMPARE NOTIFICATIONS ID
  if(currentMessageId != lastMessageId) 
    
     //SET LAST NOTIFICATION ID
     sharedPreferences.setString('last_message_id', currentMessageId);
 
     //SHOW A DIALOG OR NAVIGATE TO SOME VIEW, IN THIS CASE TO A VIEW
     String screen = message['data']['screen'];
     Navigator.of(context).pushNamed(screen);
  
 catch (e) 
  print('ERROR PROCESSING NOTIFICATION');
  print(e);
 

现在我们可以在配置中调用这个函数了:

 _firebaseMessaging.configure(
  onMessage: (Map<String, dynamic> message) async 
    print('on message $message');
    processNotification(context,message);
  ,
  onResume: (Map<String, dynamic> message) async 
    print('on resume $message');
    processNotification(context,message);
  ,
  onLaunch: (Map<String, dynamic> message) async 
    processNotification(context,message);
  ,
);

【讨论】:

【参考方案4】:

尝试在 initState 中而不是在自定义方法中配置 firebaseMessaging。这应该工作:)

【讨论】:

这个方法从 initState 调用:) @Govaadiyo :也许我遇到了和你一样的问题(现在我想我可能误解了你最初的问题)。我打开了一个 github issue,但没有得到官方 Flutter 开发者的答复。尽管如此,我找到了一个似乎对我有用的解决方法。也许它对你也有帮助?你可以在这里找到我的问题和我的工作:github.com/flutter/flutter/issues/32698#issuecomment-494766329【参考方案5】:

我知道,有点丑,但我只知道这样:

    添加flutter_local_notifications import 'package:flutter_local_notifications/flutter_local_notifications.dart';

    只需创建final fln = FlutterLocalNotificationsPlugin();

    并在需要时使用fln.cancelAll()

【讨论】:

以上是关于firebase_messaging 如何清除通知?的主要内容,如果未能解决你的问题,请参考以下文章

当应用程序通过使用 firebase_messaging 的推送通知终止时如何接收自定义数据?

firebase_messaging :没有通知通过

Flutter 推送通知应用背景:firebase_messaging

使用颤振 firebase_messaging 插件发送通知声音

使用 firebase_messaging 自定义通知(Android 和 IOS)

为啥在 Flutter 中使用 firebase_messaging 插件在 ios 中没有收到通知?