22

Is there any way to send Upstream notification message through FCM from one android device to another devices connected with Firebase database.

I know that XMPP server can then receive the upstream messages and send the notifications to the other devices.To receive messages sent with the upstream API i need to implement an XMPP server but there is any other way???

Vishal Patoliya ツ
  • 3,170
  • 4
  • 24
  • 45
  • 6
    The approach your answer takes of embedding a server key in the app is dangerous and not recommended for anything that you will send to an actual app/play store. – Frank van Puffelen Jul 18 '16 at 19:48
  • 4
    The proper way to send device-to-device notifications with Firebase Cloud Messaging requires the use of an app server. This is not nearly as difficult as it may initially sound, which is why I documented it in this Firebase blog post [Sending notifications between Android devices with Firebase Database and Cloud Messaging](https://firebase.googleblog.com/2016/08/sending-notifications-between-android.html). – Frank van Puffelen Aug 31 '16 at 14:28
  • At least we can use Firebase per se, however we can avoid using the second server apart from Firebase. https://stackoverflow.com/a/67974553/1065226 – Liker777 Jun 14 '21 at 17:22

3 Answers3

16

Is there any way to send Upstream notification message through FCM from one android device to another devices connected with Firebase database?

Currently it's NOT possible to send messages directly from one device to another.
(or at least it's not possible without introducing a HUGE security vulnerability: more details below)

Full details:

  1. Sending messages to a user device is a pretty serious action!
    based on the payload a message can result in spam, phishing, execution of internal methods.
  2. You want this operation to be allowed only be trusted entities, this is why the FCM send API requires the SERVER-API-KEY in the authentication header.
  3. Adding the SERVER-API-KEY in your app code (or communicating it to the app in some other way) IS NOT SAFE. This because apk can be extracted, decompiled, inspected, executed on emulators, executed under debugging and so on.

The best way to implement this today: is to have some sort of server between the two devices:

[DeviceA] -- please send message to B -->  [SERVER] -- fcmSendAPI --> [DeviceB]

The server can be as simple as a PHP page, or a more complex XMPP implementation.

An example in Node.js can be found here:
Sending notifications between devices with Firebase Database and Cloud Messaging

Diego Giorgini
  • 12,489
  • 1
  • 47
  • 50
  • Give me any written text where your answer is defined here This is can not be possible to pk can be extracted, decompiled, inspected, executed on emulators, executed under debugging and so on due to gradle rules in now a days !! – Vishal Patoliya ツ Sep 02 '16 at 06:48
  • There is now also an [example using Cloud Functions for Firebase](https://firebase.google.com/docs/functions/use-cases#notify_users_when_something_interesting_happens), which can also fill the role of the trusted environment needed to securely send messages. – Frank van Puffelen Jul 12 '17 at 15:35
3

Finally, after 2 months of trying to maintain reliable server script myself, I suddenly found OneSignal. It's completely free, supports device-to-device push messages on iOS, Android, WP and browsers.

Hope, I won't get flag for promotion spam, but it's currently the only (and easiest) way to be completely "backendless".

Also, it's completely secure way. Nobody can send push unless he knows special OS user id, which you can store in Firebase Database protected by rules.

UPD: It's not a replacement for Firebase. It has only push service and nothing else

UPD2: Firebase now has Functions, and examples of it usage has sending FCM. You now don't need any other server or service. Read more in official samples https://github.com/firebase/functions-samples

Dmytro Rostopira
  • 10,588
  • 4
  • 64
  • 86
1

After lots of try finally i got one solution and its work perfectly

Step 1 :Include two library.

compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.google.firebase:firebase-messaging:9.2.0'

Step 2 : In your MainActivity or from where you want to send notifications.

OkHttpClient mClient = new OkHttpClient();

String refreshedToken = "";//add your user refresh tokens who are logged in with firebase.

JSONArray jsonArray = new JSONArray();
jsonArray.put(refreshedToken);

Step 3: Create one async task which sends notifications to all devices.

public void sendMessage(final JSONArray recipients, final String title, final String body, final String icon, final String message) {

        new AsyncTask<String, String, String>() {
            @Override
            protected String doInBackground(String... params) {
                try {
                    JSONObject root = new JSONObject();
                    JSONObject notification = new JSONObject();
                    notification.put("body", body);
                    notification.put("title", title);
                    notification.put("icon", icon);

                    JSONObject data = new JSONObject();
                    data.put("message", message);
                    root.put("notification", notification);
                    root.put("data", data);
                    root.put("registration_ids", recipients);

                    String result = postToFCM(root.toString());
                    Log.d("Main Activity", "Result: " + result);
                    return result;
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onPostExecute(String result) {
                try {
                    JSONObject resultJson = new JSONObject(result);
                    int success, failure;
                    success = resultJson.getInt("success");
                    failure = resultJson.getInt("failure");
                    Toast.makeText(MainActivity.this, "Message Success: " + success + "Message Failed: " + failure, Toast.LENGTH_LONG).show();
                } catch (JSONException e) {
                    e.printStackTrace();
                    Toast.makeText(MainActivity.this, "Message Failed, Unknown error occurred.", Toast.LENGTH_LONG).show();
                }
            }
        }.execute();
    }

String postToFCM(String bodyString) throws IOException {



   public static final String FCM_MESSAGE_URL = "https://fcm.googleapis.com/fcm/send";
      final MediaType JSON
                = MediaType.parse("application/json; charset=utf-8");

        RequestBody body = RequestBody.create(JSON, bodyString);
        Request request = new Request.Builder()
                .url(Url.FCM_MESSAGE_URL)
                .post(body)
                .addHeader("Authorization", "key=" + "your server key")
                .build();
        Response response = mClient.newCall(request).execute();
        return response.body().string();
    }

Step 4 : Call in onclick of your button

    btnSend.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            sendMessage(jsonArray,"Hello","How r u","Http:\\google.com","My Name is Vishal");
        }
    });
Vishal Patoliya ツ
  • 3,170
  • 4
  • 24
  • 45
  • 15
    *firebaser here* This puts your FCM server key into the APK, where malicious users can find it and use it to send message on your behalf. This is a very bad idea and I strongly recommend against it. As one of the FCM engineers said in [this answer](http://stackoverflow.com/a/37634914/209103): sending device-to-device messages requires that you run a trusted process on a server at the moment. – Frank van Puffelen Jul 18 '16 at 14:41
  • 1
    very very thanks for warn me @FrankvanPuffelen to remind me for server key which i have not seen at that!!! This was my mistake!! – Vishal Patoliya ツ Jul 18 '16 at 17:15
  • Could you please help me, i have the same issue, i need sent direct message from one user to another... But according your answer i am didn't understand which way you connect to firebase DB? As far as i understand you combine `json` in `doInBackground()` and then send it to your server, and what next? How firebase DB will know that you sent message? and from other side, how recipent will recive message ? – Sirop4ik Aug 30 '16 at 13:12
  • @AlekseyTimoshchenko for send user to user notification you have must data of that user with his device refresh token when user is logged in – Vishal Patoliya ツ Aug 31 '16 at 08:28
  • @AlekseyTimoshchenko String refreshedToken = "" in this you can store your refresh token and make all refresh token of user and send notification to that all users which have login with refresh token. – Vishal Patoliya ツ Aug 31 '16 at 08:34
  • @FrankvanPuffelen is it okay to use this technique if the FCM server key is retrieved from the firebase database? (rather than it being in the APK) – Pat Myron Jan 25 '17 at 21:48
  • 1
    No, that inherently still has the same problem. I just answered a question that here: http://stackoverflow.com/questions/41853694/firebase-messaging-without-server-xmpp-server-proposal/41853937#41853937 – Frank van Puffelen Jan 26 '17 at 09:09
  • @FrankvanPuffelen why this is not proper answer explain me if i'm going to wrong direction. – Vishal Patoliya ツ Jan 26 '17 at 09:28
  • @VishalPatoliyaツ is it possible to open certain activity when user clicks on the notification e.g. currently it opens the main activity but I want to open a different one? Also can I pass some intent, thanks. – Adam Jan 30 '17 at 21:58
  • there are two type of notification in FCM 1. When app in foreground. 2. When app is in background. for background you need server side implementation if you want to get data from it @Adam – Vishal Patoliya ツ Jan 31 '17 at 10:04
  • So it can't be achieved with the approach you defined above? – Adam Jan 31 '17 at 12:15
  • try your self @Adam – Vishal Patoliya ツ Feb 01 '17 at 05:16
  • 2
    I been trying :) watched so many tutorials but I can't figure out how I can put the code together. – Adam Feb 01 '17 at 08:39