Как отправлять сообщения с устройства на устройство с помощью Firebase Cloud Messaging?

После поиска в документации я не смог найти никакой информации о том, как отправлять сообщения с устройства на устройство с помощью FCM без использования внешнего сервера.

Например, если бы я создавал приложение для чата, мне нужно было бы отправлять push-уведомления пользователям о непрочитанных сообщениях, поскольку они не будут постоянно в сети, и у меня не может быть постоянной службы в фоновом режиме, которая всегда была бы подключена к базу данных в реальном времени, потому что это было бы слишком ресурсоемко.

Итак, как мне отправить push-уведомление пользователю «А», когда определенный пользователь «Б» отправит ему / ей сообщение в чате? Нужен ли мне для этого внешний сервер или это можно сделать только с серверами Firebase?


person Suyash    schedule 25.05.2016    source источник
comment
Я еще не использовал FCM ... но я использовал GCM ... предполагая, что FCM почти как GCM ... устройство A отправляет сообщение на сервер, который отправит сообщение на устройство B. firebase.google.com/support/faq/#messaging-difference   -  person j4rey    schedule 25.05.2016
comment
@ j4rey89 Да, я знаю, что это можно сделать с помощью внешнего сервера. Я спрашиваю, можно ли обойтись без него, поскольку для этого мне потребовалось бы обслуживать и оплачивать два сервера вместо одного.   -  person Suyash    schedule 25.05.2016
comment
@Suyash - обязательно запустить собственный сервер для отправки сообщений FCM между вашими устройствами. Если вас беспокоят затраты на работу сервера, вы можете начать развертывание в Openshift Online (PaaS) или Google AppEngine (PaaS тоже), у которых есть бесплатная квота.   -  person MrBrightside    schedule 25.05.2016
comment
@ j4rey89 MrBrightside: похоже на ответ. :-)   -  person Frank van Puffelen    schedule 25.05.2016
comment
stackoverflow.com/questions/38432243/   -  person Vishal Patoliya ツ    schedule 08.08.2016
comment
@Suyash, вы можете отправлять уведомления с помощью почтового запроса на другое устройство   -  person Jagjit Singh    schedule 12.08.2016
comment
похоже, что вы можете отправить сообщение с устройства на устройство через http-сообщение, не имея собственного сервера, согласно этой документации на firebase: https://firebase.google.com/docs/cloud-messaging/http-server-ref Мне не удалось понять, как отправить запрос на публикацию. кто-нибудь пробовал это? Это кажется слишком хорошим, чтобы быть правдой.   -  person mjpablo23    schedule 29.11.2016
comment
Теперь с помощью Google Cloud Functions можно отправлять сообщения с устройства на устройство. См. Ответ ниже: stackoverflow.com/a/47106374/144088   -  person Crashalot    schedule 04.11.2017


Ответы (14)


ОБНОВЛЕНИЕ: теперь можно использовать облачные функции firebase в качестве сервера для обработки push-уведомлений. Ознакомьтесь с их документацией здесь

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

Согласно документации, вы должны реализовать сервер для обработки push-уведомлений при обмене данными между устройствами.

Прежде чем вы сможете писать клиентские приложения, использующие Firebase Cloud Messaging, у вас должен быть сервер приложений, который соответствует следующим критериям:

...

Вам нужно будет решить, какие протоколы серверов соединений FCM вы хотите использовать, чтобы сервер приложений мог взаимодействовать с серверами соединений FCM. Обратите внимание: если вы хотите использовать восходящий обмен сообщениями из клиентских приложений, вы должны использовать XMPP. Более подробное обсуждение этого вопроса см. В разделе Выбор протокола сервера соединений FCM .

Если вам нужно отправлять пользователям только базовые уведомления с сервера. Вы можете использовать их бессерверное решение, Уведомления Firebase.

См. Сравнение уведомлений FCM и Firebase здесь: https://firebase.google.com/support/faq/#messaging-difference

person eikooc    schedule 25.06.2016
comment
хороший ответ. Знаете ли вы какие-нибудь учебные пособия или видео, в которых объясняется, как это сделать? Спасибо - person Ben Akin; 15.08.2016
comment
См. firebase.googleblog.com/2016/08/ - person Frank van Puffelen; 28.08.2016
comment
Не могли бы вы помочь мне понять, пожалуйста. Насколько я понимаю, если мне нужно отправить прямое сообщение от одного пользователя к другому, я должен использовать HTTP и отправить это сообщение на мой сервер, а следующий сервер будет использовать FCM для отправки уведомления получателю и, таким образом, получатель получит данные с идентификатором отправителя. На следующем шаге получатель подключается к FCM и с помощью идентификатора получает все данные из базы данных FCM? Такой способ? - person Aleksey Timoshchenko; 30.08.2016
comment
Идеальный ответ, я исследовал эти 2 дня. Очень полная информация о FCM и нужна она или нет. Спасибо !. - person Khang Tran; 27.11.2016

