如何使用Firebase Cloud Messaging将设备发送到设备消息?
在搜索文档后,我找不到任何有关如何使用FCM将设备发送到设备消息的信息,而无需使用外部服务器。
例如,如果我正在创建一个聊天应用程序,我需要发送推送通知给用户关于未读消息,因为他们不会一直在线,我不能有一个永远连接到后台的持久服务实时数据库,因为这将是太重的资源。
那么当某个用户“B”向他/她发送聊天消息时,如何向用户“A”发送推送通知? 我需要一个外部服务器吗?还是只能使用Firebase服务器来完成?
更新:现在可以使用Firebase云功能作为处理推送通知的服务器。 在这里查看他们的文档
============
根据文档,您必须实现一个服务器来处理设备间通信的推送通知。
在编写使用Firebase云消息传递的客户端应用程序之前,必须先安装符合以下标准的应用程序服务器:
…
您需要决定要使用哪个FCM连接服务器协议来启用您的应用服务器与FCM连接服务器进行交互。 请注意,如果您想要使用来自客户端应用程序的上行消息,则必须使用XMPP。 有关更详细的讨论,请参阅选择FCM连接服务器协议 。
如果您只需要从服务器向用户发送基本通知。 您可以使用其无服务器解决方案Firebase通知 。
查看FCM和Firebase通知之间的比较: https ://firebase.google.com/support/faq/#messaging-difference
我明白了这一点:
通过链接“ https://fcm.googleapis.com/fcm/send ”发出HTTP POST请求,并在此处引用所需的标题和数据。
Constants.LEGACY_SERVER_KEY是本地类变量,您可以在Firebase项目设置 – >云端消息传送 – >传统服务器密钥中找到此变量。 您需要在下面的代码片段中引用设备注册令牌(reg_token) HERE。
不过,你需要okhttp库依赖才能得到这个片段的工作。
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); private void sendNotification(final String reg_token) { 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中的“regToken”
json.put("to","/topics/foo-bar")
最后不要忘记在你的AndroidManifest.xml中添加INTERNET权限。
重要提示 : – 使用上面的代码意味着您的服务器密钥驻留在客户端应用程序中。 这是很危险的,因为有人可以挖掘你的应用程序,并获得服务器密钥发送恶意通知给你的用户。
1)订阅相同的主题名称,例如:
- ClientA.subcribe( “到/ topic_users_channel”)
- ClientB.subcribe( “到/ topic_users_channel”)
2)在应用程序内部发送消息
GoogleFirebase:如何发送主题消息
是的,有可能没有任何服务器。 您可以创建设备组客户端,然后在组中交换消息。 但是有一些限制:
- 您必须在设备上使用相同的Google帐户
- 您不能发送高优先级的消息
参考: Firebase文档请参阅“管理Android客户端应用程序上的设备组”一节
如果您有要向其发送通知的设备的fcm(gcm)令牌。 这只是发送通知的发布请求。
你可以使用Retrofit。 订阅设备主题新闻。 从一个设备发送通知给其他设备。
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); }
您可以使用Volly Jsonobject请求来执行此操作。
先按照以下步骤操作:
1复制旧版服务器密钥并将其作为Legacy_SERVER_KEY存储
传统服务器密钥
你可以在图片中看到如何获得
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); }
只需调用sendFCMPush() ;
所以我在这里有一个想法。 请参阅:如果FCM以及GCM对http请求有一个endpoint,那么我们可以发送包含我们希望传递此消息的设备令牌的消息数据的post json。
那么为什么不发送一个帖子到Firebase服务器,并将这个通知发送给用户B呢? 你明白 ?
因此,如果用户在后台使用应用程序,则可以发送消息并与通话消息进行聊天,以确保发送通知。 我也很快就需要这个了,以后再测试一下。 你怎么说?
您可以使用Firebase实时数据库来执行此操作。 您可以创建用于存储聊天的数据结构,并为两个用户添加对话线程的观察者。 它仍然是设备 – 服务器 – 设备架构,但是在这种情况下,开发者不需要额外的服务器。 这使用了Firebase服务器。 你可以在这里查看教程(忽略UI部分,尽管这也是聊天UI框架的一个很好的起点)。
Firebase实时聊天
我花了很多时间在这个话题上,因为我的需求并不需要一个AppServer,而且我觉得这是一个负担,以及性能瓶颈 – 由于明显的往返。
即使根据官方文档,您需要外部第三方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
Google云端函数使得现在可以在没有应用服务器的情况下从设备到设备发送推送通知。
从 Google云端功能的相关页面 :
开发人员可以使用云功能来保持用户的参与,并了解有关应用程序的相关信息。 例如,考虑一个允许用户在应用程序中关注对方活动的应用程序。 在这样的应用程序中,由实时数据库写入来存储新追随者的功能可以创建Firebase云消息传递(FCM)通知,以便让适当的用户知道他们获得了新的追随者。
例:
该函数触发写入存储追随者的实时数据库路径。
该功能组成一个消息通过FCM发送。
FCM将通知消息发送给用户的设备。
这是一个演示项目,用于通过Firebase和Google云端功能发送设备到设备推送通知。
最简单的方法:
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; } }