Android, Cometd: Cometd отправляет альтернативные сообщения

Я работаю над приложением для Android, в котором реализую функциональность чата. Чат довольно быстрый, учитывая использование Cometd, но по какой-то причине Cometd отправляет альтернативные сообщения. Если он отправляет сообщение-1, он не отправляет сообщение-2, затем отправляется 3, и так далее, и тому подобное. Это очень странное поведение, и проблему трудно изолировать, так как ошибки нет.

Я добавил системные журналы, чтобы проверить, вызывается ли метод onClick и цикл, внутри которого отправляется сообщение. Кроме того, я добавил system.out в код на стороне сервера, и принимаются только альтернативные сообщения. Это привело к выводу, что Cometd каким-то образом не отправляет каждое альтернативное сообщение. Любая помощь будет приятно. Спасибо.

Обратите внимание, что служба PUSH предоставляется Cometd, которая создается в ConsoleChatClient.java.

Код :

public class ChatMessagesActivity extends ApplicationDrawerLoader {

 HttpClient httpClient;
 ConsoleChatClient consoleChatClient;

 @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, ConsoleChatClient.class);
        bindService(intent, mConnection, Context.BIND_IMPORTANT);
    }

    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                                       IBinder service) {
            ConsoleChatClient.LocalBinder binder = (ConsoleChatClient.LocalBinder) service;
            consoleChatClient = binder.getService();
            mBound = true;
            onConsoleChatClientReady();
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };


    private void onConsoleChatClientReady() {
        httpClient = consoleChatClient.httpClient;
        subscribeFlag = true;
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            groupAccountId = extras.getLong("groupid");
            conversationId = extras.getInt("conversationid");
        }

        if (conversationId != 0) {
            consoleChatClient.bayeuxClient.getChannel("/person/" + conversationId).subscribe(chatListener);
        }

        if (groupAccountId != 0) {
            consoleChatClient.bayeuxClient.getChannel("/chat/" + groupAccountId).subscribe(chatListener);
        }
    }
sendMessageButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
// method below sends the message, and it does so for every //alternate message precisely. 
  Log.d("We","groupmessage");
Map<String, Object> outputData = new HashMap<>();
                    outputData.put("name", typeMessageField.getText().toString());
                    outputData.put("timestamp", new Timestamp(System.currentTimeMillis()));
                    outputData.put("type", false);
                    consoleChatClient.bayeuxClient.getChannel("/service/chat/" + String.valueOf(groupAccountId)).publish(outputData);
}

ConsoleChatClient :

public class ConsoleChatClient extends Service {

    private final IBinder mBinder = new LocalBinder();
    BayeuxClient bayeuxClient = StaticRestTemplate.getClient();
    HttpClient httpClient = StaticRestTemplate.getHttpClient();
    String defaultURL = StaticRestTemplate.baseURL + "/cometd";


    public class LocalBinder extends Binder {
        ConsoleChatClient getService() {
            // Return this instance of LocalService so clients can call public methods
            return ConsoleChatClient.this;
        }
    }

    private void connectionEstablished() {
        System.err.printf("system: Connection to Server Opened%n");

    }

    private void connectionClosed() {
        System.err.printf("system: Connection to Server Closed%n");
    }

    private void connectionBroken() {
        System.err.printf("system: Connection to Server Broken%n");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        performConnection();
    }

    @Override
    public IBinder onBind(Intent intent) {
        performConnection();
        return mBinder;

    }

    private void performConnection() {
        try {
            httpClient.start();
            ClientTransport clientTransport = new LongPollingTransport(null, httpClient);
            bayeuxClient = new BayeuxClient(defaultURL, clientTransport);
            // Below for use with Spring-Security post-login.
            bayeuxClient.putCookie(new HttpCookie("JSESSIONID", StaticRestTemplate.getJsessionid()));
            bayeuxClient.getChannel(Channel.META_HANDSHAKE).addListener(new InitializerListener());
            bayeuxClient.getChannel(Channel.META_CONNECT).addListener(new ConnectionListener());
            bayeuxClient.handshake();
            StaticRestTemplate.setClient(bayeuxClient);
            StaticRestTemplate.setHttpClient(httpClient);
            boolean success = bayeuxClient.waitFor(2000, BayeuxClient.State.CONNECTED);
            if (!success) {
                System.err.printf("Could not handshake with server at %s%n", defaultURL);
            }else {
                System.err.printf("Handhskare complete");
            }

        } catch (Exception ignored) {}
    }

    private class InitializerListener implements ClientSessionChannel.MessageListener {
        @Override
        public void onMessage(ClientSessionChannel channel, Message message) {
            if (message.isSuccessful()) {
                System.out.println("Message successful");
            }
        }
    }

    private class ConnectionListener implements ClientSessionChannel.MessageListener {
        private boolean wasConnected;
        private boolean connected;

        public void onMessage(ClientSessionChannel channel, Message message) {
            if (bayeuxClient.isDisconnected()) {
                connected = false;
                connectionClosed();
                return;
            }
            wasConnected = connected;
            connected = message.isSuccessful();
            if (!wasConnected && connected) {
                connectionEstablished();
            } else if (wasConnected && !connected) {
                connectionBroken();
            }
        }
    }
}
public class ConsoleChatClient extends Service {

    private final IBinder mBinder = new LocalBinder();
    BayeuxClient bayeuxClient = StaticRestTemplate.getClient();
    HttpClient httpClient = StaticRestTemplate.getHttpClient();
    String defaultURL = StaticRestTemplate.baseURL + "/cometd";


    public class LocalBinder extends Binder {
        ConsoleChatClient getService() {
            // Return this instance of LocalService so clients can call public methods
            return ConsoleChatClient.this;
        }
    }

    private void connectionEstablished() {
        System.err.printf("system: Connection to Server Opened%n");

    }

    private void connectionClosed() {
        System.err.printf("system: Connection to Server Closed%n");
    }

    private void connectionBroken() {
        System.err.printf("system: Connection to Server Broken%n");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        performConnection();
    }

    @Override
    public IBinder onBind(Intent intent) {
        performConnection();
        return mBinder;

    }

    private void performConnection() {
        try {
            httpClient.start();
            ClientTransport clientTransport = new LongPollingTransport(null, httpClient);
            bayeuxClient = new BayeuxClient(defaultURL, clientTransport);
            // Below for use with Spring-Security post-login.
            bayeuxClient.putCookie(new HttpCookie("JSESSIONID", StaticRestTemplate.getJsessionid()));
            bayeuxClient.getChannel(Channel.META_HANDSHAKE).addListener(new InitializerListener());
            bayeuxClient.getChannel(Channel.META_CONNECT).addListener(new ConnectionListener());
            bayeuxClient.handshake();
            StaticRestTemplate.setClient(bayeuxClient);
            StaticRestTemplate.setHttpClient(httpClient);
            boolean success = bayeuxClient.waitFor(2000, BayeuxClient.State.CONNECTED);
            if (!success) {
                System.err.printf("Could not handshake with server at %s%n", defaultURL);
            }else {
                System.err.printf("Handhskare complete");
            }

        } catch (Exception ignored) {}
    }

    private class InitializerListener implements ClientSessionChannel.MessageListener {
        @Override
        public void onMessage(ClientSessionChannel channel, Message message) {
            if (message.isSuccessful()) {
                System.out.println("Message successful");
            }
        }
    }

    private class ConnectionListener implements ClientSessionChannel.MessageListener {
        private boolean wasConnected;
        private boolean connected;

        public void onMessage(ClientSessionChannel channel, Message message) {
            if (bayeuxClient.isDisconnected()) {
                connected = false;
                connectionClosed();
                return;
            }
            wasConnected = connected;
            connected = message.isSuccessful();
            if (!wasConnected && connected) {
                connectionEstablished();
            } else if (wasConnected && !connected) {
                connectionBroken();
            }
        }
    }
}

Код со счетчиком: счетчик инициализирован 0.

