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:20

1) subscribe an identical topic name, for example:

  • ClientA.subcribe("to/topic_users_channel")
  • ClientB.subcribe("to/topic_users_channel")

2) send messages inside the application

GoogleFirebase : How-to send topic messages

查看更多
旧时光的记忆
3楼-- · 2018-12-31 08:24

Yes, it's possible to do it without any server. You can create a device group client side and then you exchange messages in the group. However there are limitations:

  1. You have to use the same Google account on the devices
  2. You can't send high priority messages

Reference: Firebase doc See the section "Managing device groups on Android client apps"

查看更多
忆尘夕之涩
4楼-- · 2018-12-31 08:25

If you have fcm(gcm) token of the device to whom you want to send notification. It's just a post request to send the notification.

https://github.com/prashanthd/google-services/blob/master/android/gcm/gcmsender/src/main/java/gcm/play/android/samples/com/gcmsender/GcmSender.java

查看更多
心情的温度
5楼-- · 2018-12-31 08:33

You can use Retrofit. Subscribe devices to topic news. Send notification from one device to other.

public void onClick(View view) {

    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=legacy server key from FB console"); // <-- 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("Notification title","Notification body");

Call<Message> call2 = firebaseAPI.sendMessage(new Message("topic or deviceID", notifydata));

    call2.enqueue(new Callback<Message>() {
        @Override
        public void onResponse(Call<Message> call, Response<Message> response) {

            Log.d("Response ", "onResponse");
            t1.setText("Notification sent");

        }

        @Override
        public void onFailure(Call<Message> call, Throwable t) {
            Log.d("Response ", "onFailure");
            t1.setText("Notification failure");
        }
    });
}

POJOs

public class Message {
String to;
NotifyData notification;

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

}

and

public class NotifyData {
String title;
String body;

public NotifyData(String title, String body ) {

    this.title = title;
    this.body = body;
}

}

and FirebaseAPI

public interface FirebaseAPI {

@POST("/fcm/send")
Call<Message> sendMessage(@Body Message message);

}
查看更多
与风俱净
6楼-- · 2018-12-31 08:35

UPDATE: It is now possible to use firebase cloud functions as the server for handling push notifications. Check out their documentation here

============

According to the docs you must implement a server for handling push notifications in device to device communication.

Before you can write client apps that use Firebase Cloud Messaging, you must have an app server that meets the following criteria:

...

You'll need to decide which FCM connection server protocol(s) you want to use to enable your app server to interact with FCM connection servers. Note that if you want to use upstream messaging from your client applications, you must use XMPP. For a more detailed discussion of this, see Choosing an FCM Connection Server Protocol.

If you only need to send basic notifications to your users from the server. You can use their serverless solution, Firebase Notifications.

See a comparison here between FCM and Firebase Notifications: https://firebase.google.com/support/faq/#messaging-difference

查看更多
荒废的爱情
7楼-- · 2018-12-31 08:36

I figured out like this:-
Making a HTTP POST request with the link "https://fcm.googleapis.com/fcm/send" with required header and data referenced HERE.
Constants.LEGACY_SERVER_KEY is a local class variable, you can find this at your Firebase Project Settings-->CLOUD MESSAGING-->Legacy Server key. You need to pass device registration token(reg_token) in below code snippet referenced HERE.
However you need okhttp library dependency in order to get this snippet work.

public static final MediaType JSON
        = MediaType.parse("application/json; charset=utf-8");
private void sendNotification(final String regToken) {
    new AsyncTask<Void,Void,Void>(){
        @Override
        protected Void doInBackground(Void... params) {
            try {
                OkHttpClient client = new OkHttpClient();
                JSONObject json=new JSONObject();
                JSONObject dataJson=new JSONObject();
                dataJson.put("body","Hi this is sent from device to device");
                dataJson.put("title","dummy title");
                json.put("notification",dataJson);
                json.put("to",regToken);
                RequestBody body = RequestBody.create(JSON, json.toString());
                Request request = new Request.Builder()
                        .header("Authorization","key="+Constants.LEGACY_SERVER_KEY)
                        .url("https://fcm.googleapis.com/fcm/send")
                        .post(body)
                        .build();
                Response response = client.newCall(request).execute();
                String finalResponse = response.body().string();
            }catch (Exception e){
                //Log.d(TAG,e+"");
            }
            return null;
        }
    }.execute();

}

further if you want to send message to a particular topic, replace 'regToken' in json like this

json.put("to","/topics/foo-bar")

and at last don't forget to add INTERNET permission in your AndroidManifest.xml.

IMPORTANT : - Using above code means your server key resides in the client application. That is dangerous as someone can dig into your application and get the server key to send malicious notifications to your users.

查看更多
登录 后发表回答