关于firebase:firebase_messaging如何清除通知?

firebase_messaging how to clear notification?

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
      },
    );
  }

在调用onMessage,onResume和onLaunch方法时,每次都会调用_showPushNotificationDialog方法。

面临的问题,例如当我的应用程序处于后台或终止模式时,通知会出现,并在通知托盘上轻按即可,一切正常。但是,当我转到另一页并一直返回到上一个_firebaseMessaging.configure(....方法调用时,该方法调用具有数据,因此每次我的警报对话框弹出时。

那么如何清除通知托盘中单击的通知?


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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),
            ),
            );
  }

然后我在路由小部件的初始化中调用了此方法:

1
2
3
4
5
6
7
@override
  void initState(){
    super.initState();
    refreshServices();
    getDirectionBasedOnLocation();
    MessagingWidget.configuringFirebase(currentUser, context);
}

希望这对您有所帮助


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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);
 }
}

现在我们可以在配置中调用此函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
 _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);
  },
);

我要防止onLaunch和onResume方法一次又一次运行的方法是用最后一个通知检查当前通知(我使用shared_preferences)

以下是代码段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
_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');
  }
}

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

  • 添加flutter_local_notifications
  • import 'package:flutter_local_notifications/flutter_local_notifications.dart';
  • 只需创建final fln = FlutterLocalNotificationsPlugin();

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


  • 尝试在initState而非自定义方法中配置firebaseMessaging。那应该工作:)