【问题标题】:Getting offline messages in android chat application with use of asmack library使用 asmack 库在 android 聊天应用程序中获取离线消息
【发布时间】:2023-07-20 10:36:02
【问题描述】:

我正在为我的聊天应用程序使用 asmack 库。我正在使用下面描述的代码来获取消息计数:

ServiceDiscoveryManager manager = ServiceDiscoveryManager.getInstanceFor(connection);
                 DiscoverInfo info = manager.discoverInfo(null,"http://jabber.org/protocol/offline");
                    Form extendedInfo = Form.getFormFrom(info);
                    if (extendedInfo != null) {
                        String value = extendedInfo.getField("number_of_messages").getValues().next();
                        Log.e(TAG, "offline message"+value);


                    }

但我得到了如下所述的异常:

09-14 16:11:32.892: ERROR/AndroidRuntime(498):     at com.datingapps.breaktheice.SigninScreen.coonectToChat(SigninScreen.java:393)
09-14 16:35:20.611: WARN/System.err(538): java.lang.ClassCastException: org.jivesoftware.smack.util.PacketParserUtils$2
09-14 16:35:20.811: WARN/System.err(538):     at org.jivesoftware.smackx.ServiceDiscoveryManager.discoverInfo(ServiceDiscoveryManager.java:608)
09-14 16:35:20.811: WARN/System.err(538):     at com.datingapps.breaktheice.Chat$connectionTask.doInBackground(Chat.java:286)
09-14 16:35:20.811: WARN/System.err(538):     at com.datingapps.breaktheice.Chat$connectionTask.doInBackground(Chat.java:1)
09-14 16:35:20.811: WARN/System.err(538):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
09-14 16:35:20.811: WARN/System.err(538):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
09-14 16:35:20.821: WARN/System.err(538):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
09-14 16:35:20.821: WARN/System.err(538):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
09-14 16:35:20.821: WARN/System.err(538):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
09-14 16:35:20.821: WARN/System.err(538):     at java.lang.Thread.run(Thread.java:1096)

任何使用 asmack 实现它或使用 smack lib 替代解决方案的人, 请帮我解决这个问题。

