Show me the code! – By Davanum Srinivas

December 31, 2007

Android – Just use Smack API for XMPP

Filed under: Uncategorized — Davanum Srinivas @ 9:36 am

OUTDATED SAMPLE – Updated code is here:


http://davanum.wordpress.com/2008/12/29/updated-xmpp-client-for-android/

Using Smack XMPP API from Android

Once you get tired of the limitations of android’s built-in IMProvider and the corresponding API – IXmppSession and IXmppService, try the sample below. Inside the source/binary zip (bottom of this article) you will find a smack.jar that works with android. To build the jar yourself, You can download the Smack 3.0.4 sources from here and apply the patch here.

Here is a screen shot of the XMPP Settings Dialog.

1

Notes



  • For GTalk, use “gtalk.google.com” as host with port 5222. The service name is “gmail.com”

  • Don’t add “@gmail.com” in the user name, just the id will do

Here’s the code for the settings dialog

package org.apache.android.xmpp;

import android.app.Dialog;
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);

        // Create a connection
        ConnectionConfiguration connConfig =
                new ConnectionConfiguration(host, Integer.parseInt(port), service);
        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());
            xmppClient.setConnection(null);
        }
        try {
            connection.login(username, password);
            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 " + username);
            xmppClient.setConnection(null);
        }
        dismiss();
    }

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

Here is a screen shot of the main window.

1

Notes



  • In the Recipient field, make sure you add the “@gmail.com”, not just the user id

Here’s the code for the main activity

package org.apache.android.xmpp;

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);
        setContentView(R.layout.main);

        mRecipient = (EditText) this.findViewById(R.id.recipient);
        mSendText = (EditText) this.findViewById(R.id.sendText);
        mList = (ListView) this.findViewById(R.id.listMessages);
        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);
    }
}

Download Source and APK from here – XMPPClient.zip

54 Comments »

  1. Hey Srini,

    Great job! We are building a app for Android around XMPP and other Android services. this is cool stuff.

    Thanks,
    Sunil

    Comment by Sunil Vishnubhotla — January 2, 2008 @ 8:53 am

  2. Thanks Sunil,
    If anyone has trouble building the JARs, get kxml2 from here and place it in build/merge/ This should help.

    Comment by Blago — January 3, 2008 @ 1:23 pm

  3. Hi, Davanum,

    how did you get to compile 3rd party JAR file to Android platform? Could you list your steps? Thanks a lot in advance.

    Andrew

    Comment by Andrew — January 4, 2008 @ 3:32 pm

  4. The funny thing is that Android is using smack library underneath. You can see it by taking a look at XMPPService dex code.

    Comment by simeon — January 6, 2008 @ 4:34 pm

  5. [...] to watch that evolve as they flesh out the platform details. [edit: look like people are figuring out how to get around Google’s artificial limitations] It could be a very interesting platform for [...]

    Pingback by candyspark* » Blog Archive » Status Update, Jan 2008 — January 7, 2008 @ 11:42 am

  6. Well, Android itself is using the smack library :)

    Comment by Russian Translit — January 10, 2008 @ 8:49 pm

  7. Have you had any issues with some of the smackx packages?

    It looks like its not loading the classes so things like ServiceDiscoverManager don’t work properly.

    Comment by Mike Ryan — January 11, 2008 @ 5:05 pm

  8. Great package! I tried to connect to a lokal openfire server but it failed. If I use your smack.jar together with android.jar outside the emulator it works fine. Are there some limitations (only connections to google talk server) inside the emulator?

    Comment by Markus — January 16, 2008 @ 3:06 am

  9. Found a workaround for the error descibed before: The Android platform seems not to use DNS entries in the hosts file (tested on Windows Vista and XP).

    Nether 127.0.0.1 nor “localhost” nor any other entry directing on the loopback address works. When I use the lokal address in my lokal network it’s runing fine and the connection can be established.

    Comment by Markus — January 16, 2008 @ 9:36 am

  10. Android – Just use Smack API for XMPP

    0
    vote

    Once you get tired of the limitations of android’s built-in IMProvider and the corresponding API – IXmppSession and IXmppService, try the sample below. Inside the source/binary zip (bottom of this article) you will find a smack.jar that work

    Trackback by Go to Android — January 17, 2008 @ 4:44 am

  11. When I run this application, it gives me an error
    NullPointerException

    Comment by Natasha — January 24, 2008 @ 6:00 am

  12. Markus, what exactly do you mean by “When I use the lokal address in my lokal network it’s runing fine and the connection can be established.” ??

    Please help me if you know the answer. I understand redirecting the traffic from host port to guest port, but here the client is running on android, but it wont connect to the server- using the server name/hostname/ip address.

    Comment by Natasha — January 30, 2008 @ 6:14 am

  13. @Natasha: Just use the IP address of the computer where the xmpp server is running.

    If you are running xmpp server and android emulator on the same machine use the external IP address of the computer to connect. The loopback address (“localhost”, 127.0.0.1, etc.) does not work. I think android is resolving “localhost” to it self.

    Comment by Markus — February 3, 2008 @ 7:59 am

  14. Hi Guys, taking the XMPPClient.zip from above and running it through my emulator through Eclipse, I get a series of warnings like the following: W/dalvikvm(556): Link of class 'org/jivesoftware/smackx/debugger/EnhancedDebuggerWindow$PopupListener' failed. The app comes up, yet testing sending messages I get nothing sent. I tried also adding to the project the smackx.jar file, but then I get errors about classes already being loaded. I’m using the following configs: talk.google.com 5222 gmail.com organic2@gmail.com . Can someone shed some some light on what might be going on here? Thanks.

    Comment by MikeO — February 4, 2008 @ 4:13 pm

  15. quick correction, my userid is just organic2, no @gmail.com, per the instructions above.

    Comment by MikeO — February 4, 2008 @ 4:15 pm

  16. Ok, update; I can send messages to GTalk, so I can have a conversation between a gtalk client and my android emulator. I would like to go phone to phone, or emulator to emulator in this case. I’ve scoured the user groups for this, anyone have an idea on how to do this?

    Comment by MikeO — February 4, 2008 @ 4:59 pm

  17. @MikeO: All smackx classes are compiled into the smack.jar above. That’s why you get the error messages after adding smackx.jar.

    The error message “W/dalvikvm(556): Link of class ‘org/jivesoftware/smackx/debugger/EnhancedDebuggerWindow$PopupListener’ failed.” is thrown because the debugger window requiring some java.awt classes not included in android is also compiled within.

    Based on Davanum’s patch I’ve compiled a new lightweight smack.jar where all these classes were removed. You can download the new jar file here.

    Comment by Markus — February 9, 2008 @ 8:36 am

  18. Markus, thank you for replying to my query. Really appreciate it.
    I tried using the local ip address of the machine where the OpenFire server is installed, but it gave me exception ‘No response from server’. Then I replaced the openfire server with gtalk and then with Jabberd 2 server, same result. And I’m sure the credentials are correct, logs in with a commercial client, but when I try from my Java client, just doesnt go past the ‘No response..’ error. And the code is exactly similar to the one above.

    If possible, please help.
    Thanks.

    Comment by Natasha — February 13, 2008 @ 6:48 am

  19. Natasha, do you get the error message “No response from the server.” or “No response from server.”? There are two different types of messages in the smack package.

    The first exception is thrown during the authentification process. Is your internet connection very slow? Smack waits only 5 seconds for a reply of the server and then the exception is thrown. Try to increase the packet reply timeout. The static method

    SmackConfiguration.setPacketReplyTimeout(15000);

    will set the timeout to 15 seconds. Set the timeout before connection.connect().

    Comment by Markus — February 14, 2008 @ 3:33 pm

  20. Hi, Could anyone please tell me how to use the above code, I mean step wise explaination of how to implement it?
    Please help me.

    Comment by Sonal — February 15, 2008 @ 8:26 am

  21. I am also encountering the null pointer exception. I built it using the new android sdk under eclipse. Launched the emulator OK. In the set up screen I set the host to talk.google.com port 5222, specified my gmail ID and password and pressed OK. After ‘thinking’ for a while the emulator came back with the chat window. In there I specified the recipient (another gmail account that’s logged into gtalk from a desktop, with full ‘____@gmail.com’ address), and tried to send it a message. When I clicked the “send” button I got a null pointer exception in org.apache.android.xmpp. From the desktop side, the gtalk application did not recognize that the emulator account was logged in, either.

    Please advice if possible. Thanks.

    Comment by anon8mizer — February 21, 2008 @ 4:28 am

  22. the question still remain from previous version of unofficial gtalk client, is this version capable to receiving text message from gtalk client? please advise

    Comment by enshrentko — February 27, 2008 @ 5:24 am

  23. i got the error “not connected to server” when trying to setting the connection, please advise

    Comment by enshrentko — February 27, 2008 @ 8:44 am

  24. And what about an Android-Jingle app.?

    Comment by Rodrigo — March 8, 2008 @ 11:37 am

  25. Could you try to update this sample for the latest android SDK please?

    Comment by Joseph Dung — March 11, 2008 @ 6:09 am

  26. Thanks! This is a great program.

    To Joseph Dung:

    The only thing you need to modify is the layout of the program. After you add “android” in front of each “id:”
    this program can run.

    Comment by Luke — March 25, 2008 @ 11:07 am

  27. Hello,

    thank you for this API porting, srinivas. It is at the heart of my entire project :)

    For anyone that might still be interrested in this API, have you guys tried out the example in the debugger ? And if you did, what were the results ?
    For me it works ok when i run the example, but when i try debugging it, it connects ok to the xmpp server (tried with talk.google.com and jabber.org). When stepping over

    “connection.login(username, password);”

    line the debugger waits for the 5 seconds default timeout of smack API and catches an xmppException. And it also says in its output window:

    “ERROR/OpenSSLSocketImpl(1234): SSL handshake failure (return code 0; error code 5; errno 0)”

    It makes no difference if I set a longer timeout. Just 5 minutes ago I have noticed that it can also connect from debugger if I press the Ok button again in the SettingsDialog form x-).
    Yes, if I “connect twice” from the debugger, I get my user connected and logged in to my server. lol ???

    Thanks

    Comment by kellogs — March 31, 2008 @ 7:13 pm

  28. Hi Davanum,
    I tried the source code for XXMP,its giving runtime error org/jivesoftware/smack/connectionConfiguration while trying to create ConnectionConfiguration connConfig =
    new ConnectionConfiguration(“talk.google.com”, 5222, “gmail.com”);
    Please let me know what can be possible error.

    Comment by anup tiwary — April 2, 2008 @ 12:27 am

  29. Hi there

    I get an XMPPException in Line 46 when trying to connect to talk.google.com (i.e. IP: 209.85.137.125). Any idea why?

    Greetz
    Graphity

    Comment by Graphity — April 10, 2008 @ 5:04 am

  30. Hi again

    I fired up my debugger, played around and found out that the exception comes from org.jivesoftware.smack.PacketRead Line 164 (it must be around there, I changes the code a little). The line says ‘throw new XMPPException(“Connection failed. No response from server.”);’ when connectionID == null.
    BUT, that connectionID is set in parsePackets(Thread) which is never called (or is it?).

    Any ideas what I can do?

    Comment by Graphity — April 10, 2008 @ 9:18 am

  31. Ok, I figured parsePackets(Thread) is called when init() is called. So do I get an XMPPException?

    Comment by Graphity — April 11, 2008 @ 3:41 am

  32. I am a beginner…. I dont know how to apply patch for the xmpp connection. I am getting Connenction configuration error.i.e, connection itself not getting established……. What is the error … Plz any one reply…
    Thanks.

    Comment by Gunaa — April 22, 2008 @ 8:00 am

  33. Please provide XMPPClient.zip with the patch

    Comment by Tinky — September 5, 2008 @ 1:52 am

  34. Hi. I hope this threat is already open. The XMPPClient.zip is no longer available. I build the client by my self, but i dont have the correct smack.jar file. And i don’t know how i can patch the original. Can anyone upload the XMPPClient.zip or patched smack.jar again?

    Comment by Bulldog — September 18, 2008 @ 4:09 am

  35. Hello,

    I have tried same code, i am getting error message on the program GMailSender.java, line is static {
    Security.addProvider(new org.apache.harmony.xnet.provider.jsse.JSSEProvider());
    }
    the error message is org.apache.harmony cannot be ressolved as type..

    is there any dependancies need to be installed to run an application.

    Thanks in Advance

    Regard’s
    Parasuraman.K

    Comment by Parasuram — October 6, 2008 @ 7:32 am

  36. Hey anyone has the updated zip file for SDK 1.0.

    Comment by indiabolbol — October 17, 2008 @ 10:35 pm

  37. I want to route(send) the received message to any another person.But can not do.when I creates a new chat to send message to another ID it is not working…..can anybody help me.

    Thanx in advanced.

    Comment by Vijendra Yadav — November 13, 2008 @ 3:38 am

  38. Dear all,
    The link (smack, xmppclient.zip) you provided is somehow invalid. Could you please post it again?

    Thanks a lot.

    Comment by Canh cut — November 14, 2008 @ 3:37 am

  39. Hi all,
    i have a problem sending a message with PacketExtension.
    I successfully patched the smack sources with the given diff-file.
    It works fine, to send a Message to different clients. But if i add a PacketExtension, the message don’t arrive the recipient.
    I tested the same example with my patched sources as normal java application. This works fine.
    So i think there is maybe more to patch, that it works on android.

    Does anyone have the same problems and have a solution?

    Thanks.

    Comment by Bulldog — November 28, 2008 @ 4:06 am

  40. @Bulldog,
    how do you patch the diff file to Smack?
    thnx

    I am having trouble with changing security features of android and i am guessing that it has something to do with /system/etc/security/ stuff.
    anybody has any idea?

    thanks

    Comment by mike — November 29, 2008 @ 7:13 pm

  41. @mike,
    the patching is very easy – and i din’t use a diff-tool.
    Just download the sources, open it in eclipse. Then open the three files and apply the changes from the diff-file.
    Then download the kxml2.jar and place it in build/merge.
    Run ant and its done.
    With the security problems u mentioned i can’t help u.

    @All
    Whats about my problem with the PacketExtension???

    Comment by Bulldog — December 1, 2008 @ 2:50 am

  42. Hi all,
    Thanks in advance .please send me the link for XMPPClient.zip .

    Comment by Rajesh — December 10, 2008 @ 6:49 am

  43. Hello
    Give me AndroidMenifest.xml for XMPPClient By Dvanum shrinivas

    Regards
    Jagtap

    Comment by Jagtap — December 15, 2008 @ 4:55 am

  44. I want AndroidManifest.xml for XMPPClient , so if anybody have it forward me jagtap@igloo360.com

    Comment by jagtap — December 17, 2008 @ 5:00 am

  45. My android can’t authenticate to my XMPP server. however, I could use IM program to login to my server.

    The log in the server showed the sever had accepted the connection from android, but there was no any authentication occuring.

    please help me
    PS. I still don’t understand how to apply the patch.

    Thanks
    Addion

    Comment by Addion — December 18, 2008 @ 5:32 am

  46. Hi,

    The the code example and smack.jar are missing. Can someone please upload them?

    I went over the patch but no joy, unless I’m missing something there are still a lot missing pieces…

    Cheers,
    Ilan

    Comment by Ilan — December 19, 2008 @ 2:09 am

  47. Can anyone send me a link to download the patched smack.jar file?
    Thanks in advance.

    Comment by earlence — December 22, 2008 @ 1:42 am

  48. [...] Android – Just use Smack API for XMPP « Show me the code! – By Davanum Srinivas [...]

    Pingback by Updated XMPP Client for Android « Show me the code! - By Davanum Srinivas — December 29, 2008 @ 12:25 am

  49. hi…………
    what is xmpp?
    in simple sentence

    Comment by sujisha — March 9, 2009 @ 5:15 am

  50. how to add the smack.jar file。

    Comment by jacen — March 22, 2009 @ 9:04 pm

  51. thanks, it works well,

    Comment by Mahsa — March 31, 2009 @ 7:41 am

  52. using OpenFire server as well, so far everything is smoothly working. Now it’s time to extend this bad boy! :)

    Thanks again.

    Comment by Logor — April 22, 2009 @ 11:46 pm

  53. I tried same program but I am getting exception ” XMMPClient is not responding ”

    please help me
    Thanks

    Comment by abhijit — September 18, 2009 @ 8:02 am


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.