3

I have push notifications set up for my app using Firebase Cloud Functions. It works well. Now I want to update the app's badge count as part of the push notification. I've read that the only way to do that is via server-side code; I can't do it locally.

So I'm trying to get the number of new users from the server and then use that number as the badge count when I send the push notification, but I can't figure out how to go about it. I've spent three days on this and now I'm hoping someone can point me in the right direction.

I'm using Firebase functions and Typescript (with VSCode). My course of action is to:

  1. get list of userIDs from 'admin' node
  2. iterate over those userIDs on 'user' node to query if user's 'newUser' parameter is true
  3. append those results to an array
  4. count the array and then send that to the badge on push notification

My 'users' database structure is like so:

"users": {

  "2NBvNgdNRVe3nccTEDts2Xseboma": {

    "email": "someone@someone.com"

    "newUser": "true",

    "referral": "none",

    ...

  },

  "hjC6os6wzIV1FyULmGxalU3fM7ef": {

    "email": "someoneElse@someone.com"

    "newUser": "false",

    "referral": "Bennett",

    ...

  }

And my 'admin' database is structured like so:

"admin": {

  "2NBvNgdNRVe3nccTEDts2Xseboma": {

    "email": "someone@someone.com"

    "familyName": "Someone",

    "memberSince": "1529119893",

  },

  "hjC6os6wzIV1FyULmGxalU3fM7ef": {

    "email": "someoneElse@someone.com"

    "familyName": "Someone Else",

    "memberSince": "1529125722",

    ...

  }

Here is my feeble attempt to code this:

exports.getNewUserCount =

functions.database.ref('/users/{userID}/newUser')

    .onUpdate((snapshot, _context) => {

        console.log('test 2')

        // Get a database reference

        const db = admin.database();
        const ref = db.ref('admin');


        return ref.once('value', function(adminSnap) {

            const userData = adminSnap.val()

            console.log('admin key:', adminSnap.key)
            console.log('user data:', userData)

        })

    });

Right now I'm stuck on retrieving the list of users from the admin node (my step #1 above).

UPDATE

I finally got a list of the users as a snapshot, but I can't figure out how to iterate over them. How do I turn the snapshot into an array of the user keys?

And then once I get the list of user keys, then how do I use that to iterate over the 'users' node to get the list of new users (my step #2 above)?

And then how to put those new users into an array (my step #3 above), and then get the number of new users for the 'badge' parameter when I send my push notification (my step #4 above)?

The problem is that this seems really inefficient. There has to be a better way to simply get a list of new users. There has to be some sort of query I can perform that will go over my 'users' node, see which ones have 'true' for their 'newUser' node, and get a count of those--instead of my roundabout way of getting a list of user from 'admin' node, then using that list to get a list of 'new users' from the 'users' node, then creating an array and then counting that array, then using that number to send to the 'badge' parameter on my push notification.

Any thoughts? I've been at this for days.

If it helps, I know Swift and the app is iOS. Thanks!!

UPDATE #2

So I opted to try and just get a snapshot of all users and bypass the 'admin' node altogether. Here is the code:

const db = admin.database();
const ref = db.ref('users');

return ref.once('value').then((adminSnap) => {

    console.log('admin key:', adminSnap.key)

    // create blank array to store 
    let newUserCount = 0;

    // iterate over adminSnap to get each individual snap
    adminSnap.forEach(function (userSnap) {

        const userData = userSnap.val();
        const userKey = userSnap.key

        // console.log('email?', userData.email, 'user key:', userKey, 'new user?', userData.newUser)

        if (userData.newUser === true) {
            newUserCount++
            console.log('new user:', userKey, userData.newUser, userData.email)
        }
    });

    console.log(newUserCount)
})

This new code works and gives me the number for my badge parameter for when I perform my push notification, but I'm wondering if it's the most efficient way to do things. Plus, as my database grows in size, won't it tax the server / slow way down? And won't it cost me a lot of bandwidth for my Firebase account?

I thought this would be a simple thing to do, but it's turning into a bit of a hassle. I'm open to a different way to complete this. Thanks!

Phontaine Judd
  • 308
  • 5
  • 14

1 Answers1

1

After even more research, I ended up abandoning my original approach. I decided to just create a new node on my Firebase database with the new user count and then update it via code from elsewhere. It's the simplest approach and will use the least amount of bandwidth.

Here is my final code:

function sendAlertToiPhone() {

console.log('test E')

// Get a database reference
const db = admin.database();
const ref = db.ref('stats');

ref.child('newUserCount').once('value').then((snapshot) => {

    const newUserCount = snapshot.val()

    console.log('new user count:', newUserCount)

    // send to Phontaine's iPhone 6
    const FCMToken = "blahbehtyblahblah"

    const payload = {
        notification: {
            title: 'New User',
            body: 'Moneypants has a new download.',
            sound: 'default',
            badge: String(newUserCount)
        }
    };

    return admin.messaging().sendToDevice(FCMToken, payload)
        .then(function (response) {
            console.log("Successfully sent message:", response);
        })
        .catch(function (error) {
            console.log("Error sending message:", error);
        });

}).catch(function (err) {
    console.log('new user count error:', err);
})
}
Phontaine Judd
  • 308
  • 5
  • 14