Как отправить сообщение устройства на устройство с помощью Firebase Cloud Messaging?
После поиска документов я не смог найти информацию о том, как отправлять сообщения устройства на устройство с помощью FCM без использования внешнего сервера.
Например, если я создавал приложение для чата, мне нужно было бы отправлять push-уведомления пользователям о непрочитанных сообщениях, так как они не будут в сети все время, и я не могу иметь постоянную службу в фоновом режиме, которая всегда будет быть подключенным к базе данных реального времени, потому что это будет слишком тяжелым ресурсом.
Итак, как я могу отправить push-уведомление пользователю "A", когда определенный пользователь "B" отправляет ему чат-сообщение? Нужен ли мне внешний сервер для этого или может быть сделано только с серверами Firebase?
Ответы
Ответ 1
UPDATE: теперь можно использовать функции облачной службы firebase в качестве сервера для обработки push-уведомлений. Ознакомьтесь с их документацией здесь.
============
В соответствии с документами вы должны внедрить сервер для обработки push-уведомлений в устройстве для связи с устройством.
Прежде чем вы сможете писать клиентские приложения, использующие Firebase Cloud Messaging, у вас должен быть сервер приложений, который отвечает следующим критериям:
...
Вам нужно будет решить, какой протокол сервера соединений FCM вы хотите использовать, чтобы ваш сервер приложений мог взаимодействовать с серверами соединений FCM. Обратите внимание: если вы хотите использовать восходящую передачу сообщений из ваших клиентских приложений, вы должны использовать XMPP. Подробнее об этом см. В разделе Выбор протокола сервера соединений FCM.
Если вам нужно отправлять основные уведомления пользователям с сервера. Вы можете использовать их безсерверное решение Firebase Notifications.
См. Здесь сравнение между FCM и уведомлениями Firebase: https://firebase.google.com/support/faq/#messaging-difference
Ответ 2
Мне помог запрос HTTP POST со ссылкой https://fcm.googleapis.com/fcm/send с обязательным заголовком и данными. В приведенном ниже фрагменте кода Constants.LEGACY_SERVER_KEY
- это локальная переменная класса, вы можете найти ее в своем проекте Firebase Settings->Cloud Messaging->Legacy Server key
. Вам необходимо передать маркер регистрации устройства, т.е. regToken
в приведенном ниже фрагменте кода, на который ссылается ЗДЕСЬ.
Наконец, вам нужна зависимость от библиотеки 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.
ВАЖНО: - Использование приведенного выше кода означает, что ваш ключ сервера находится в клиентском приложении. Это опасно, поскольку кто-то может зайти в ваше приложение и получить ключ сервера для отправки вредоносных уведомлений вашим пользователям.
Ответ 3
Да, это возможно сделать без какого-либо сервера. Вы можете создать клиентскую группу группы устройств, а затем обмениваться сообщениями в группе. Однако существуют ограничения:
- Вы должны использовать ту же учетную запись Google на устройствах
- Вы не можете отправлять сообщения с высоким приоритетом
Ссылка: Firebase doc См. раздел "Управление группами устройств в клиентских приложениях Android"
Ответ 4
1) подпишитесь на идентичное имя темы, например:
- ClientA.subcribe( "в/topic_users_channel" )
- ClientB.subcribe( "в/topic_users_channel" )
2) отправлять сообщения внутри приложения
GoogleFirebase: как отправить сообщения темы
Ответ 5
Вы можете сделать это, используя запрос Volly Jsonobject....
выполните следующие шаги:
1 скопируйте старый ключ сервера и сохраните его как Legacy_SERVER_KEY
Легальный серверный ключ
вы можете видеть на картинке, как получить
2 Вам нужна зависимость от Volley
compile '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("[email protected]@[email protected]@_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("[email protected]@_SUCESS", response + "");
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("[email protected]@_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();
Ответ 6
Если у вас есть токен fcm (gcm) устройства, которому вы хотите отправить уведомление. Это просто запрос на отправку уведомления.
https://github.com/prashanthd/google-services/blob/master/android/gcm/gcmsender/src/main/java/gcm/play/android/samples/com/gcmsender/GcmSender.java
Ответ 7
Вы можете использовать "Дооснащение". Подписывайте устройства для обсуждения новостей. Отправлять уведомление с одного устройства на другое.
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;
}
}
и
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);
}
Ответ 8
Облачные функции Google теперь позволяют отправлять push-уведомления с устройства на устройство без сервера приложений.
На соответствующей странице в облачных функциях Google:
Разработчики могут использовать функции Cloud, чтобы поддерживать пользователей и до дату с соответствующей информацией о приложении. Рассмотрим, например, приложение, которое позволяет пользователям следить друг за другом в приложении. В таком приложении функция, запускаемая базой данных Realtime, записывает в новые подписчики могут создавать Firebase Cloud Messaging (FCM) уведомления, чтобы соответствующие пользователи знали, что они получили новых последователей.
Пример:
-
Функция запускает запись в путь базы данных Realtime, где хранятся последователи.
-
Функция создает сообщение для отправки через FCM.
-
FCM отправляет уведомление на пользовательское устройство.
Вот демонстрационный проект для отправки push-уведомлений устройства на устройство с Firebase и облачными функциями Google.
Ответ 9
Облачные функции 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 ;
});
Ответ 10
В моем случае я использую модификацию с этим классом 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;
}
Данные
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);
}
Ответ 11
Вы можете использовать базу данных реального времени firebase для этого. Вы можете создать структуру данных для хранения чатов и добавить наблюдателей для потоков беседы для обоих пользователей. Он по-прежнему не обладает архитектурой device-server-device, но в этом случае на стороне разработчиков нет дополнительного сервера. Это использует серверы firebase. Вы можете ознакомиться с учебником здесь (игнорируйте часть пользовательского интерфейса, хотя это также хорошая отправная точка для пользовательских интерфейсов чата).
Firebase Realtime Chat
Ответ 12
Итак, у меня была идея. См.: Если FCM, а также GCM имеют доступ к HTTP-запросу, мы можем отправить сообщение json с данными наших сообщений, включая токены устройств, которые мы хотим, чтобы это сообщение было доставлено.
Так почему бы не отправить сообщение на сервер Firebase с этим уведомлением, которое будет доставлено пользователю B? вы понимаете?
Итак, вы отправляете сообщение и чат с сообщением о вызове, чтобы обеспечить доставку уведомления, если пользователь находится в вашем приложении в фоновом режиме. Я тоже скоро буду в этом нуждаться, я буду тестировать позже. Что вы говорите?
Ответ 13
Я потратил много времени на эту тему, так как моему требованию точно не нужен AppServer, и я чувствовал, что это как бремя, так и узкое место в производительности - из-за очевидной поездки в оба конца.
Несмотря на то, что согласно официальным документам вам нужен внешний сторонний AppServer для пересылки/генерации нисходящего push-уведомления клиентам, вы можете на самом деле замаскировать функцию AppServer, создав HTTP-запросы POST (которые, согласно документам, должны быть сгенерированы от стороннего Appserver) от самих клиентов. Вот фрагмент кода метода HTTP POST FCM Сообщение от клиентов:
public class FcmDeviceNotifier {
private final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private final String TAG = FcmDeviceNotifier.class.getSimpleName();
private String requestType;
private JSONObject payloadJson;
public FcmDeviceNotifier(String requestType /*can be "notification" or "data"*/) {
this.requestType = requestType;
}
public void setValuePairs(Map<String, String> valuePairs) {
try {
payloadJson = new JSONObject();
Iterator<Map.Entry<String,String>> iterator = valuePairs.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String,String> entry = iterator.next();
payloadJson.put(entry.getKey(), entry.getValue());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void sendNotification(final String regToken /*Token of target device*/) {
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
try {
OkHttpClient client = new OkHttpClient();
JSONObject fcmJson = new JSONObject();
fcmJson.put(requestType, payloadJson);
fcmJson.put(TO, regToken);
RequestBody body = RequestBody.create(JSON, fcmJson.toString());
Request request = new Request.Builder()
.header(AUTHORIZATION, "key=" + Constants.FCM_LEGACY_KEY)
.url("https://fcm.googleapis.com/fcm/send")
.post(body)
.build();
Response response = client.newCall(request).execute();
String finalResponse = response.body().string();
Log.d(TAG, "sendNotification: " + finalResponse);
}catch (Exception e){
Log.e(TAG, "sendNotification: " + e.getMessage());
}
return null;
}
}.execute();
}
}
Предоставлено brijesh kumar
Ответ 14
Простейший способ:
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;
}
}