簡體   English   中英

帶有Google Cloud Messaging的App Engine后端向1000多個用戶發送消息

[英]App Engine Backend with Google Cloud Messaging sending message to more than 1000 users

我想向所有用戶發送消息(例如,可用更新)(〜15,000)。 我已經使用Google Cloud Messaging實現了App Engine后端來發送消息。

我已經在2種設備上進行了測試。 都收到消息。 但是正如google docs所說的那樣, “ GCM支持單個消息最多支持1000個收件人。”

我的問題是在我的情況下如何向其余14,000個用戶發送相同的消息? 還是下面的代碼會解決這個問題?

以下是發送消息的代碼

import com.google.android.gcm.server.Constants;
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiNamespace;

import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;

import javax.inject.Named;

import static com.example.shani.myapplication.backend.OfyService.ofy;

/**
 * An endpoint to send messages to devices registered with the backend
 * <p/>
 * For more information, see
 * https://developers.google.com/appengine/docs/java/endpoints/
 * <p/>
 * NOTE: This endpoint does not use any form of authorization or
 * authentication! If this app is deployed, anyone can access this endpoint! If
 * you'd like to add authentication, take a look at the documentation.
 */
@Api(name = "messaging", version = "v1", namespace = @ApiNamespace(ownerDomain = "backend.myapplication.shani.example.com", ownerName = "backend.myapplication.shani.example.com", packagePath = ""))
public class MessagingEndpoint {
    private static final Logger log = Logger.getLogger(MessagingEndpoint.class.getName());

    /**
     * Api Keys can be obtained from the google cloud console
     */
    private static final String API_KEY = System.getProperty("gcm.api.key");

    /**
     * Send to the first 10 devices (You can modify this to send to any number of devices or a specific device)
     *
     * @param message The message to send
     */
    public void sendMessage(@Named("message") String message) throws IOException {
        if (message == null || message.trim().length() == 0) {
            log.warning("Not sending message because it is empty");
            return;
        }
        // crop longer messages
        if (message.length() > 1000) {
            message = message.substring(0, 1000) + "[...]";
        }
        Sender sender = new Sender(API_KEY);

         Message msg = new Message.Builder().addData("message", message).build();

        List<RegistrationRecord> records = ofy().load().type(RegistrationRecord.class).limit(1000).list();
        for (RegistrationRecord record : records) {
            Result result = sender.send(msg, record.getRegId(), 5);
            if (result.getMessageId() != null) {
                log.info("Message sent to " + record.getRegId());
                String canonicalRegId = result.getCanonicalRegistrationId();
                if (canonicalRegId != null) {
                    // if the regId changed, we have to update the datastore
                    log.info("Registration Id changed for " + record.getRegId() + " updating to " + canonicalRegId);
                    record.setRegId(canonicalRegId);
                    ofy().save().entity(record).now();
                }
            } else {
                String error = result.getErrorCodeName();
                if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
                    log.warning("Registration Id " + record.getRegId() + " no longer registered with GCM, removing from datastore");
                    // if the device is no longer registered with Gcm, remove it from the datastore
                    ofy().delete().entity(record).now();
                } else {
                    log.warning("Error when sending message : " + error);
                }
            }
        }
    }
}

我知道有類似的問題,但我使用的是Java語言。 我發現在后端使用php語言的問題。 所以對我沒有幫助!

  1. Google Cloud Messaging:向“所有”用戶發送消息
  2. 在多個設備上發送推送通知

是否有人成功實現了App Engine + Google Cloud Messaging JAVA語言?

在下面的代碼行中,如果我將1000替換為15,000,它將解決我的問題嗎?

List<RegistrationRecord> records = ofy().load().type(RegistrationRecord.class).limit(1000).list();

請盡快提供幫助。 非常抱歉我的英語。如果有人需要其他詳細信息,歡迎您提出。

謝謝你的時間。

一些注意事項,

1)向可能數量龐大的用戶發送通知可能會花費大量時間,請考慮使用“ 任務隊列 ”將在60秒以內“離線”完成的工作排隊。

2)現在,對於GCM限制,如果您需要所有用戶,但GCM一次允許您有1000個,只需將它們分成1000個批次,並分別向每個批次發送一條消息。

如果將這兩個建議結合在一起,則應該有一個相當可擴展的過程,您可以在1個請求中查詢所有用戶,拆分該列表,然后僅一次將消息發送給這些用戶1000個隊列。

以下@jirungaray答案的擴展名是用於將GCM消息發送給所有注冊用戶的代碼,

在這里,我假設從android您正在為GCM服務注冊每個移動設備並將這些設備令牌存儲在數據庫中。

public class GCM {
    private final static Logger LOGGER = Logger.getLogger(GCM.class.getName());
    private static final String API_KEY = ConstantUtil.GCM_API_KEY;
    public static void doSendViaGcm(List<String> tocken,String message) throws IOException {
        Sender sender = new Sender(API_KEY);
    // Trim message if needed.
    if (message.length() > 1000) {
      message = message.substring(0, 1000) + "[...]";
     }
     Message msg = new Message.Builder().addData("message", message).build();
    try{
    MulticastResult result = sender.send(msg, tocken, 5);
    }catch(Exception ex){
    LOGGER.severe("error is"+ex.getMessage());
    ex.printStackTrace();
    }
}

}

在上面的代碼段中,可以從Google控制台項目中獲取API_KEY,這里我假設您已經創建了一個Google控制台項目並啟用了GCM api,

您可以如下生成API_KEY

your_google_console_project >>憑證>>創建新密鑰>>服務器密鑰>>輸入您要允許訪問GCM api的IP地址[我使用了0.0.0.0/0]

現在,GCM類的doSendViaGcm(List tocken,String message)執行向所有注冊的android移動設備發送消息的任務

這里List<String> token is array-list of all device token將在其上傳遞消息List<String> token is array-list of all device token ,請記住,此list size不能than 1000 ,否則http調用將失敗。

希望這對您有所幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM