Java 应用程序引擎后端与谷歌云消息发送消息给1000多个用户
我想向所有用户(~15000)发送一条消息(例如,更新可用)。我已经实现了发送消息 我在2台设备上进行了测试。两个都有消息。但正如google docs所说,“GCM支持一条消息最多1000个收件人。” 我的问题是如何将相同的消息发送给我的系统中剩余的14000个用户 案例或者下面的代码会处理它 下面是发送消息的代码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
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);
}捕获(例外)