Map<String, Object> outputData = new HashMap<>();
                    outputData.put("name", typeMessageField.getText().toString());
                    outputData.put("timestamp", new Timestamp(System.currentTimeMillis()));
                    outputData.put("type", "false");
                    outputData.put("counter",counter);
                    counter++;
                    try {
                        if(consoleChatClient.httpClient.isStarted()) {
                            consoleChatClient.bayeuxClient.getChannel("/service/chat/" + String.valueOf(groupAccountId)).publish(outputData);
                            Log.d("Android, counter",String.valueOf(counter));
                        }else {
                            consoleChatClient.httpClient.start();
                            Log.d("Client","not started");
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }

Печать счетчика на стороне сервера:

  @Listener("/service/chat/{id}")
    public void processHello(ServerSession remote, ServerMessage message, @Param("id") String id) {

        System.out.println("I was called"+message.toString());
// Other code
}

Журналы андроида:

04-04 10:30:11.465 2047-2271/mycompany.app I/System.out: Message successful
04-04 10:30:11.485 2047-2265/mycompany.app W/System.err: system: Connection to Server Opened
04-04 10:30:11.585 2047-2266/mycompany.app I/System.out: Message successful
04-04 10:30:11.697 2047-2270/mycompany.app W/System.err: Handhskare completesystem: Connection to Server Opened
04-04 10:30:11.720 2047-2047/mycompany.app I/Choreographer: Skipped 41 frames!  The application may be doing too much work on its main thread.
04-04 10:30:13.738 2047-2047/mycompany.app W/Settings: Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, returning read-only value.
04-04 10:30:19.394 2047-2047/mycompany.app D/Android, counter: 1
04-04 10:30:29.557 2047-2047/mycompany.app D/Android, counter: 2
04-04 10:30:51.787 2047-2047/mycompany.app D/Android, counter: 3
04-04 10:31:05.414 2047-2047/mycompany.app D/Android, counter: 4
04-04 10:31:15.590 2047-2047/mycompany.app D/Android, counter: 5
04-04 10:31:26.513 2047-2047/mycompany.app D/Android, counter: 6
04-04 10:31:32.510 2047-2047/mycompany.app D/Android, counter: 7
04-04 10:31:43.192 2047-2047/mycompany.app D/Android, counter: 8
04-04 10:31:49.566 2047-2047/mycompany.app D/Android, counter: 9

Журналы на стороне сервера:

I was called{clientId=412fqdbm458ip31je6r676za42t, data={name=hello, counter=1, type=false, timestamp=2016-04-04 10:30:29.547}, channel=/service/chat/5250, id=9}
Authenticated user is AKSHAY
I was called{clientId=412fqdbm458ip31je6r676za42t, data={name=wassup, counter=2, type=false, timestamp=2016-04-04 10:30:51.78}, channel=/service/chat/5250, id=12}
Authenticated user is AKSHAY
I was called{clientId=412fqdbm458ip31je6r676za42t, data={name=yoyo, counter=4, type=false, timestamp=2016-04-04 10:31:15.583}, channel=/service/chat/5250, id=16}
Authenticated user is AKSHAY
I was called{clientId=412fqdbm458ip31je6r676za42t, data={name=hhhh, counter=6, type=false, timestamp=2016-04-04 10:31:32.501}, channel=/service/chat/5250, id=18}
Authenticated user is AKSHAY
I was called{clientId=412fqdbm458ip31je6r676za42t, data={name=hhhhh, counter=8, type=false, timestamp=2016-04-04 10:31:49.557}, channel=/service/chat/5250, id=22}
Authenticated user is AKSHAY

Изображения журнала:

введите здесь описание изображения

введите здесь описание изображения

введите здесь описание изображения


person We are Borg    schedule 31.03.2016    source источник
comment
Я сомневаюсь, что это проблема CometD, так как многие другие без проблем используют CometD на Android. Нет никаких доказательств (как в операторах журнала), которые показывают поведение, которое вы описываете, и сообщения, которые вы отправляете, не имеют счетчика, чтобы можно было определить, отправляются ли нечетные сообщения, а сообщения о событиях - нет. Скорее всего у вас проблема в другом. Попробуйте удалить код, пока не заработаете минимальный CometD, а затем снова начните добавлять код.   -  person sbordet    schedule 01.04.2016
comment
@sbordet: это всего 4-5 строк кода, где я создаю карту и отправляю сообщение. Я вижу как сообщения Log.d, так и прослушиватель на стороне сервера имеет System.out, где снова я могу видеть, приходит ли сообщение, и приходит ли точно альтернативное сообщение ... Это я подтвердил, и мой коллега тоже. Обрезать код до минимума для любой или всех проблем не имеет смысла, интеграция является важным аспектом любого проекта, ее нельзя игнорировать...   -  person We are Borg    schedule 01.04.2016
comment
@sbordet: я отладил код и обнаружил, что метод toString не работает. Я добавил изображения для него в основной пост, если вам нужна какая-либо другая информация от отладчика, пожалуйста, дайте мне знать. Спасибо.. :-)   -  person We are Borg    schedule 01.04.2016
comment
@sbordet: обратите внимание на код, размещенный внизу изображения, если httpClient не запущен, я запускаю его и печатаю журнал. И, как я уже знал, ни разу сообщение журнала не было напечатано, а альтернативное сообщение все еще продолжалось.   -  person We are Borg    schedule 01.04.2016
comment
Мне непонятно, что вы имеете в виду под альтернативой. Если у вас есть счетчик, это не очевидно из того, что вы разместили здесь. Если у вас нет счетчика, вам нужно лучше объяснить, что вы подразумеваете под альтернативой. NPE, который вы нашли в toString(), возможен только в том случае, если null ChannelId передается конструктору канала. CometD никогда этого не делает.   -  person sbordet    schedule 01.04.2016
comment
@sbordet: Как вы сказали, я добавил счетчик к отправляемым данным и зарегистрировал их. Я загрузил изображения, код и журнал внизу основного сообщения. Надеюсь, это поможет. Пожалуйста, дайте мне знать. Спасибо. :-)   -  person We are Borg    schedule 04.04.2016
comment
Две вещи, которые нужно попробовать: 1) работает ли ваш код в среде, отличной от Android? 2) Работает ли ваш код в Android, если вы используете Jetty вместо Tomcat?   -  person sbordet    schedule 06.04.2016
comment
@sbordet: 1) Код на стороне сервера работает без проблем и с API-интерфейсом JavaScript во внешнем интерфейсе, как это связано с Android, я не понимаю. 2) Та же проблема с Jetty, это было первое, что мы попробовали. .. Вы не были уверены, что он отправляет альтернативные сообщения, теперь вы знаете... Если вы знаете каких-либо разработчиков Cometd, не могли бы вы поделиться с ними этим вопросом.. Спасибо.. :-)   -  person We are Borg    schedule 06.04.2016