Android,Cometd:Cometd 发送备用消息

2024-02-24

我正在开发一个 Android 应用程序,在其中实现聊天功能。考虑到 Cometd 的使用,聊天速度相当快,但由于某种原因,Cometd 正在发送备用消息。如果它发送message-1,则不发送message-2,然后发送3,依此类推。这是一种非常奇怪的行为,并且由于没有错误而很难隔离问题。

我添加了系统日志来检查 onClick 方法是否被调用以及其中的循环是否发送消息。另外,我在服务器端代码中添加了 system.out,并且仅收到备用消息。由此得出的结论是 Cometd 并未发送所有备用消息。你能帮忙的话,我会很高兴。谢谢。

请注意,PUSH 服务由 Cometd 提供,在 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);
}

控制台聊天客户端:

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

日志图像:


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android,Cometd:Cometd 发送备用消息 的相关文章

随机推荐

  • 使用 thrift json 序列化将对象转换为 JSON 字符串

    我是储蓄新手 我需要将我的数据对象转换为JSON string with Thrift JSON序列化 我用这种方式尝试过 TSerializer serializer new TSerializer new TSimpleJSONProt
  • jQuery 方法:.submit() 与 .trigger('submit') 之间的区别

    jQuery 允许通过以下任一方式以编程方式触发表单提交 js form class hook submit js form class hook trigger submit 注 我的理解是 trigger submit is to su
  • C# == 运算符详细做什么?

    在 C 中 当您在两个对象上使用 运算符进行比较时 后台到底发生了什么 它只是比较地址吗 或者是类似 Equals 或 CompareTo 的东西吗 PS java中的 运算符怎么样 它的行为相同吗 据我所知 它按值 相等 比较值类型 它通
  • Clojure:如何在运行时找出函数的数量?

    给定一个函数对象或名称 我如何确定它的数量 就像是 arity func name 我希望有办法 因为 arity 在 Clojure 中非常重要 函数的元数存储在变量的元数据中 arglists meta str x x ys 这要求该函
  • Lisp 中的函数名可以有别名吗?

    就像包裹一样 我使用Emacs 也许 它可以提供某种解决方案 例如 defun the very very long but good name 稍后在代码中没有用处 但名字就像Fn 15或者第一个字母缩写也没有用 是否可以使用类似于包的别
  • Java 静态方法上的线程锁

    根据我对 Java 类的了解 非静态同步方法 在特定对象上获取锁 静态同步方法 在类上获取锁 我对此有点困惑 因为我们可以通过类名或对象名调用静态方法 请假设我的类有 4 个方法都是同步的 2 个方法是静态的 2 个方法不是静态的 如果我创
  • Jquery 在 Href 上创建双击事件

    伙计们是否可以使用 jquery 为 a href 创建双击事件 双击锚点执行操作的问题是 页面将在第一次单击时重定向 从而阻止双击及时响应 如果您想 拦截 点击事件 以便双击事件有机会在页面重定向之前触发 那么您可能必须设置点击超时 如下
  • 如何在 Django 中获取用户 IP 地址?

    如何在 Django 中获取用户的 IP 我有这样的看法 Create your views from django contrib gis utils import GeoIP from django template import Re
  • 如何在 Aurelia 中“继承”可绑定属性?

    我正在使用 TypeScript 开发 Aurelia 应用程序 在此应用程序中 我定义了一组自定义元素 每个元素共享一组可绑定属性 这些属性被转换为 css 设置 如以下简化示例所示 import computedFrom bindabl
  • 在 Azure Linux VM 中,什么仍然存在?什么磁盘收费?

    我在 Microsoft 的 Azure 中创建了一个小型 Linux VM 我还创建了一个 20GB BLOB 并将其安装为文件系统 在我的虚拟机上 我看到以下内容 根文件系统 约28GB 启动文件系统 约500MB 我的 20GB 文件
  • iphone AVEditDemo 或任何视频处理示例

    我正在尝试以某种方式处理视频 剪切和合并视频 录制屏幕并从该录制内容中制作视频 我也在互联网和 stackoverflow 上查找 看到苹果有一个名为 AVEditDemo 的代码示例 但我永远找不到它 如果有人有这个例子并愿意与我分享 或
  • 微软 Roslyn 与 CodeDom

    From a 新闻稿 http www infoworld com d application development microsofts roslyn reinventing the compiler we know it 176671
  • Laravel 5.5 将迁移与生产数据库合并

    希望我能很好地解释这一点 我有一个 Laravel 应用程序 已经投入生产了一分钟 所以 我有一堆包含很多更改的迁移文件 我想合并这些迁移文件而不丢失数据库 我的方式think这会起作用 将所有生产表迁移到所需状态 将所有迁移文件合并为所需
  • 如何列出 mongo shell 中的所有数据库?

    我知道怎么做列出特定数据库中的所有集合 https stackoverflow com questions 8866041 how to list all collections in the mongo shell 但是如何在 Mongo
  • mysqld_safe UNIX 套接字文件的目录“/var/run/mysqld”不存在

    使用 mysqld safe 启动 mysql 服务器 5 7 17 时 出现以下错误 2017 02 10T17 05 44 870970Z mysqld safe Logging to var log mysql error log 2
  • 从 XMLHttpRequest 对象中删除 cookie

    我正在使用 jquery 进行 ajax 调用 例如 ajax url path to webservice asmx beforeSend function xmlHTTPRequest modify headers here remov
  • 分页计算算法

    我正在尝试计算分页 var pagination total result length per page itemsPerPage required current page currentPage required last page
  • 用回形针圆角

    如何用回形针创建圆角 我找到了这个解决方案 它创建了使用convert options用回形针实现圆角 http loo no 2009 08 09 rounded corners with paperclip 但它不适用于 Rails 3
  • 跨浏览器事件对象规范化?

    我正在寻找有关事件对象的事件规范化的良好资源 我想自己做 但我总觉得我会错过一些东西 这是我到目前为止所掌握的 如果我错过了什么 请告诉我 var eFix function e e e window event e target e ta
  • Android,Cometd:Cometd 发送备用消息

    我正在开发一个 Android 应用程序 在其中实现聊天功能 考虑到 Cometd 的使用 聊天速度相当快 但由于某种原因 Cometd 正在发送备用消息 如果它发送message 1 则不发送message 2 然后发送3 依此类推 这是