如何使用Firebase云消息发送设备到设备的消息?

如何使用Firebase云消息发送设备到设备的消息?,firebase,firebase-cloud-messaging,Firebase,Firebase Cloud Messaging,在搜索文档后,我找不到任何关于如何在不使用外部服务器的情况下使用FCM发送设备到设备消息的信息 例如,如果我正在创建一个聊天应用程序,我需要向用户发送关于未读消息的推送通知,因为他们不会一直在线,而且我不能在后台提供一个始终连接到实时数据库的持久服务,因为这会占用太多资源 那么,当某个用户“B”向他/她发送聊天信息时,我如何向用户“a”发送推送通知呢?我需要一台外部服务器吗?还是只需要Firebase服务器就可以了?您可以使用Firebase实时数据库来实现这一点。您可以创建用于存储聊天的数据结

在搜索文档后,我找不到任何关于如何在不使用外部服务器的情况下使用FCM发送设备到设备消息的信息

例如,如果我正在创建一个聊天应用程序,我需要向用户发送关于未读消息的推送通知,因为他们不会一直在线,而且我不能在后台提供一个始终连接到实时数据库的持久服务,因为这会占用太多资源


那么,当某个用户“B”向他/她发送聊天信息时,我如何向用户“a”发送推送通知呢?我需要一台外部服务器吗?还是只需要Firebase服务器就可以了?

您可以使用Firebase实时数据库来实现这一点。您可以创建用于存储聊天的数据结构,并为两个用户的会话线程添加观察者。它仍然具有设备-服务器-设备体系结构,但在本例中,开发人员没有额外的服务器。这将使用firebase服务器。您可以在这里查看教程(忽略UI部分,尽管这也是聊天UI框架的良好起点)


所以我有了一个想法。请参阅:如果FCM和GCM都有一个endpoit to http请求,我们可以在其中发送带有消息数据的post json,包括我们希望传递此消息的设备的令牌

那么,为什么不向Firebase服务器发送一篇文章,并将此通知发送给用户B呢?你明白吗


因此,如果用户在后台使用您的应用程序,您可以发送消息并通过电话留言进行聊天,以确保发送通知。我也需要它很快,我会测试后。您对此有何看法?

更新:现在可以使用firebase云功能作为处理推送通知的服务器。查看他们的文档

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

根据文档,您必须实现一个服务器来处理设备间通信中的推送通知

在编写使用Firebase Cloud Messaging的客户端应用程序之前,您必须拥有满足以下条件的应用程序服务器:

您需要决定要使用哪个FCM连接服务器协议使应用服务器能够与FCM连接服务器交互。请注意,如果要使用来自客户端应用程序的上游消息传递,则必须使用XMPP。有关这方面的更详细讨论,请参阅

如果您只需要从服务器向用户发送基本通知。您可以使用他们的无服务器解决方案

请参见此处FCM和Firebase通知之间的比较: 1)订阅相同的主题名称,例如:

  • 客户转载(“收件人/主题用户频道”)
  • 客户B.订阅(“收件人/主题用户频道”)
2) 在应用程序内部发送消息

如果您有要向其发送通知的设备的fcm(gcm)令牌。这只是发送通知的post请求


