Firebase Java服务器如何向所有设备发送推送通知

24

我正在尝试使用新的Firebase服务向我的安卓设备发送推送通知。

我已注册并设置了应用程序,还在安卓应用程序中放置了接收通知所需的所有代码。通过Firebase控制台,我可以向我的应用程序发送通知并成功接收并显示。

现在我想编写一个Java独立服务器以向所有设备发送通知。以下是我的当前代码:

final String apiKey = "I added my key here";
URL url = new URL("https://fcm.googleapis.com/fcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "key=" + apiKey);

conn.setDoOutput(true);

String input = "{\"notification\" : {\"title\" : \"Test\"}, \"to\":\"test\"}";

OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
os.close();

int responseCode = conn.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + input);
System.out.println("Response Code : " + responseCode);

BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();

while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();

// print result
System.out.println(response.toString());

这是我从他们服务器收到的结果:

{"multicast_id":6602141464107786356,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}

很遗憾,仅仅删除“to”标签无效,我会收到一个400代码返回。 我看到需要注册设备,将设备ID发送到服务器并在那里保存,然后循环遍历服务器上所有已注册的设备以发送消息。 难道没有更简单的方法,就像在控制台中发送消息一样吗?

非常感谢您的帮助,因为我一整天都在尝试使它工作 =(

问候, 达斯汀


你可以查看这个答案 https://dev59.com/PqXja4cB1Zd3GeqPYOV_#51172021 - Md. Sajedul Karim
10个回答

18

是的,我也考虑过这种方式,但我不想在应用程序本身中进行任何注册代码... 你有什么想法吗?是否可能以某种方式实现? - user3907491
4
在应用程序中,"registration code"是指注册码。当用户启动您的应用时,您可以自动将他们注册到主题中。在Android中,代码如下: FirebaseMessaging.getInstance().subscribeToTopic("allDevices"); 您可以将此代码放在onCreate方法中,在应用启动时,他们就会自动注册。 - Alexander N.
太棒了,感谢您的帮助!这正是我在寻找的 =) 我该如何将您的答案标记为最佳答案?我已经点赞了它。 - user3907491
左侧的踩和分数符号下面应该有一个勾选标记。我看到您已经选中了它。谢谢! - Alexander N.

13

这个解决方案使用Apache HttpClient向Firebase发送推送通知:

HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost("https://fcm.googleapis.com/fcm/send");
post.setHeader("Content-type", "application/json");
post.setHeader("Authorization", "key=AIzaSyBSxxxxsXevRq0trDbA9mhnY_2jqMoeChA");

JSONObject message = new JSONObject();
message.put("to", "dBbB2BFT-VY:APA91bHrvgfXbZa-K5eg9vVdUkIsHbMxxxxxc8dBAvoH_3ZtaahVVeMXP7Bm0iera5s37ChHmAVh29P8aAVa8HF0I0goZKPYdGT6lNl4MXN0na7xbmvF25c4ZLl0JkCDm_saXb51Vrte");
message.put("priority", "high");

JSONObject notification = new JSONObject();
notification.put("title", "Java");
notification.put("body", "Notificação do Java");

message.put("notification", notification);

post.setEntity(new StringEntity(message.toString(), "UTF-8"));
HttpResponse response = client.execute(post);
System.out.println(response);
System.out.println(message);

我在您的代码中遇到了一个错误:HttpClientBuilder无法解析。我该如何修复这个错误? - Peter
你是否已经添加了Maven依赖项? <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency> - gilbriatore
message 中的 "to" 值到底是什么? - tomasb
1
@Geucimar 在运行这段代码片段后,我得到了这个响应。 - Hasan shaikh
https://www.google.co.in/search?q=HTTP%2F1.1+401+Unauthorized+%5BContent-Type%3A+text% - Hasan shaikh
此功能现已过时。 - grantespo

11

使用以下代码将推送通知发送到多个设备:

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.MulticastResult;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;

public class PushNotifactionHelper {
public final static String AUTH_KEY_FCM = "your key ";
public final static String API_URL_FCM = "https://fcm.googleapis.com/fcm/send";

public static void sendPushNotification(List<String> deviceTokenList) {
    Sender sender = new Sender(AUTH_KEY_FCM);
    Message msg = new Message.Builder().addData("message", "Message body")
            .build();
    try {
        MulticastResult result = sender.send(msg, deviceTokenList, 5);
        for (Result r : result.getResults()) {
            if (r.getMessageId() != null) 
                System.out.println("Push Notification Sent Successfully");
             else 
                System.out.println("ErrorCode " + r.getErrorCodeName());
        }
    } catch (IOException e) {
        System.out.println("Error " + e.getLocalizedMessage());
    }
   }
  }   

注意:使用 gcm.server.jar


2
运行得很好,就像魔法般。谢谢。 - Avijit Nagare
1
API_URL_FCM有什么用处?代码中没有使用它。 - kunal
1
请注意 - gcm-server 不再维护 FCM - https://github.com/google/gcm/pull/272/files#diff-04c6e90faac2675aa89e2176d2eec7d8R3 - prayagupa

9

你的JSON格式将会是这个样子:

      {
      "registration_ids": [
                        "fcm token 1",
                        "fcm token 2",
                        "fcm token 3"
                    ],
      "data": {
                "message": "msg"
              },
      "notification": {
                "title": "App name",
                "text": " your msg"
            }
    }
public void sendGroupPush(Context context, ArrayList tokenlist, String message) {
            String msg = message;
            String title = context.getString(R.string.app_name);
            JSONArray regId = null;
            JSONObject objData = null;
            JSONObject data = null;
            JSONObject notif = null;
            try {
                regId = new JSONArray();
                for (int i = 0; i < tokenlist.size(); i++) {
                    regId.put(tokenlist.get(i));
                }
                data = new JSONObject();
                data.put("message", message);
                notif = new JSONObject();
                notif.put("title", title);
                notif.put("text", msg);

                objData = new JSONObject();
                objData.put("registration_ids", regId);
                objData.put("data", data);
                objData.put("notification", notif);
                Log.e("!_@rj@_group_PASS:>", objData.toString());
            } catch (JSONException e) {
                e.printStackTrace();
            }

            JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, Constants.FCM_PUSH_GROUP_URL, objData,
                    new Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject response) {
                            Log.e("!_@rj@_@@_SUCESS", response + "");
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            Log.e("!_@rj@_@@_Errors--", error + "");
                        }
                    }) {
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> params = new HashMap<String, String>();
                    params.put("Authorization", "key=" + Constants.FCM_API_KEY);
                    params.put("Content-Type", "application/json");
                    Log.e("!_@rj@_@@PUSH_headrers", "::> " + params);
                    return params;
                }
            };
            RequestQueue requestQueue = Volley.newRequestQueue(context);
            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);
        }

公共静态字符串FCM_PUSH_URL = "https://fcm.googleapis.com/fcm/send";


(注:该代码段为Java代码,FCM代指Firebase Cloud Messaging)

6

这里我有一个非常简单的解决方案,可以发送推送消息给群组和个人。

public class FCM {
final static private String FCM_URL = "https://fcm.googleapis.com/fcm/send";

/**
* 
* Method to send push notification to Android FireBased Cloud messaging 
Server.
* @param tokenId Generated and provided from Android Client Developer
* @param server_key Key which is Generated in FCM Server 
   @param message which contains actual information.
* 
*/

static void send_FCM_Notification(String tokenId, String server_key, String 

message){


    try{
// Create URL instance.
URL url = new URL(FCM_URL);
// create connection.
HttpURLConnection conn;
conn = (HttpURLConnection) url.openConnection();
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
//set method as POST or GET
conn.setRequestMethod("POST");
//pass FCM server key
conn.setRequestProperty("Authorization","key="+server_key);
//Specify Message Format
conn.setRequestProperty("Content-Type","application/json");
//Create JSON Object & pass value
 JSONObject infoJson = new JSONObject();

 infoJson.put("title","Alankit");
infoJson.put("body", message);

JSONObject json = new JSONObject();
json.put("to",tokenId.trim());
json.put("notification", infoJson);

System.out.println("json :" +json.toString());
System.out.println("infoJson :" +infoJson.toString());
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(json.toString());
wr.flush();
int status = 0;
if( null != conn ){
status = conn.getResponseCode();
}
if( status != 0){

if( status == 200 ){
//SUCCESS message
BufferedReader reader = new BufferedReader(new 
InputStreamReader(conn.getInputStream()));
System.out.println("Android Notification Response : " + reader.readLine());
}else if(status == 401){
//client side error
System.out.println("Notification Response : TokenId : " + tokenId + " Error occurred :");
}else if(status == 501){
//server side error
System.out.println("Notification Response : [ errorCode=ServerError ] TokenId : " + tokenId);
}else if( status == 503){
//server side error
System.out.println("Notification Response : FCM Service is Unavailable  
TokenId : " + tokenId);
}
}
}catch(MalformedURLException mlfexception){
// Prototcal Error
System.out.println("Error occurred while sending push Notification!.." + mlfexception.getMessage());
}catch(Exception mlfexception){
//URL problem
System.out.println("Reading URL, Error occurred while sending push 
Notification!.." + mlfexception.getMessage());
}

}

 static void send_FCM_NotificationMulti(List<String> putIds2, String 
tokenId, 
 String server_key, String message){
    try{
    // Create URL instance.
    URL url = new URL(FCM_URL);
    // create connection.
    HttpURLConnection conn;
    conn = (HttpURLConnection) url.openConnection();
    conn.setUseCaches(false);
    conn.setDoInput(true);
    conn.setDoOutput(true);
    //set method as POST or GET
    conn.setRequestMethod("POST");
    //pass FCM server key
    conn.setRequestProperty("Authorization","key="+server_key);
    //Specify Message Format
    conn.setRequestProperty("Content-Type","application/json");
    //Create JSON Object & pass value

        JSONArray regId = null;
        JSONObject objData = null;
        JSONObject data = null;
        JSONObject notif = null;

            regId = new JSONArray();
            for (int i = 0; i < putIds2.size(); i++) {
                regId.put(putIds2.get(i));
            }
            data = new JSONObject();
            data.put("message", message);
            notif = new JSONObject();
            notif.put("title", "Alankit Universe");
            notif.put("text", message);

            objData = new JSONObject();
            objData.put("registration_ids", regId);
            objData.put("data", data);
            objData.put("notification", notif);
            System.out.println("!_@rj@_group_PASS:>"+ objData.toString());


    System.out.println("json :" +objData.toString());
    OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());

    wr.write(objData.toString());
    wr.flush();
    int status = 0;
    if( null != conn ){
    status = conn.getResponseCode();
    }
    if( status != 0){

        if( status == 200 ){
    //SUCCESS message
    BufferedReader reader = new BufferedReader(new 
    InputStreamReader(conn.getInputStream()));
    System.out.println("Android Notification Response : " + 
    reader.readLine());
    }else if(status == 401){
    //client side error
    System.out.println("Notification Response : TokenId : " + tokenId + " 
      Error occurred :");
    }else if(status == 501){
    //server side error
    System.out.println("Notification Response : [ errorCode=ServerError ] 
    TokenId : " + tokenId);
    }else if( status == 503){
    //server side error
    System.out.println("Notification Response : FCM Service is Unavailable  
   TokenId : " + tokenId);
    }
    }
    }catch(MalformedURLException mlfexception){
    // Prototcal Error
    System.out.println("Error occurred while sending push Notification!.." + 
   mlfexception.getMessage());
    }catch(IOException mlfexception){
    //URL problem
    System.out.println("Reading URL, Error occurred while sending push 
  Notification!.." + mlfexception.getMessage());
    }catch (Exception exception) {
    //General Error or exception.
    System.out.println("Error occurred while sending push Notification!.." + 
 exception.getMessage());
    }

    }

}

     Calling should be like that :



  public class TestFCM {
        static List<String> putIds;
        public static void main(String[] args) {

    //Just I am passed dummy information
    // DeviceID's

    String tokenId1 = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    String tokenId  = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
    String server_key ="<Server Key>" ;
    String message = "Welcome alankit Push Service.";

    putIds= new ArrayList<>();
    putIds.add(tokenId1);
    putIds.add(tokenId);

   /* for Group*/
    FCM.send_FCM_NotificationMulti(putIds,tokenId,server_key,message);  

    /*for indevidual*/
    FCM.send_FCM_Notification( tokenId,server_key,message);
    }


}

4

您的代码非常完美,只需重新检查您发送通知的用户的注册ID。请使用用户设备的regid代替to。这对我来说非常有效。


3

安卓客户端代码应该是:

//subscribe_topic with name "ALL"
FirebaseMessaging.getInstance().subscribeToTopic("ALL");    

服务器端:

string json = "{\"to\": \"/topics/ALL\",\"data\": {\"message\": \"This is a Cloud Messaging Topic Message\",}}";

3
  @Autowired
AndroidPushNotificationsService androidPushNotificationsService;

@RequestMapping(value = "/send", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<String> send() {


    JSONObject body = new JSONObject();
    // JsonArray registration_ids = new JsonArray();
    // body.put("registration_ids", registration_ids);
    body.put("to", "xxxxxxxxxxxxxxxxxxxjPwZpLgLpji_");
    body.put("priority", "high");
    // body.put("dry_run", true);

    JSONObject notification = new JSONObject();
    notification.put("body", "body string here");
    notification.put("title", "title string here");
    // notification.put("icon", "myicon");

    JSONObject data = new JSONObject();
    data.put("key1", "value1");
    data.put("key2", "value2");

    body.put("notification", notification);
    body.put("data", data);

    HttpEntity<String> request = new HttpEntity<>(body.toString());

    CompletableFuture<FirebaseResponse> pushNotification = androidPushNotificationsService.send(request);
    CompletableFuture.allOf(pushNotification).join();

    try {
        FirebaseResponse firebaseResponse = pushNotification.get();
        if (firebaseResponse.getSuccess() == 1) {
            log.info("push notification sent ok!");
        } else {
            log.error("error sending push notifications: " + firebaseResponse.toString());
        }
        return new ResponseEntity<>(firebaseResponse.toString(), HttpStatus.OK);

    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    return new ResponseEntity<>("the push notification cannot be send.", HttpStatus.BAD_REQUEST);
}

您可以从这里获取类:https://github.com/AndreiD/testingpushnotifications

我检查了你的代码,但我不明白的是为什么你要使用HeaderRequestInterceptor,而你可以直接使用HttpHeaders来设置头,并将其放入HttpEntity中。 - zt1983811

1

您只需要Firebase服务器密钥以进行授权。 您只需编写HTTP客户端代码,可以使用任何编程语言进行此操作。

查看Github Repo。 它具有完整的Java Rest Client项目,用于从Java服务器发送Firebase推送通知。


1
使用以下代码通过 FCM 向多个设备发送推送。
public void sendAndroidPush(String input) {
        final String apiKey = ServerKey or legacyServerKey;
        StringBuffer response = new StringBuffer();
        try {
            URL url = new URL("https://fcm.googleapis.com/fcm/send");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Authorization", "key=" + apiKey);

            conn.setDoOutput(true);

            OutputStream os = conn.getOutputStream();
            os.write(input.getBytes());
            os.flush();
            os.close();

            int responseCode = conn.getResponseCode();
            System.out.println("\nSending 'POST' request to URL : " + url);
            System.out.println("Post parameters : " + input);
            System.out.println("Response Code : " + responseCode);

            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;


            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
        // print result
        System.out.println(response.toString());
    }


JSONArray devices = new JSONArray();
        devices.put("Your Actual Device Token");

        JSONObject payloadObj = new JSONObject();
        try {
            JSONObject notifyObj = new JSONObject();
            notifyObj.put("title","Your Title");
            notifyObj.put("text", "Your Text");

            payloadObj.put("registration_ids",devices.toString());
            payloadObj.put("notification",notifyObj.toString());

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        sendAndroidPush(payloadObj.toString());

1
它返回了HTTP响应代码400,URL为https://fcm.googleapis.com/fcm/send,为什么? - Onkar Musale

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接