繁体   English   中英

通过Smack 4.2.0建立XMPP连接时出现NullPointerException

[英]NullPointerException when making XMPP connection through Smack 4.2.0

我打算使用Smack通过Firebase CCS发送消息。 我为我的Web应用程序修改了一个简单的CCS客户端,但是当我尝试建立连接时,它会导致异常。 我正在使用Smack 4.2.0

这是连接过程。

1)在我的客户端中的连接方法:

public void connect() throws XMPPException{
        try{
            config = XMPPTCPConnectionConfiguration.builder()
                    .setPort(Config.FCM_PORT)
                    .setHost("fcm-xmpp.googleapis.com")
                    .setXmppDomain("googleapis.com")
                    .setSecurityMode(/*Default; Explicit setting for emphasis*/SecurityMode.ifpossible)
                    .setSendPresence(true)
                    .setUsernameAndPassword(fcmServerUsername, mApiKey)
                    .setSocketFactory(SSLSocketFactory.getDefault())
                    .setDebuggerEnabled(mDebuggable)/* Launch a window with info about packets sent and received */
                    .build();
        }
        catch(XmppStringprepException e){
            e.printStackTrace();
        }

        connection = new XMPPTCPConnection(config);


        // Configuring Automatic reconnection
        ReconnectionManager manager = ReconnectionManager.getInstanceFor(connection);
        manager.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
        manager.enableAutomaticReconnection();

        // Connect now then login
        try{
            connection.connect();
            connection.login();
        }
        // TODO: Handle the exceptions if possible appropriately
        catch(SmackException sme){
            logger.severe(sme.getMessage());
            sme.printStackTrace();
        }
        catch(IOException ioe){
            logger.severe(ioe.getMessage());
            ioe.printStackTrace();
        }
        catch(InterruptedException ie){
            logger.severe("Connection got interrupted!!");
            ie.printStackTrace();
        }
    }

2)我跟踪了异常,并在这里得到了:(Smack的来源)

在此行HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());

// AbstractXMPPConnection.java
protected List<HostAddress> populateHostAddresses() {
        List<HostAddress> failedAddresses = new LinkedList<>();
        if (config.hostAddress != null) {
            hostAddresses = new ArrayList<>(1);
            HostAddress hostAddress = new HostAddress(config.port, config.hostAddress);
            hostAddresses.add(hostAddress);
        }
        else if (config.host != null) {
            hostAddresses = new ArrayList<HostAddress>(1);
            HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
            if (hostAddress != null) {
                hostAddresses.add(hostAddress);
            }
        } else {
            // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
            hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
        }
        // Either the populated host addresses are not empty *or* there must be at least one failed address.
        assert(!hostAddresses.isEmpty() || !failedAddresses.isEmpty());
        return failedAddresses;
    }

例外是NullPointerException ,我发现getDNSResolver()返回null。 在我引用的所有来源中,没有任何与DNS解析器相关的内容,因为它应该由Smack内部处理。 所以我的问题是,是否错过了一些关键的配置或建立连接的步骤?

编辑:我在这里问,因为Smack是巨大的库,可能有人知道我可能错过了一些配置。 我无法直接设置DNSResolver

编辑:答案更新

这不是Smack来源中的错误,因为他们的4.2.0升级指南明确提到:

**

API变更

**

警告 :此列表可能不完整

引入了ConnectionConfiguration.setHostAddress(InetAddress)

在以前版本的Smack中,可以使用ConnectionConfiguration.setHost(String)设置XMPP服务的主机IP地址。 由于添加了DNSSEC支持,因此不再可能。 您必须改用新的连接配置ConnectionConfiguration.setHostAddress(InetAddress)


这似乎是一个错误,因为我通过提供主机地址(应该从{Host,Domain}推断出)来解决了它。 那么,我怎么知道提供主机地址?

诀窍就在这里:(Smack的来源)

// AbstractXMPPConnection.java

if (config.hostAddress != null) {
            hostAddresses = new ArrayList<>(1);
            HostAddress hostAddress = new HostAddress(config.port, config.hostAddress);
            hostAddresses.add(hostAddress);
        }
        else if (config.host != null) {
            hostAddresses = new ArrayList<HostAddress>(1);
            HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
            if (hostAddress != null) {
                hostAddresses.add(hostAddress);
            }
        } else {
            // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
            hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
        }

您可以在此处看到if,else-if块,并且由于在else if (config.host != null)else if (config.host != null)发生了异常,因此我提供了hostAddress,以便它永远不会进入该块并起作用。

我知道这是针对实际问题的破解,但这似乎是Smack 4.2.0中的错误,除非有人反驳我。

奖励信息:如果更正了此问题,然后在登录期间收到了Base 64编码的另一个异常,请参考此- 使用Smack 4.1的XMPP客户端在登录期间提供NullPointerException

不确定在4.2.0中,但在4.2.2(及更高版本)中,您需要将smack-resolver-dnsjava-4.2.2.jar放入类路径中,如果类没有,则smack调用软件包中包含的DNSUtil不存在,它将返回NullPointerException。

希望对您有所帮助! 大卫

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM