How to send device to device messages using Fireba

2018-12-31 08:10发布

After searching the docs I could not find any info on how to send device to device messages using FCM without the use of an external server.

For example, if I was creating a chat application I would need to send push notifications to users about unread messages since they won't be online all the time and I can't have a persistent service in the background that would always be connected to the real time database because that would be too resource heavy.

So how would I send a push notification to a user "A" when a certain user "B" sends him/her a chat message? Do I need an external server for this or can it be done with just Firebase servers?

13条回答
荒废的爱情
2楼-- · 2018-12-31 08:12

You can do it using Volly Jsonobject request....

follow this Steps first:

1 copy legacy server key and store it as Legacy_SERVER_KEY

Legacy Server key

you can see in picture how to get

2 You need Volley dependency

compile 'com.mcxiaoke.volley:library:1.0.19'

enter image description here

Code for send Push:-

    private void sendFCMPush() {

            String Legacy_SERVER_KEY = YOUR_Legacy_SERVER_KEY;
            String msg = "this is test message,.,,.,.";
            String title = "my title";
            String token = FCM_RECEIVER_TOKEN;

            JSONObject obj = null;
        JSONObject objData = null;
        JSONObject dataobjData = null;

        try {
            obj = new JSONObject();
            objData = new JSONObject();

            objData.put("body", msg);
            objData.put("title", title);
            objData.put("sound", "default");
            objData.put("icon", "icon_name"); //   icon_name image must be there in drawable
            objData.put("tag", token);
            objData.put("priority", "high");

            dataobjData = new JSONObject();
            dataobjData.put("text", msg);
            dataobjData.put("title", title);

            obj.put("to", token);
            //obj.put("priority", "high");

            obj.put("notification", objData);
            obj.put("data", dataobjData);
            Log.e("!_@rj@_@@_PASS:>", obj.toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }

            JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, Constants.FCM_PUSH_URL, obj,
                    new Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject response) {
                            Log.e("!_@@_SUCESS", response + "");
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            Log.e("!_@@_Errors--", error + "");
                        }
                    }) {
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> params = new HashMap<String, String>();
                    params.put("Authorization", "key=" + Legacy_SERVER_KEY);
                    params.put("Content-Type", "application/json");
                    return params;
                }
            };
            RequestQueue requestQueue = Volley.newRequestQueue(this);
            int socketTimeout = 1000 * 60;// 60 seconds
            RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
            jsObjRequest.setRetryPolicy(policy);
            requestQueue.add(jsObjRequest);
}

Just Call sendFCMPush();

查看更多
还给你的自由
3楼-- · 2018-12-31 08:14

Simplest way :

void sendFCMPush(String msg,String token) {
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    httpClient.addInterceptor(new Interceptor() {
        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            Request original = chain.request();

            // Request customization: add request headers
            Request.Builder requestBuilder = original.newBuilder()
                    .header("Authorization", "key="+Const.FIREBASE_LEGACY_SERVER_KEY); // <-- this is the important line
            Request request = requestBuilder.build();
            return chain.proceed(request);
        }
    });

    httpClient.addInterceptor(logging);
    OkHttpClient client = httpClient.build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://fcm.googleapis.com/")//url of FCM message server
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())//use for convert JSON file into object
            .build();

    // prepare call in Retrofit 2.0
    FirebaseAPI firebaseAPI = retrofit.create(FirebaseAPI.class);

    //for messaging server
    NotifyData notifydata = new NotifyData("Chatting", msg);

    Call<Message> call2 = firebaseAPI.sendMessage(new Message(token, notifydata));

    call2.enqueue(new Callback<Message>() {
        @Override
        public void onResponse(Call<Message> call, retrofit2.Response<Message> response) {
            Log.e("#@ SUCCES #E$#", response.body().toString());
        }

        @Override
        public void onFailure(Call<Message> call, Throwable t) {

            Log.e("E$ FAILURE E$#", t.getMessage());
        }
    });
}

Create Class to make Object:

public class Message {
String to;
NotifyData data;

public Message(String to, NotifyData data) {
    this.to = to;
    this.data = data;
}
}

Create Class to make Object:

public class Notification {
String title;
String message;
enter code here`enter code here`
public Notification(String title, String message) {
    this.title = title;
    this.message = message;
}
}
查看更多
梦醉为红颜
4楼-- · 2018-12-31 08:15

In my case I use retrofit with this class Message:

public class Message {

    private String to;
    private String collapseKey;
    private Notification notification;
    private Data data;