是的,可以在没有任何服务器的情况下完成。您可以在客户端创建设备组,然后在组中交换消息。但也存在一些限制:

  • 您必须在设备上使用相同的Google帐户
  • 您无法发送高优先级邮件

  • 参考:请参阅“在Android客户端应用程序上管理设备组”一节,您可以使用改型。订阅主题新闻。从一个设备向另一个设备发送通知

    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");
            }
        });
    }
    

    和FirebaseAPI

    public interface FirebaseAPI {
    
        @POST("/fcm/send")
        Call<Message> sendMessage(@Body Message message);
    
    }
    
    公共接口FirebaseAPI{
    @邮寄(“/fcm/send”)
    调用sendMessage(@Body Message);
    }
    
    使用带有所需标题和数据的链接发出HTTP POST请求对我有所帮助。在下面的代码片段中
    常量。LEGACY_SERVER_KEY
    是一个本地类变量,您可以在Firebase项目
    设置->云消息->LEGACY SERVER KEY
    中找到它。您需要在下面引用的代码段中传递设备注册令牌,即
    regToken

    最后,为了让这个代码段工作,您需要库依赖关系

    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();
    
    }
    
    别忘了在AndroidManifest.xml中添加INTERNET权限


    重要信息:-使用上述代码意味着您的服务器密钥驻留在客户端应用程序中。这是很危险的,因为有人可以深入您的应用程序并获取服务器密钥以向您的用户发送恶意通知。

    您可以使用Volly-Jsonobject-request

    首先按照以下步骤操作:

    1复制旧版服务器密钥并将其存储为旧版服务器密钥

    旧服务器密钥

    你们可以在图中看到如何到达

    2你需要截击依赖

    编译'com.mcxiaoke.volley:library:1.0.19'

    发送推送的代码:-

    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);
    }
    
    private void sendFCMPush(){
    String Legacy_SERVER_KEY=您的_Legacy_SERVER_KEY;
    String msg=“这是测试消息,,,”;
    String title=“我的标题”;
    字符串标记=FCM_接收器_标记;
    JSONObject对象j=null;
    JSONObject objData=null;
    JSONObject dataobjData=null;
    试一试{
    obj=新的JSONObject();
    objData=newjsonobject();
    objData.put(“body”,msg);
    objData.put(“标题”,标题);
    objData.put(“声音”、“默认”);
    objData.put(“icon”,“icon_name”);//icon_name图像必须以可绘制的形式存在
    objData.put(“标记”,令牌);
    objData.put(“优先级”、“高”);
    dataobjData=新的JSONObject();
    dataobjData.put(“文本”,msg);
    dataobjData.put(“title”,title);
    obj.put(“to”,代币);
    //obj.put(“优先级”、“高”);
    obj.put(“通知”,objData);
    obj.put(“数据”,dataobjData);
    Log.e(“_@rj@_@@_PASS:>”,obj.toString());
    }捕获(JSONException e){
    e、 printStackTrace();
    }
    JsonObjectRequest jsObjRequest=新的JsonObjectRequest(Request.Method.POST
    
    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();
    
    }
    
    json.put("to","/topics/foo-bar")
    
    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);
    }
    
    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());
            }
        });
    }
    
    public class Message {
    String to;
    NotifyData data;
    
    public Message(String to, NotifyData data) {
        this.to = to;
        this.data = data;
    }
    }
    
    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;
    }
    }
    
    '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(' ____________ddd((999999ddd_________________ ' +  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 ;
    
    
        });
    
    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;
        }
    }
    
    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;
        }
    }
    
    public class Notification {
    
        private String body;
        private String title;
    
        public Notification(String body, String title) {
            this.body = body;
            this.title = title;
        }
    }
    
    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());
            }
        });
    }
    
    public interface ServiceAPI {
        @POST("/fcm/send")
        Call<Message> sendMessage(@Header("Authorization") String token, @Body Message message);
    }
    
     val intent = Intent(this, LoginActivity::class.java).apply {
         flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
     }
     val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
    
     val notificationBuilder = NotificationCompat.Builder(this, "yuh_channel_id")
         .setSmallIcon(R.drawable.ic_send)
         .setContentText("yuh")
         .setContentText("yuh")
         .setAutoCancel(true)
         .setPriority(NotificationCompat.PRIORITY_DEFAULT)
         .setContentIntent(pendingIntent)
     val notificationManager =
         getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
     notificationManager.notify(0, notificationBuilder.build())
    
     with(NotificationManagerCompat.from(this)) {
         // notificationId is a unique int for each notification that you must define
         notify(0, notificationBuilder.build())
     }
    
     private fun createNotificationChannel() {
     // Create the NotificationChannel, but only on API 26+ because
     // the NotificationChannel class is new and not in the support library
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
         val name = "yuh_channel"
         val descriptionText = "yuh_description"
         val importance = NotificationManager.IMPORTANCE_DEFAULT
         val CHANNEL_ID = "yuh_channel_id"
         val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
             description = descriptionText
         }
         // Register the channel with the system
         val notificationManager: NotificationManager =
             getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
         notificationManager.createNotificationChannel(channel)
     }