【问题讨论】:

    标签: android asmack


    【解决方案1】:

    在谷歌搜索和搜索文档后,我得到了用于获取离线消息的离线管理器。

    但是它在 asmack 中不起作用或可能在 smack 中。它总是返回 0 消息。

    最后通过查看日志,我发现每次登录时我都收到了来自聊天服务器的很多响应,其中还包含离线消息,但带有消息标签而不是离线消息标签。所以我终于找到了

    您可以通过在登录后直接设置数据包侦听器从中获取离线消息。如下所述,您必须在登录方法后实现数据包侦听器。

            PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
            this.connection.addPacketListener(new PacketListener() {
                public void processPacket(Packet packet) {
    
                    Message message = (Message) packet;
                    if (message.getBody() != null) {
                        String fromName = StringUtils.parseBareAddress(message
                                .getFrom());
                        Log.i("XMPPClient", "Got text [" + message.getBody()
                                + "] from [" + fromName + "]");
                        if (fromName.equalsIgnoreCase(matchUserJabberId
                                + "server name")) {
    
    
                            // }
                        }
                    }
                }
            }, filter);
    

    希望它能帮助许多人尽早找到解决离线消息的方法,因为我投入了更多时间来解决它。

    【讨论】:

    • 抱歉,我仍然没有收到离线消息。
    • @chirag。你能帮我吗?我也在寻找同样的东西。我已经检查过了,我在日志猫中收到了离线消息,但我无法将它通知给用户???当我在进程包部分编写通知代码时,我注意到上面的代码甚至在应用程序启动时都没有执行???登录后,这段代码运行良好,但我也想在离线消息的情况下使用它。我该怎么做呢
    • 我已经编写了与上面相同的代码,但我仍然没有收到离线消息。有时它会收到但有些消息没有收到。
    • @BorntoWin 确保您在登录前添加了数据包侦听器。登录后不久就会收到离线消息。
    • @chikka.anddeve 我已经实现了同样的事情只是唱群聊但收不到任何消息
    【解决方案2】:

    用这个替换你的代码。我已使用此代码运行良好。

    public int offlinemessagecount(){
        try {
    
            ServiceDiscoveryManager manager = ServiceDiscoveryManager
                    .getInstanceFor(connection);
            DiscoverInfo info = manager.discoverInfo(null,
                    "http://jabber.org/protocol/offline");
            Form extendedInfo = Form.getFormFrom(info);
            if (extendedInfo != null) {
                String value = extendedInfo.getField("number_of_messages")
                        .getValues().next();
    
                return Integer.parseInt(value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    
    }
    

    【讨论】:

      【解决方案3】:

      GTalkSMS 是使用 Asmack lib 的每个基本操作的好例子,下面是我从 GTalkSMS 项目中获取离线消息的小示例代码。

      public static void handleOfflineMessages(XMPPConnection connection, Context ctx)throws Exception {
              OfflineMessageManager offlineMessageManager = new OfflineMessageManager(connection);
      
              if (!offlineMessageManager.supportsFlexibleRetrieval()) {
                  Log.d("Offline messages not supported");
                  return;
              }
      
              if (offlineMessageManager.getMessageCount() == 0) {
                  Log.d("No offline messages found on server");
              } else {
                  List<Message> msgs = offlineMessageManager.getMessages();
                  for (Message msg : msgs) {
                      String fullJid = msg.getFrom();
                      String bareJid = StringUtils.parseBareAddress(fullJid);
                      String messageBody = msg.getBody();
                      if (messageBody != null) {
                          Log.d("Retrieved offline message from " +messageBody);
                      }
                  }
                  offlineMessageManager.deleteMessages();
              }
          }
      

      【讨论】:

        【解决方案4】:

        尝试用这个替换你的代码。

        ProviderManager mgr = ProviderManager.getInstance();
        mgr.addExtensionProvider(offline, http://jabber.org/protocol/offline, org.jivesoftware.smackx.packet.OfflineMessageInfo$Provider);
        mgr.addIQProvider(offline, http://jabber.org/protocol/offline, org.jivesoftware.smackx.packet.OfflineMessageRequest$Provider);
        
        OfflineMessageManager offMgr = new OfflineMessageManager(connection);
        int numOffline = offMgr.getMessageCount();
        

        【讨论】:

        • 感谢您的回复。我已经使用了您的代码,但现在我在 logcat:09-20 07:25:07.600: WARN/System.err(1100): java .lang.ClassCastException: org.jivesoftware.smack.util.PacketParserUtils$2 09-20 07:25:07.600: WARN/System.err(1100): at org.jivesoftware.smackx.ServiceDiscoveryManager.discoverInfo(ServiceDiscoveryManager.java:608) 09-20 07:25:07.600: WARN/System.err(1100): at org.jivesoftware.smackx.OfflineMessageManager.getMessageCount(OfflineMessageManager.java:92)
        • 我也有和 chirag shah 一样的问题
        • 我也得到了相同的类转换异常
        【解决方案5】:

        只是检查一下,您是否配置了您的 smack 提供程序?

        在建立连接之前,应该调用这个

        SmackAndroid.init(mContext);    // this loads extension providers into aSmack
        try { 
            conn.connect();
        } catch (XMPPException e) {
            e.printStackTrace();
            // do something
        }
        

        不调用这个,你肯定会得到

        【讨论】:

          【解决方案6】:

          如果您不想自动获取离线消息 (XEP-0013),请仅使用 OfflineMessageManager。

          否则只需将您的 StanzaListener 添加到连接并登录。

              XMPPTCPConnectionConfiguration userBasicConfiguration = XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
                      .setServiceName(SERVICE_NAME)
                      .setHost(HOST_NAME)
                      .setDebuggerEnabled(false)
                      .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
                      .setPort(PORT)
                      .setUsernameAndPassword(userName, password)
                      .build();
              AbstractXMPPConnection firstUserConnection = new XMPPTCPConnection(userBasicConfiguration);
              firstUserConnection.connect();
              StanzaFilter filter = new StanzaTypeFilter(Message.class);
              StanzaListener listener = stanza -> {
                  System.out.println(stanza.toString());
              };
              firstUserConnection.addSyncStanzaListener(listener,filter);
              firstUserConnection.login();
              while (!Thread.currentThread().isInterrupted()){
          
              }
              firstUserConnection.disconnect();
          

          【讨论】: