问题
I am working on an Android application in which I am implementing Chat functionality. The chat is quite fast given the usage of Cometd, but for some reason, Cometd is sending alternate messages. If it sends message-1, it doesn't send message-2, then 3 is sent, so on and so-forth. This is a very strange behaviour and hard to isolate the problem as there is no error.
I added system logs to check if the onClick method is getting called and the loop inside which sends the message. Also, I added a system.out at server-side code, and only alternate messages are received. This lead to the conclusion that Cometd is somehow not sending every alternate message. Any help would be nice. Thank you.
Please note, the PUSH service is provided by Cometd which is instantiated in ConsoleChatClient.java
Code :
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();
}
}
}
}
Code with counter : Counter initialized with 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();
}
Server side printing of counter :
@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
}
Android logs :
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
Server side logs :
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
Log images :
来源:https://stackoverflow.com/questions/36334314/android-cometd-cometd-sending-alternate-messages