Backend на App Engine с Google Cloud Messaging, изпращащ съобщение до повече от 1000 потребители

Искам да изпратя съобщение (напр. налична актуализация) до всички потребители (~15 000). Внедрих App Engine Backend с Google Cloud Messaging за изпращане на съобщение.

Тествах на 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. Изпращане на насочено известие на множество устройства

Има ли някой, който успешно е внедрил JAVA езика на App Engine+Google Cloud Messaging?

В кодовия ред по-долу, ако заменя 1000 с 15 000 Ще реши ли проблема ми?

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

Моля, помогнете възможно най-скоро. И много съжалявам за моя английски.. Ако някой се нуждае от други подробности, можете да попитате.

Благодаря за отделеното време.


person Programmer    schedule 18.04.2015    source източник
comment
какво се случва, когато стартирате кода, който казвате, че може да работи тогава?   -  person Paul Collingwood    schedule 18.04.2015
comment
@PaulCollingwood Когато стартирам клиентски код на 2 устройства, всички получиха регистрационен идентификатор, тогава изпратих съобщения от appspot.com, всички устройства получиха съобщение. Благодаря.   -  person Programmer    schedule 18.04.2015
comment
Проверете [Моят въпрос/отговор][1] Направих го по този начин, но има нужда от малко тестване [1]: stackoverflow.com/questions/29934331/   -  person George2456    schedule 29.04.2015


Отговори (2)


Няколко съображения,

1) Изпращането на известия до вероятно огромен брой потребители може да отнеме значително време, обмислете използването на опашки със задачи, за да поставите тази работа в опашка за извършване „офлайн“ извън ограничението от 60 секунди.

2) Що се отнася до ограничението на GCM, ако имате нужда от всички ваши потребители, но GCM ви позволява 1000 наведнъж, просто ги разделете на партиди от 1000 и изпратете на всяка партида съобщение отделно.

Ако комбинирате и двете препоръки, трябва да имате доста мащабируем процес, при който правите заявка за всичките си потребители в 1 заявка, разделяте този списък и просто изпращате съобщението на опашка до 1000 потребители наведнъж.

person jirungaray    schedule 18.04.2015
comment
Здравей jirungaray, Благодаря за отговора. Съгласен съм с вашите съображения. Ако можете да ми дадете примерен код, това ще бъде от голяма полза. - person Programmer; 18.04.2015
comment
Имате ли по-просто решение за пакетни заявки за 1000 потребители? Не познавам опашки със задачи. - person Programmer; 18.04.2015
comment
Мога да се сетя за много решения, нито едно по-просто от използването на опашки. Опашките със задачи са основна услуга за GAE и определено трябва да прочетете за тях във връзката, която предоставих. Освен това, ако не прибягвате до опашки или бекенд процеси, приложението ви няма да работи след определен брой потребители. Вече имате кода, просто трябва да преместите изпращащата част в друг сървлет и да зададете опашка за него. Документите ви показват как да направите това за 5 минути. - person jirungaray; 18.04.2015

Разширението на отговора @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();
    }
}

}

В горния кодов фрагмент API_KEY може да бъде получен от проект за конзола на Google, тук предполагам, че вече сте създали един проект за конзола на Google и активирайте GCM api,

можете да генерирате API_KEY, както следва

your_google_console_project>> Идентификационни данни>> Създаване на нов ключ >> Ключ на сървъра >> въведете ip адрес, който искате да разрешите достъп до GCM api[i used 0.0.0.0/0]

Сега doSendViaGcm(List tocken,String message) на GCM клас изпълнява задача за изпращане на съобщения до всички регистрирани мобилни устройства с Android

тук List<String> token is array-list of all device token на кои съобщения ще бъдат доставени, запомнете това list size не трябва повече than 1000 или в противен случай http извикването ще се провали.

надявам се това да ви помогне благодаря

person Dev    schedule 20.04.2015
comment
Здравей, Dev, благодаря ти за приноса. Съжалявам, но не разбирам тази част, която съхранява тези токени на устройства в базата данни. Не съм написал конкретен код за съхраняване на токена на устройството. Както виждам в кода на сървъра на App Engine има файл RegistrationEndpoint.java, състоящ се от registerDevice(),listDevice(). Мисля, че тези методи вече съхраняват регистрационни номера на устройства. Трябва ли да напиша код за същото? Моля, разяснете съмнението ми. - person Programmer; 21.04.2015
comment
Изглежда, че използвате облачна крайна точка в такъв случай listDevice() просто трябва да работи добре, но в такъв случай трябва да извлечете символичен низ от Device Object. Позволете ми да ви попитам откъде ще изпращате GCM съобщения от самия android или от машината на приложението приложение?? - person Dev; 21.04.2015
comment
Използвам HTTP сървър за връзка и за това използвам Google App Engine Backend. Изпращам съобщение от project_id.appspot.com/_ah/api/explorer. - person Programmer; 21.04.2015
comment
така че основно използвате шаблон по подразбиране от project_id.appspot.com/_ah/api/explorer, за да изпратите насочено известие на GCM до клиент на android, мисля, че трябва да създадете една крайна точка и да приложите един метод, който извиква listDevices() в таблицата на устройствата, извлича маркер от обект Device и изпращане на GCM съобщения [бизнес логика] може да искате да извикате тази крайна точка от една от уеб страниците на вашето приложение - person Dev; 21.04.2015
comment
Съжалявам, че ви питам многократно, но съм много нов в App-Engine, всъщност в уеб приложенията. Всъщност приложението ми работи офлайн (така че нямам никакви уеб страници), сега, когато искам да внедря функцията за насочени известия на Google в него. Следвам cloud.google.com/mobile/messaging стъпки. Можете ли да прегледате сървърния код github.com/GoogleCloudPlatform/gradle- appengine-templates/tree/. Моля, предложете ми промените, които трябва да изисквам. Благодаря ви много за подкрепата. - person Programmer; 21.04.2015
comment
Не съм толкова запознат с крайната точка, но използвам горния кодов фрагмент с проект Appengine, използвайки servelt, препратете към тази връзка cloud.google.com/appengine/docs/java/gettingstarted/ui_and_code за повече информация - person Dev; 22.04.2015