Java 应用程序引擎后端与谷歌云消息发送消息给1000多个用户

Java 应用程序引擎后端与谷歌云消息发送消息给1000多个用户,java,google-app-engine,google-cloud-messaging,sendmessage,multiple-users,Java,Google App Engine,Google Cloud Messaging,Sendmessage,Multiple Users,我想向所有用户(~15000)发送一条消息(例如,更新可用)。我已经实现了发送消息 我在2台设备上进行了测试。两个都有消息。但正如google docs所说,“GCM支持一条消息最多1000个收件人。” 我的问题是如何将相同的消息发送给我的系统中剩余的14000个用户 案例或者下面的代码会处理它 下面是发送消息的代码 import com.google.android.gcm.server.Constants; import com.google.android.gcm.server.Messa

我想向所有用户(~15000)发送一条消息(例如,更新可用)。我已经实现了发送消息

我在2台设备上进行了测试。两个都有消息。但正如google docs所说,“GCM支持一条消息最多1000个收件人。”

我的问题是如何将相同的消息发送给我的系统中剩余的14000个用户 案例或者下面的代码会处理它

下面是发送消息的代码

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);
                }
            }
        }
    }
}
import com.google.android.gcm.server.Constants;
导入com.google.android.gcm.server.Message;
导入com.google.android.gcm.server.Result;
导入com.google.android.gcm.server.Sender;
导入com.google.api.server.spi.config.api;
导入com.google.api.server.spi.config.ApiNamespace;
导入java.io.IOException;
导入java.util.List;
导入java.util.logging.Logger;
导入javax.inject.Named;
导入静态com.example.shani.myapplication.backend.OfyService.ofy;
/**
*向在后端注册的设备发送消息的端点
*

*有关详细信息,请参阅 * https://developers.google.com/appengine/docs/java/endpoints/ *

*注意:此端点不使用任何形式的授权或 *认证!如果部署了此应用,任何人都可以访问此端点!如果 *如果要添加身份验证,请查看文档。 */ @Api(name=“messaging”,version=“v1”,namespace=@ApiNamespace(ownerDomain=“backend.myapplication.shani.example.com”,ownerName=“backend.myapplication.shani.example.com”,packagePath=”“) 公共类MessagingEndpoint{ 私有静态最终记录器log=Logger.getLogger(MessaginEndpoint.class.getName()); /** *Api密钥可以从google云控制台获得 */ 私有静态最终字符串API_KEY=System.getProperty(“gcm.API.KEY”); /** *发送到前10个设备(您可以修改此选项以发送到任意数量的设备或特定设备) * *@param message要发送的消息 */ public void sendMessage(@Named(“message”)字符串消息)引发IOException{ if(message==null | | message.trim().length()==0){ log.warning(“由于消息为空而不发送消息”); 返回; } //裁剪长消息 如果(message.length()>1000){ message=message.substring(0,1000)+“[…]”; } 发送方=新发送方(API_密钥); Message msg=new Message.Builder().addData(“Message”,Message).build(); 列表记录=of y().load().type(RegistrationRecord.class).limit(1000).List(); 用于(注册记录:记录){ 结果=sender.send(msg,record.getRegId(),5); if(result.getMessageId()!=null){ log.info(“消息发送到”+record.getRegId()); 字符串canonicalRegId=result.getCanonicalRegistrationId(); 如果(canonicalRegId!=null){ //如果regId发生了变化,我们必须更新数据存储 log.info(“将“+record.getRegId()+”的注册Id更改为“+canonicalRegId”); record.setRegId(canonicalRegId); ofy().save().entity(record).now(); } }否则{ 字符串错误=result.getErrorCodeName(); if(error.equals(Constants.error\u未注册)){ log.warning(“注册Id”+记录.getRegId()+“不再向GCM注册,从数据存储中删除”); //如果设备不再向Gcm注册,请将其从数据存储中删除 ofy().delete().entity(record).now(); }否则{ 日志警告(“发送消息时出错:+错误”); } } } } }

我知道有类似的问题,但我使用的是Java语言。我在后端发现了使用php语言的问题。所以对我没有帮助

  • 是否有人成功实现了App Engine+谷歌云消息JAVA语言

    在下面的代码行中,如果我用15000替换1000,它会解决我的问题吗

    List<RegistrationRecord> records = ofy().load().type(RegistrationRecord.class).limit(1000).list();
    
    List records=ofy().load().type(RegistrationRecord.class).limit(1000).List();
    
    请尽快帮忙。非常抱歉我的英语。。如果有人需要其他详细信息,欢迎询问

    谢谢您的时间。

    一些注意事项

    1)向可能的大量用户发送通知可能需要很长时间,考虑使用队列将工作“离线”在60秒限制之外完成。 2) 至于GCM限制,如果您需要所有用户,但GCM允许您一次使用1000个,只需将它们分成1000个批次,并分别向每个批次发送一条消息


    如果您将这两个建议结合起来,您应该有一个相当可扩展的流程,您可以在一个请求中查询所有用户,将该列表拆分,然后将消息一次发送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();
        }
    }
    
    }
    
    公共类GCM{
    私有最终静态记录器Logger=Logger.getLogger(GCM.class.getName());
    私有静态最终字符串API_KEY=ConstantUtil.GCM_API_KEY;
    公共静态void doSendViaGcm(列表tocken,字符串消息)引发IOException{
    发送方=新发送方(API_密钥);
    //如果需要,修剪消息。
    如果(message.length()>1000){
    message=message.substring(0,1000)+“[…]”;
    }
    Message msg=new Message.Builder().addData(“Message”,Message).build();
    试一试{
    multicastersult result=sender.send(msg,tocken,5);
    }捕获(例外)