使用Smack 4.1的XMPP客户端在登录期间出现空指针异常

26

我正在尝试使用Smack 4.1.0-rc3实现一个Java XMPP客户端,连接到ejabberd XMPP服务器。我正在使用以下代码连接到服务器。

    XMPPTCPConnectionConfiguration connConfig =    XMPPTCPConnectionConfiguration
            .builder()
            .setServiceName("example.com")
            .setHost("192.168.56.101")
            .setPort(5222)
            .setCompressionEnabled(false)
            .setSecurityMode(SecurityMode.disabled)
            .setHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }
            })
            .setUsernameAndPassword(user, pass).build();

    connection = new XMPPTCPConnection(connConfig);
    connection.connect();
    connection.login();

在执行 'connection.login()' 时,我遇到了以下NullPointerException。

Exception in thread "main" java.lang.NullPointerException
at org.jivesoftware.smack.util.stringencoder.Base64.encode(Base64.java:64)
at org.jivesoftware.smack.util.stringencoder.Base64.encode(Base64.java:60)
at org.jivesoftware.smack.util.stringencoder.Base64.encodeToString(Base64.java:42)
at org.jivesoftware.smack.sasl.SASLMechanism.authenticate(SASLMechanism.java:199)
at org.jivesoftware.smack.sasl.SASLMechanism.authenticate(SASLMechanism.java:169)
at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:236)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.loginNonAnonymously(XMPPTCPConnection.java:365)
at org.jivesoftware.smack.AbstractXMPPConnection.login(AbstractXMPPConnection.java:452)
at org.jivesoftware.smack.AbstractXMPPConnection.login(AbstractXMPPConnection.java:410)
at org.org.oodlezz.unio.jabber.client.XmppClient.connect(XmppClient.java:88)
at org.org.oodlezz.unio.jabber.client.Client.main(Client.java:32)

我的代码哪里出了问题?你能否给我一个使用Smack 4.1.0-rc3的正确示例?

6个回答

38

此页面上的其他答案有部分答案,但在尝试它们后,我发现真正缺少的是对smack-java7库的依赖。添加此依赖项将导致初始化程序被调用,base64encoder被设置,因此这个NullPointerException消失。

在Android上,将smack-java7替换为smack-android。


1
这对我有效,无需进一步初始化。只需将依赖项添加到smack-java7即可。 - codewandler
谢谢,它像魔法一样奏效了...我已经思考了几个小时,不知道自己到底做错了什么。 - Ninad
可以了,谢谢。我一直在想为什么Smack没有明确地提到这个依赖关系,毕竟它是一个依赖项。 - Manish Kumar Sharma

6
您的代码没问题,但可能需要正确的依赖项。您可以将以下内容放在您的pom.xml文件中。
<dependencies>
    <dependency>
        <groupId>org.igniterealtime.smack</groupId>
        <artifactId>smack-java7</artifactId>
        <version>4.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.igniterealtime.smack</groupId>
        <artifactId>smack-tcp</artifactId>
        <version>4.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.igniterealtime.smack</groupId>
        <artifactId>smack-im</artifactId>
        <version>4.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.igniterealtime.smack</groupId>
        <artifactId>smack-extensions</artifactId>
        <version>4.1.1</version>
    </dependency>
</dependencies>

这是基于以下内容:https://github.com/igniterealtime/Smack/wiki/Smack-4.1-Readme-and-Upgrade-Guide 您可以使用所需的Smack版本。
如果您不熟悉maven的一些基本步骤,这可能对您有用:https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html 希望这能帮到您!

3

正如Stephen所建议的那样,Base64encoder确实为null,因为它没有被设置。要初始化它,您需要在项目中包含smack-java7模块。

在连接之前,您必须使用以下方式初始化smack:

new Java7SmackInitializer().initialize();

对于Android,我相信您可以通过以下方式实现:

new AndroidSmackInitializer().initialize();

2
你不需要手动进行初始化,一旦你配置了正确的依赖项,Smack会自动完成它。 - Flow

1
我正在使用4.1.0-rc3版本。在我的情况下,我没有遇到NPE。示例可以正常工作。
以下是pom.xml的一部分。

pom.xml

<properties>
    <smack.version>4.1.0-rc3</smack.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.igniterealtime.smack</groupId>
        <artifactId>smack-core</artifactId>
        <version>${smack.version}</version>
    </dependency>
    <dependency>
        <groupId>org.igniterealtime.smack</groupId>
        <artifactId>smack-tcp</artifactId>
        <version>${smack.version}</version>
    </dependency>
    <dependency>
        <groupId>org.igniterealtime.smack</groupId>
        <artifactId>smack-java7</artifactId>
        <version>${smack.version}</version>
    </dependency>
...
</dependencies>
...

一个示例代码只是这样的,
AbstractXMPPConnection conn = new XMPPTCPConnection("xxx", "yyy", "zzz");

conn.connect();
conn.login();

关键在于依赖于smack-java7。这就是帮助我的东西。 - Noam Ben Ari

1
我在安卓上也遇到了这个问题... 我的问题是通过更改库的安卓版本来解决的... 所以,在 path/to/your/android-project/build.gradle 上, 删除以下内容:

compile "org.igniterealtime.smack:smack-java7:4.1.4"

并添加以下内容:

compile "org.igniterealtime.smack:smack-android:4.1.4"


0

当网络不可用且我没有与XMPP建立任何连接时,我会遇到空指针异常。因此,在smack中没有从任何地方初始化Base64。在这种情况下,我需要手动使用以下方法初始化SmackInitializer:

new AndroidSmackInitializer().initialize(); // Add this single line for initialization

这一行代码调用了Smack库中的AndroidSmackInitializer类的initialize()方法:

public class AndroidSmackInitializer implements SmackInitializer {

    @Override
    public List<Exception> initialize() {
        SmackConfiguration.setDefaultHostnameVerifier(new StrictHostnameVerifier());
        Base64.setEncoder(AndroidBase64Encoder.getInstance());
        Base64UrlSafeEncoder.setEncoder(AndroidBase64UrlSafeEncoder.getInstance());
        return null;
    }

} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接