我正在开发一个我正在实现聊天功能的 Android 应用程序。考虑到 Cometd 的使用,聊天速度非常快,但出于某种原因,Cometd 正在发送替代消息。如果它发送 message-1,它不发送 message-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);
}
控制台聊天客户端:
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
日志图像: