Firebase 云功能发送带有地理位置的推送通知

Firebase cloud function sending push notifications with geo location

我目前有一个连接了 firebase 实时数据库的 React-Native 应用程序。用户可以选择上传数据并通过推送通知通知附近的用户。用户位置与推送消息的 Firebase 令牌一起保存在数据库中。

创建了一个云函数来查找 pushUsed 值。如果这是真的,它将收集令牌并发送消息。现在它向每个用户发送一条消息,我可以重写云函数来检查用户是否在附近吗?

这是创建 tokenArray 的部分。我希望做类似的事情; 如果用户坐标在 xx 英里范围内,则将标记添加到数组中。否则忽略。

const tokenArray = []

  const getDeviceTokensPromise = await admin.database()
  .ref("/UserFCMToken/").once('value', (snapShot) => {

          snapShot.forEach((childSnapshot) => {
            tokenArray.push(childSnapshot.val().FCMToken)
          })
        });

        console.log(tokenArray)
      const response = await admin.messaging().sendToDevice(tokenArray, payload);

谁能帮我解决这个问题?我对 GPS 位置不够熟悉,无法使其正常工作。

这很有趣。我能想到以下几点:

  • 创建另一个函数来定期获取所有用户的位置。这可以通过像 geolocation or location 这样的 React native 库来完成。将您的功能设置为每 5 或 10 分钟更新一次用户的位置。

  • 一旦你运行你的原始功能你得到这个用户的位置并且只需添加逻辑来比较是否有另一个用户在附近进行查询。查询将 运行 在最近保存的位置上,这应该是最近的。

有趣的是,这些库的结果在 latitudelongitude 上返回,因此您还需要了解 How to calculate distance in miles from longitue and latitude.

希望对您有所帮助! :)

所以我使用 geofire-js 获得了地理位置通知!

        saveLocationHandler = async() => {
        let uid = await AsyncStorage.getItem("ta:auth:userId");
        let userLocationAsync = await AsyncStorage.getItem("ta:auth:userLocation");
        const transformedData = JSON.parse(userLocationAsync);
        const { userLocation } = transformedData;
        const firebaseRef = Firebase.database().ref('Geolocations')
        const geoFire = new GeoFire(firebaseRef)
        const ref = geoFire.ref()
    if (uid || userLocation) {
        geoFire.set(uid, [userLocation.lat, userLocation.lng]); 
        } 
    else {
        console.log('GeoFire UserID en/of userLocation are not known')
        return
    }
}

使用此功能,用户位置将使用用户 ID 和 GPS 位置存储在 de Firebase 数据库中。 在 Firebase 的另一个条目中,我有:

_FCMTokens __UserID ___FCMToken(用于发送推送通知)

然后我更改了我的云功能,首先检查哪些用户在附近使用 Geofire。

  const tokenArray = []
  const geofireQuery = new GeoFire(admin.database().ref('Geolocations')).query({
    center: [event._data.location[0].lat, event._data.location[0].lng],
    radius: event._data.selectedRange
  })
  .on('key_entered', async (key) => {
    // Geofire only provides an index to query.
    // We'll need to fetch the original object as well
    const getDeviceTokensPromise = await admin.database()
    .ref('/UserFCMToken/'+ key ).once('value', (snapShot) => {

      snapShot.forEach((childSnapshot) => {
        tokenArray.push(childSnapshot.val().FCMToken)
                })
          })
    });

      const response = await admin.messaging().sendToDevice(tokenArray, payload);

Geofire 查询 returns 所选范围内的每个用户 ID(这是 Firebase 数据库中可用的条目)。在使用密钥触发的 key_entered 上,为每个用户获取了 FCMToken。密钥由 Geofire 提供,在我的例子中是用户 ID。