Выполнение HTTP-запроса POST со ссылкой https://firebase.google.com/docs/cloud-messaging/send-message с нужным заголовком и данными мне помогли. В приведенном ниже фрагменте кода Constants.LEGACY_SERVER_KEY - это переменная локального класса, вы можете найти ее в своем проекте Firebase Settings->Cloud Messaging->Legacy Server key. Вам необходимо передать токен регистрации устройства, т.е. regToken в приведенном ниже фрагменте кода, на который имеется ссылка ЗДЕСЬ.

Наконец, вам нужна зависимость библиотеки https://github.com/square/okhttp, чтобы этот фрагмент работал.

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();

}

далее, если вы хотите отправить сообщение в определенную тему, замените regToken в json следующим образом

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

и не забудьте добавить разрешение INTERNET в свой AndroidManifest.xml.

ВАЖНО. Использование приведенного выше кода означает, что ваш серверный ключ находится в клиентском приложении. Это опасно, поскольку кто-то может проникнуть в ваше приложение и получить ключ сервера для отправки вредоносных уведомлений вашим пользователям.

person Brijesh Kumar    schedule 01.02.2017
comment
Привет, есть ли возможность отправлять сообщения на определенный канал, на который вы подписаны? - person Suchith; 05.03.2017
comment
Обратной стороной является то, что ваш серверный ключ находится в клиентском приложении. Это опасно, поскольку кто-то может проникнуть в ваше приложение и получить ключ сервера для отправки вредоносных уведомлений вашим пользователям. Вот почему вы никогда не должны этого делать. - person kirtan403; 12.04.2017
comment
@ kirtan403 Сильное шифрование ключа сервера на стороне клиента могло остановить это ??? - person Mr.Popular; 20.04.2017
comment
@ Mr.Popular Может быть, но если кто-то сможет декомпилировать ваш код (конечно, может), тогда он сможет захватить то, что вы используете для шифрования ключа сервера, и получить ключ сервера. И тогда они могут отправлять уведомления кому угодно без каких-либо ограничений .. Так что ставить серверный ключ на стороне клиента - очень плохая идея. Очень-очень плохая идея ... - person kirtan403; 22.04.2017
comment
Привет, друзья, расскажите, пожалуйста, что такое regToken и как я его сгенерировал, а также что такое Constants.LEGACY_SERVER_KEY, пожалуйста, помогите мне в этом - person Qutbuddin Bohra; 04.06.2017
comment
что такое regToken? - person Kaushik Makwana; 19.09.2017
comment
@KaushikMakwana reg_token - это регистрационный токен, который вы можете получить из службы FirebaseInstanceIDS, как указано в firebase. google.com/docs/cloud-messaging/android/client - person Brijesh Kumar; 19.09.2017
comment
Я пробовал, чтобы этот код генерировался, но remoteMessage.getData() имеет значение null (Пусто) Пожалуйста, помогите - person Tabish; 03.05.2018
comment
@Tabish, пожалуйста, используйте remoteMessage.getNotification (). Мы не отправляем сюда данные. - person Brijesh Kumar; 03.05.2018
comment
Спасибо за быстрый ответ, и проблема была решена :) - person Tabish; 03.05.2018
comment
Как установить значок уведомления как URL-адрес, а не рисовать? @brijeshkumar - person Curio; 13.09.2020

Вы можете сделать это с помощью запроса Volly Jsonobject ....

сначала выполните следующие шаги:

1 скопируйте старый ключ сервера и сохраните его как Legacy_SERVER_KEY.

Ключ старого сервера

вы можете увидеть на картинке как получить

2 Вам нужна зависимость от Volley

скомпилировать com.mcxiaoke.volley: library: 1.0.19

введите описание изображения здесь

Код для отправки 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);
}

Просто вызовите sendFCMPush ();