    public Message(String to, String collapseKey, Notification notification, Data data) {
        this.to = to;
        this.collapseKey = collapseKey;
        this.notification = notification;
        this.data = data;
    }

Data

public class Data {

    private String body;
    private String title;
    private String key1;
    private String key2;

    public Data(String body, String title, String key1, String key2) {
        this.body = body;
        this.title = title;
        this.key1 = key1;
        this.key2 = key2;
    }
}

Notification

public class Notification {

    private String body;
    private String title;

    public Notification(String body, String title) {
        this.body = body;
        this.title = title;
    }
}

this the call

private void sentToNotification() {


            String to = "YOUR_TOKEN";
            String collapseKey = "";
            Notification notification = new Notification("Hello bro", "title23");
            Data data = new Data("Hello2", "title2", "key1", "key2");
            Message notificationTask = new Message(to, collapseKey, notification, data);

            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("https://fcm.googleapis.com/")//url of FCM message server
                    .addConverterFactory(GsonConverterFactory.create())//use for convert JSON file into object
                    .build();

            ServiceAPI api = new retrofit.create(ServiceAPI.class);

            Call<Message> call = api .sendMessage("key=YOUR_KEY", notificationTask);

            call.enqueue(new Callback<Message>() {
                @Override
                public void onResponse(Call<Message> call, retrofit2.Response<Message> response) {
                    Log.d("TAG", response.body().toString());
                }

                @Override
                public void onFailure(Call<Message> call, Throwable t) {

                    Log.e("TAG", t.getMessage());
                }
            });
        }

our ServiceAPi

public interface ServiceAPI {
    @POST("/fcm/send")
    Call<Message> sendMessage(@Header("Authorization") String token, @Body Message message);
}
查看更多
妖精总统
5楼-- · 2018-12-31 08:18

Google Cloud Functions make it now possible send push notifications from device-to-device without an app server. I have made cloud function which is trigger when new message is added in database

It is node.js code

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin'); admin.initializeApp();

exports.sendNotification = functions.database.ref('/conversations/{chatLocation}/{messageLocation}')
  .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();

       const toIDUser = original.toID;
       const isGroupChat = original.isGroupChat;

       if (isGroupChat) {
       const tokenss =  admin.database().ref(`/users/${toIDUser}/tokens`).once('value').then(function(snapshot) {

// Handle Promise
       const tokenOfGroup = snapshot.val()

      // get tokens from the database  at particular location get values 
       const valuess = Object.keys(tokenOfGroup).map(k => tokenOfGroup[k]);

     //console.log(' ____________ffffd((999999ffffd_________________ ' +  valuess );
    const payload = {
       notification: {
                 title:   original.senderName + " :- ",
                 body:    original.content
    }
  };

  return admin.messaging().sendToDevice(valuess, payload);



}, function(error) {

  console.error(error);
});

       return ;
          } else {
          // get token from the database  at particular location
                const tokenss =  admin.database().ref(`/users/${toIDUser}/credentials`).once('value').then(function(snapshot) {
                // Handle Promise
  // The Promise was "fulfilled" (it succeeded).

     const credentials = snapshot.val()



    // console.log('snapshot ......snapshot.val().name****^^^^^^^^^^^^kensPromise****** :- ', credentials.name);
     //console.log('snapshot.....****snapshot.val().token****^^^^^^^^^^^^kensPromise****** :- ', credentials.token);


     const deviceToken = credentials.token;

    const payload = {
       notification: {
                 title:   original.senderName + " :- ",
                 body:    original.content
    }
  };

  return admin.messaging().sendToDevice(deviceToken, payload);


}, function(error) {

  console.error(error);
});


          }





  return ;


    });
查看更多
人间绝色
6楼-- · 2018-12-31 08:19

You can use firebase realtime database to do so. You can create data structure for storing chats and add observers for the conversation threads for both users. It still does device - server - device architecture, but in this case there is no additional server on the developers' part. This uses the firebase servers. You can check out a tutorial here (ignore the UI part, although, that is also a good starting point for chat UI frameworks).

Firebase Realtime Chat

查看更多
零度萤火
7楼-- · 2018-12-31 08:19

So I had an idea here. See: If the FCM, as well as the GCM, has a endpoit to http request where we can send a post json with our message data, including the token (s) of devices that we want this message to be delivered.

So why not send a post to Firebase server with this notification to be delivered to user B? you understand ?

So, you send the message and chat with a call post to ensure delivery of the notification if the user is with your app in the background. I am also in need of it soon, I will test later. What do you say about?

查看更多
登录 后发表回答