How to disable cloud messaging per device/user in flutter?

5,599

Thanks to a big nudge in the right direction from Doug, I was able to figure it out! Posting my code below to help anyone take the same step in the right direction.

So, in my flutter app' settings page the user can turn notifications on and off for a few categories. The user's preference is then stored in a user specific document in my Cloud Firestore users collection. See the below code for an example of the SwitchListTile I used on the settings page.

SwitchListTile(
   title: Text('Admin notifications'),
   subtitle: Text('Maintenance and general notes'),
   onChanged: (value) {
     setState(() {
       adminNotifications = value;
       Firestore.instance
       .collection('users')
       .document(loggedInUser.uid)
       .updateData({
       'adminNotifications': value,
       });
    });
    save('adminNotifications', value);
  },
  value: adminNotifications,
),

In my cloud function I added a reference to the document in the users collection and a check to see if the value of the field adminNotifications is equal to true. If so, a notification is send, otherwise a notification is not send to the user. Below I've added the cloud function. Please do note that the cloud function renders 'nested promises' warnings, but it works for now! I'm still a Flutter beginner so I was pretty happy to get it working. Big thanks again to Doug!

exports.userNotifications = functions.firestore.document('notifications/{any}').onCreate((change, context) => {
    const userFcm = change.data().fcmToken;
    const title = change.data().title;
    const body = change.data().body;
    const forUser = change.data().for;
    const notificationContent = {
    notification: {
        title: title,
        body: body,
        badge: '1',
        click_action: 'FLUTTER_NOTIFICATION_CLICK',
        }
    };
    var usersRef = db.collection('users');
    var queryRef = usersRef.where('login', '==', forUser).limit(1).get()
    .then(snapshot => {
        snapshot.forEach(doc => {
            const adminNotifications = doc.data().adminNotifications;
            console.log(adminNotifications);

            if(swapNotifications === true){
                return admin.messaging().sendToDevice(userFcm, notificationContent)
                    .then(() => {
                    console.log('notification sent')
                    return
                    })
                    .catch(error =>{
                        console.log('error in sending notification', error)
                    })
                } else {
                    console.log('message not send due to swapNotification preferences')
                }
    return console.log('reading user data success');
    })
    .catch(err => {
        console.log('error in retrieving user data:', err)
    })
});
Share:
5,599
Lorence Cramwinckel
Author by

Lorence Cramwinckel

Flutter beginner and overall coding enthusiast!

Updated on December 16, 2022

Comments

  • Lorence Cramwinckel
    Lorence Cramwinckel over 1 year

    For a flutter app I’m using Firebase Cloud Messaging and cloud functions to send push notifications to users, using their FCM registration tokens. The app has a settings page where users should be able to turn off certain push notifications. The notifications are user specific, so a topic to subscribe or unsubscribe to wouldn’t work, but the notifications can be classified in certain categories.

    For example in a chat app when user A send a message to user B that push notification could be in a category of ‘chat messages’, while user A could also delete the chat with user B and that push notification could be in a category of ‘deleted chats’.

    How can I make it so that user B can turn off notifications for ‘deleted chats’, while still receiving notifications for ‘chat messages’? Is it possible to use a condition with a topic and a user’s registration token on one way or the other? Any ideas are greatly appreciated!

    • Doug Stevenson
      Doug Stevenson over 4 years
      This seems pretty straightforward to implement with a combination of custom code and per-user configuration that determines if a message should be sent to the user's device token. What have you tried so far that isn't working the way you expect?
    • Lorence Cramwinckel
      Lorence Cramwinckel over 4 years
      So far whenever a notification event is triggered in the app a document is created in a ‘notifications’ collection in Firestore. A cloud function responsible for sending the push notification to the registration token has an onCreate method which fires each time a new document is added to this collection. I will edit my question to include the function! In terms of per user configuration I’m pretty clueless - shared preferences is as far as I’ve come.
    • Doug Stevenson
      Doug Stevenson over 4 years
      Just allow the user to configure the behavior they want using the contents of other documents that you can query in the function?
    • Lorence Cramwinckel
      Lorence Cramwinckel over 4 years
      That makes a lot of sense when you say it! Like setting a Boolean in the notification document and then checking in the cloud function if the push notification should be send or not. I had clearly not thought of this before..
    • Lorence Cramwinckel
      Lorence Cramwinckel over 4 years
      I was able to get it working so thank you very much for helping!