person Rjz Satvara    schedule 25.02.2017
comment
Привет, есть ли возможность отправлять сообщения на определенный канал, на который вы подписаны? - person Suchith; 05.03.2017
comment
да, возможно, вам нужно добавить флаг для этого и зависит от того, что вы можете отправлять Push подписанным пользователям - person Rjz Satvara; 06.03.2017
comment
@RjzSatvara что делать, если приложение не запущено на телефоне получателя? получит ли он сообщение? заранее спасибо - person Jaco; 22.08.2017
comment
@Jaco, возможности нет. вы должны управлять этим другим способом. - person Rjz Satvara; 22.08.2017

1) подпишитесь на тему с таким же названием, например:

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

2) отправлять сообщения внутри приложения

GoogleFirebase: как отправлять тематические сообщения

person Maxim Firsoff    schedule 05.09.2016
comment
Разве для этого не потребуется использовать ключ авторизации на стороне клиента? Что делает его небезопасным. Также я даже не знаю, стоит ли создавать отдельную тему для каждого пользователя. - person Suyash; 06.09.2016
comment
Хорошая идея, но: Тематические сообщения оптимизированы для пропускной способности, а не для задержки. Для быстрой и безопасной доставки на отдельные устройства или небольшие группы устройств направляйте сообщения на токены регистрации, а не на темы. - person Michalsx; 16.02.2017
comment
@Maxim Firsoff - Как создать тему из консоли FCM или другим способом? - person Ajay Sharma; 12.07.2017
comment
@AjaySharma, насколько я помню, в консоли FMC нет инструментов для этого, вы можете создать тему программно (см. Выше мой псевдокод). - person Maxim Firsoff; 12.07.2017

Да, это возможно без сервера. Вы можете создать группу устройств на стороне клиента, а затем обмениваться сообщениями в группе. Однако есть ограничения:

  1. Вы должны использовать одну и ту же учетную запись Google на устройствах.
  2. Вы не можете отправлять сообщения с высоким приоритетом

Ссылка: документ Firebase См. Раздел «Управление группами устройств на Клиентские приложения для Android "

person greywolf82    schedule 10.12.2016
comment
вам все еще нужен сервер для отправки группового сообщения - person deviant; 13.04.2017
comment
Ни за что. Любое устройство в группе может отправить сообщение - person greywolf82; 13.04.2017
comment
из документов: Авторизация: key = API_KEY Вам по-прежнему нужен ключ сервера. поэтому это решение не подходит для производства - person deviant; 13.04.2017
comment
Ключ API - это учетная запись Google, и связь ограничена одной учетной записью пользователя. Попробуй, прежде чем комментировать. - person greywolf82; 13.04.2017

Облачные функции Google позволяют отправлять push-уведомления с устройства на устройство без сервера приложений. Я сделал облачную функцию, которая срабатывает при добавлении нового сообщения в базу данных.

Это node.js код

'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 ;


    });
person Vijayvir Sing Pantlia    schedule 26.09.2018

Если у вас есть fcm (gcm) токен устройства, на которое вы хотите отправить уведомление. Это просто почтовый запрос на отправку уведомления.

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

person Prashanth Debbadwar    schedule 14.10.2016
comment
Да, но для этого по-прежнему нужен собственный внешний сервер, верно? Потому что мы не должны встраивать API_KEY напрямую в наших клиентов. Мой вопрос заключался в том, возможно ли это без внешнего сервера, который в настоящее время не соответствует другим ответам. - person Suyash; 16.10.2016

Облачные функции Google позволяют отправлять push-уведомления с устройства на устройство без сервера приложений.

С соответствующей страницы в Google Cloud Functions:

Разработчики могут использовать облачные функции, чтобы поддерживать заинтересованность пользователей и получать актуальную информацию о приложении. Рассмотрим, например, приложение, которое позволяет пользователям следить за действиями друг друга в приложении. В таком приложении функция, запускаемая записью в базе данных в реальном времени для хранения новых подписчиков, может создавать уведомления Firebase Cloud Messaging (FCM), чтобы соответствующие пользователи знали, что у них появились новые подписчики.

Пример:

  1. Функция запускается при записи в путь к базе данных реального времени, где хранятся подписчики.

  2. Функция составляет сообщение для отправки через FCM.

  3. FCM отправляет уведомление на устройство пользователя.

Вот демонстрационный проект для отправки с устройства на устройство push-уведомления с помощью Firebase и Google Cloud Functions.

person Crashalot    schedule 04.11.2017

В моем случае я использую retrofit с этим сообщение класса:

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

наш ServiceAPi

public interface ServiceAPI {
    @POST("/fcm/send")
    Call<Message> sendMessage(@Header("Authorization") String token, @Body Message message);
}
person Cabezas    schedule 18.10.2018

Вы можете использовать дооснащение. Подписывайтесь на устройства на тематические новости. Отправлять уведомление с одного устройства на другое.

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

POJO

public class Message {
    String to;
    NotifyData notification;

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

}

а также

public class NotifyData {
    String title;
    String body;

    public NotifyData(String title, String body ) {

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

}

и FirebaseAPI

public interface FirebaseAPI {

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

}
person eurosecom    schedule 28.01.2017

Для этого вы можете использовать базу данных firebase в реальном времени. Вы можете создать структуру данных для хранения чатов и добавить наблюдателей для потоков разговора для обоих пользователей. Он по-прежнему делает архитектуру устройство - сервер - устройство, но в этом случае нет дополнительного сервера со стороны разработчиков. Это использует серверы firebase. Вы можете ознакомиться с учебным пособием здесь (не обращайте внимания на часть пользовательского интерфейса, хотя это также хорошая отправная точка для фреймворков пользовательского интерфейса чата).

Firebase Realtime Chat

person DS.    schedule 05.06.2016
comment
Пользователь не будет использовать приложение все время, и мы не можем использовать базу данных в реальном времени firebase в фоновом режиме, поскольку она поддерживает постоянное соединение сокета с сервером, что слишком сильно нагружает батарею устройства. - person Suyash; 06.06.2016
comment
Я могу отправлять сообщения Firebase между устройствами и уведомления с помощью библиотеки Smack. Я не реализую внешний сервер в моем коде Android. Smack управляет подключением и входящими / исходящими разделами сообщений, используя протокол XMPP. - person i_o; 13.09.2016

Вот прогулка по тому, как получать уведомления без второго сервера, кроме Firebase. Поэтому мы используем только Firebase, без дополнительного сервера.

  1. В коде мобильного приложения мы создаем собственную функцию уведомлений с помощью библиотек Android, например здесь, не использовать библиотеки Firebase, как здесь, без обмена сообщениями Firebase Cloud. Вот пример с Котлином:

    уведомление о частном веселье () {createNotificationChannel ()

     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)
     }
    
  1. В базе данных Firebase создайте коллекцию ожидающих уведомлений. Документы должны содержать имя пользователя (для отправки уведомления) и имя источника (куда должен перейти пользователь после нажатия на уведомление).

  2. В коде приложения реализовать возможность добавления новых записей в коллекцию ожидающих уведомлений. E. g. если пользователь A отправляет сообщение пользователю B, то в коллекции создается документ с идентификатором пользователя B (который будет уведомлен).

  3. В коде приложения настройте фоновую (когда приложение не видно пользователю) службу. Например, здесь. В фоновой службе настройте прослушиватель изменений в коллекции ожидающих уведомлений. Когда новая запись с идентификатором пользователя поступает в коллекцию, вызовите функцию уведомления, созданную в параграфе 1 supra, и удалите последующую запись из коллекции.

person Liker777    schedule 14.06.2021

Так что у меня появилась идея. См .: Если у FCM, а также у GCM есть конечная точка для HTTP-запроса, где мы можем отправить сообщение json с данными нашего сообщения, включая токены (-ы) устройств, которые мы хотим, чтобы это сообщение было доставлено.

Так почему бы не отправить сообщение на сервер Firebase с этим уведомлением, которое будет доставлено пользователю B? вы понимаете ?

Итак, вы отправляете сообщение и общаетесь в чате, чтобы гарантировать доставку уведомления, если пользователь работает с вашим приложением в фоновом режиме. Тоже мне скоро понадобится, позже потестирую. О чем ты говоришь?

person Paulo Linhares - Packapps    schedule 10.06.2016
comment
У FCM уже есть конечная точка, см. здесь. Но использовать его напрямую в наших клиентах невозможно, так как для этого требуется ключ api сервера. И даже если бы он был общедоступным, это вызвало бы проблемы с безопасностью, поскольку любой пользователь мог бы отправить любое сообщение FCM кому угодно. - person Suyash; 11.06.2016

Самый простой способ:

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;
}
}
person Sachin Shah    schedule 21.06.2017
comment
Const.FIREBASE_LEGACY_SERVER_KEY небезопасно использовать в коде на стороне клиента. Пожалуйста, по крайней мере, прочтите другие ответы и комментарии перед публикацией. - person Suyash; 21.06.2017