17

I am thinking about keeping all registration ids(push token) in DB and sending notifications to user from iPhone. I tried something like this but did not get any notification.

func sendPNMessage() {
    FIRMessaging.messaging().sendMessage(
        ["body": "hey"], 
        to: TOKEN_ID, 
        withMessageID: "1", 
        timeToLive: 108)  
 } 

What I am doing wrong or maybe it is impossible at all?

Svitlana
  • 2,938
  • 1
  • 29
  • 38
  • I have here question with the same concept : https://stackoverflow.com/questions/62902631/send-notification-from-device-to-another-with-firebase-in-android – Bhaa Rizik Jul 14 '20 at 19:30

6 Answers6

19

Currently it's not possible to send messages from the application itself. You can send messages from the Firebase Web Console, or from a custom server using the server-side APIs.

What you might want to do is to contact a server (like via http call) and that server will send the message to the user. This way ensure that the API-KEY of the server is protected.

PS: the sendMessage(..) api is called upstream feature, and can be used to send messages from your app to your server, if you server has an XMPP connection with the FCM server.

Diego Giorgini
  • 12,489
  • 1
  • 47
  • 50
7

Yes you can send push notification through Firebase.Please make sure do NOT include the server-key into your client. There are ways "for not so great people" to find it and do stuff... The Proper way to achieve that is for your client to instruct your app-server to send the notification.

You have to send a HTTP-Post to the Google-API-Endpoint.

You need the following headers:

Content-Type: application/json
Authorization: key={your_server_key}
You can obtain your server key within in the Firebase-Project.

HTTP-Post-Content: Sample

{ 
    "notification": {
        "title": "Notification Title",
        "text": "The Text of the notification."
    },
    "project_id": "<your firebase-project-id",
    "to":"the specific client-device-id"
}
Dupinder kaur
  • 188
  • 2
  • 12
  • You say yes, others say no.... including people that work for firebase... so what is the correct answer? – Nerdy Bunz Feb 14 '17 at 20:51
  • They are technically both correct. This answer is one that works, but shouldn't be done because you're exposing your server key to the world – Mbrevda Apr 28 '17 at 13:51
  • Hey @Dupinderkaur can you show me how to do that in swift code? I have done something like that but i get error code 401. Means request is not authorized. – Salman Ali Jul 10 '17 at 09:16
4

Google Cloud Functions make it now possible send push notifications from device-to-device without an app server.

From the Google Cloud Functions documentation:

Developers can use Cloud Functions to keep users engaged and up to date with relevant information about an app. Consider, for example, an app that allows users to follow one another's activities in the app. In such an app, a function triggered by Realtime Database writes to store new followers could create Firebase Cloud Messaging (FCM) notifications to let the appropriate users know that they have gained new followers.

Example:

  1. The function triggers on writes to the Realtime Database path where followers are stored.

  2. The function composes a message to send via FCM.

  3. FCM sends the notification message to the user's device.

Here is a demo project for sending device-to-device push notifications with Firebase and Google Cloud Functions.

Crashalot
  • 33,605
  • 61
  • 269
  • 439
1

Diego's answer is very accurate but there's also cloud functions from firebase it's very convenient to send notifications in every change in the db. For example let's say you're building chat application and sending notification in every new follower change. This function sample is very good example.

For more information about cloud functions you can check official docs.

mert
  • 1,090
  • 13
  • 26
0

I have an app that has a "send feedback to developer" section. I also have a User collection in my firestore database. When a user logs into the app, I have that Users data update their FCM token with the following code in my SceneDelegate.swift:

import Firebase

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

  authListener = Auth.auth().addStateDidChangeListener({ (auth, user) in
                
    Auth.auth().removeStateDidChangeListener(self.authListener!)
    if user != nil {
       DispatchQueue.main.async {
         let docRef = Firestore.firestore().collection("User").document((user?.email)!)
         docRef.getDocument { (snapshot, error) in
            guard let snapshot = snapshot else {return}
            Messaging.messaging().token { token, error in
              if let error = error {
                 print("Error fetching FCM registration token: \(error)")
              } else if let token = token {
                 docRef.updateData(["FCMtoken":token])
                 print("FCM registration token: \(token)")
              }
            }
          }
        }
      }
    })
  guard let _ = (scene as? UIWindowScene) else { return }
}

then in my feedback view controller i have this code to send my specific device (but you can look up/fetch which specific device you want in your database where the FCMtoken is stored where i have INSERT-DEVICE-TOKEN-HERE). The url to send to is "https://fcm.googleapis.com/fcm/send" and you can find YOUR-APP-FCM-KEY by going to your project settings in firebase, going to cloud messaging tab and its the server key.

func sendMePushNotification() {
  let token = "INSERT-DEVICE-TOKEN-HERE"
  if let url = URL(string: "https://fcm.googleapis.com/fcm/send") {
    var request = URLRequest(url: url)
    request.allHTTPHeaderFields = ["Content-Type":"application/json", "Authorization":"key=YOUR-APP-FCM-KEY"]
    request.httpMethod = "POST"
    request.httpBody = "{\"to\":\"\(token)\",\"notification\":{\"title\":\"Feedback Sent!\",\"body\":\"\(self.feedbackBox.text!)\",\"sound\":\"default\",\"badge\":\"1\"},\"data\": {\"customDataKey\": \"customDataValue\"}}".data(using: .utf8)
    URLSession.shared.dataTask(with: request) { (data, urlresponse, error) in
      if error != nil {
         print("error")
      } else {
         print("Successfully sent!.....")
      }
    }.resume()
  }
}
-1

Use onesignal,you can send device to notifications or device to segments ,it can work with firebase in this way Use onesignal functions to create a specific id,save it in a firebase database ,then when the id can be put in another function that is used to send a notification Notes: 1-i am using it in my apps with firebase works perfectly 2-i can submit that code,just someone comments so i can find this answer

Abdull
  • 53
  • 1
  • 8