android中的XMPP连接使用smack

Posted

技术标签:

【中文标题】android中的XMPP连接使用smack【英文标题】:XMPP connection in android using smack 【发布时间】:2015-09-01 10:00:38 【问题描述】:

我在运行代码时收到此错误。我正在使用 smack 3.1.0 和 smackx3.1.0 以及 smack 的 android 扩展(smack-android-4.1.0-alpha6)

09-01 15:28:37.430: E/NativeCrypto(9558): ssl=0x670ec948 cert_verify_callback x509_store_ctx=0x6790a938 arg=0x0
09-01 15:28:37.431: E/NativeCrypto(9558): ssl=0x670ec948 cert_verify_callback calling verifyCertificateChain authMethod=DHE_RSA
09-01 15:28:38.267: E/AndroidRuntime(9558): FATAL EXCEPTION: AsyncTask #6
09-01 15:28:38.267: E/AndroidRuntime(9558): Process: com.example.xmppkoderootapp, PID: 9558
09-01 15:28:38.267: E/AndroidRuntime(9558): java.lang.RuntimeException: An error occured while executing doInBackground()
09-01 15:28:38.267: E/AndroidRuntime(9558):     at android.os.AsyncTask$3.done(AsyncTask.java:300)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.lang.Thread.run(Thread.java:841)
09-01 15:28:38.267: E/AndroidRuntime(9558): Caused by: java.lang.VerifyError: org/jivesoftware/smack/sasl/SASLMechanism
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.lang.reflect.Constructor.constructNative(Native Method)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:304)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:395)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:349)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at com.example.xmppkoderootapp.SettingsDialog$LongOperation.doInBackground(SettingsDialog.java:69)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at com.example.xmppkoderootapp.SettingsDialog$LongOperation.doInBackground(SettingsDialog.java:1)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at android.os.AsyncTask$2.call(AsyncTask.java:288)
09-01 15:28:38.267: E/AndroidRuntime(9558):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
09-01 15:28:38.267: E/AndroidRuntime(9558):     ... 4 more

这是我的代码

SettingsDialog.java

package com.example.xmppkoderootapp;

import android.app.Dialog;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;

/**
 * Gather the xmpp settings and create an XMPPConnection
 */
public class SettingsDialog extends Dialog implements android.view.View.OnClickListener 
    private XMPPClient xmppClient;

    public SettingsDialog(XMPPClient xmppClient) 
        super(xmppClient);
        this.xmppClient = xmppClient;
    

    protected void onStart() 
        super.onStart();
        setContentView(R.layout.settings);
        getWindow().setFlags(4, 4);
        setTitle("XMPP Settings");
        Button ok = (Button) findViewById(R.id.ok);
        ok.setOnClickListener(this);
    

    public void onClick(View v) 
        String host = getText(R.id.host);
        String port = getText(R.id.port);
        String service = getText(R.id.service);
        String username = getText(R.id.userid);
        String password = getText(R.id.password);
        new LongOperation().execute("im.koderoot.net","5222","im.koderoot.net","xxxx@im.koderoot.net","xxxx");

        dismiss();
    

    private String getText(int id) 
        EditText widget = (EditText) this.findViewById(id);
        return widget.getText().toString();
    

    private class LongOperation extends AsyncTask<String, Void, String> 

        @Override
        protected String doInBackground(String... params) 
            // Create a connection
             // Create a connection
            ConnectionConfiguration connConfig =
                    new ConnectionConfiguration(params[0], Integer.parseInt(params[1]), params[2]);
            XMPPConnection connection = new XMPPConnection(connConfig);

            try 
                connection.connect();
                Log.i("XMPPClient", "[SettingsDialog] Connected to " + connection.getHost());
             catch (XMPPException ex) 
                Log.e("XMPPClient", "[SettingsDialog] Failed to connect to " + connection.getHost());
                Log.e("XMPPClient", ex.toString());
                xmppClient.setConnection(null);
            
            try 
                connection.login(params[3], params[4]);
                Log.i("XMPPClient", "Logged in as " + connection.getUser());

                // Set the status to available
                Presence presence = new Presence(Presence.Type.available);
                connection.sendPacket(presence);
                xmppClient.setConnection(connection);
             catch (XMPPException ex) 
                Log.e("XMPPClient", "[SettingsDialog] Failed to log in as " + params[3]);
                Log.e("XMPPClient", ex.toString());
                    xmppClient.setConnection(null);
            

            return "Executed";
        

        @Override
        protected void onPostExecute(String result) 
            Log.e("In onpost execute ", "Success");
            // TextView txt = (TextView) findViewById(R.id.output);
            //txt.setText("Executed"); // txt.setText(result);
            // might want to change "executed" for the returned string passed
            // into onPostExecute() but that is upto you
        

        @Override
        protected void onPreExecute() 

        @Override
        protected void onProgressUpdate(Void... values) 
    

XMPPClient.java

package com.example.xmppkoderootapp;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.MessageTypeFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.StringUtils;

import java.util.ArrayList;

public class XMPPClient extends Activity 

    private ArrayList<String> messages = new ArrayList();
    private Handler mHandler = new Handler();
    private SettingsDialog mDialog;
    private EditText mRecipient;
    private EditText mSendText;
    private ListView mList;
    private XMPPConnection connection;

    /**
     * Called with the activity is first created.
     */
    @Override
    public void onCreate(Bundle icicle) 
        super.onCreate(icicle);
        Log.i("XMPPClient", "onCreate called");
        setContentView(R.layout.main);

        mRecipient = (EditText) this.findViewById(R.id.recipient);
        Log.i("XMPPClient", "mRecipient = " + mRecipient);
        mSendText = (EditText) this.findViewById(R.id.sendText);
        Log.i("XMPPClient", "mSendText = " + mSendText);
        mList = (ListView) this.findViewById(R.id.listMessages);
        Log.i("XMPPClient", "mList = " + mList);
        setListAdapter();

        // Dialog for getting the xmpp settings
        mDialog = new SettingsDialog(this);

        // Set a listener to show the settings dialog
        Button setup = (Button) this.findViewById(R.id.setup);
        setup.setOnClickListener(new View.OnClickListener() 
            public void onClick(View view) 
                mHandler.post(new Runnable() 
                    public void run() 
                        mDialog.show();
                    
                );
            
        );

        // Set a listener to send a chat text message
        Button send = (Button) this.findViewById(R.id.send);
        send.setOnClickListener(new View.OnClickListener() 
            public void onClick(View view) 
                String to = mRecipient.getText().toString();
                String text = mSendText.getText().toString();

                Log.i("XMPPClient", "Sending text [" + text + "] to [" + to + "]");
                Message msg = new Message(to, Message.Type.chat);
                msg.setBody(text);
                connection.sendPacket(msg);
                messages.add(connection.getUser() + ":");
                messages.add(text);
                setListAdapter();
            
        );
    

    /**
     * Called by Settings dialog when a connection is establised with the XMPP server
     *
     * @param connection
     */
    public void setConnection
            (XMPPConnection
                    connection) 
        this.connection = connection;
        if (connection != null) 
            // Add a packet listener to get messages sent to us
            PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
            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 + "]");
                        messages.add(fromName + ":");
                        messages.add(message.getBody());
                        // Add the incoming message to the list view
                        mHandler.post(new Runnable() 
                            public void run() 
                                setListAdapter();
                            
                        );
                    
                
            , filter);
        
    

    private void setListAdapter
            () 
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                R.layout.multi_line_list_item,
                messages);
        mList.setAdapter(adapter);
    

提前致谢

【问题讨论】:

【参考方案1】:

希望这还不算太晚,错误是指 SASL 验证,我注意到您没有在 doInBackground() 中设置任何相关内容,请在您的 try 块中尝试以下操作(可能不完全是你需要,但这是基本的):

ConnectionConfiguration config = new ConnectionConfiguration(server, port);

//... any other stuff you need

//very basic security stuff just to get you going...
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
XMPPTCPConnection connection = new XMPPTCPConnection(config);
SASLAuthentication.supportSASLMechanism("DIGEST-MD5", 0);
connection.connect();

//... any other stuff you want

connection.login(user, passw);

希望这会有所帮助!

【讨论】:

以上是关于android中的XMPP连接使用smack的主要内容,如果未能解决你的问题,请参考以下文章

无法在android中的xmpp服务器中连接

Android 中的 XMPP 聊天:ChatManager 未解决

xmpp连接Android Studio中的NetworkOnMainThreadException [重复]

XMPP android中的连接因错误而关闭

单独线程中的 XMPP 连接 - 仍然被 Android 操作系统关闭?

如何将 xmpp 侦听器添加到 android 中的服务?