Tuesday, 18 January 2011

Writing a basic XMPP/Jabber chat application for Android

There are many chat applications for android open source that you can use to connect to an XMPP or Jabber server instance. This could be you own server such as Ejabberd or one such as Facebook / yahoo etc.

I have started to look at how to write a basic android XMPP client that I can use to connect to my Ejabberd server. I have pulled a number of sources available to gain knowledge in android, initially stating with Professional Android 2 Application Development.
There are a number other sample applications in this book that will aid in learning the android programming language.

However to understand how to create an XMPP application I started looking at Smack, an XMPP client library.
This is the library you will need to import and refer to when writing your android XMPP client. Google no longer has it's own native XMPP library.

Smack has be heavily patched to work with android devices, re-badged asmack, library downloads are available from http://code.google.com/p/asmack/
.

Once you have this imported into your project workspace you can now write a basic chat client. I used the following example code for my first point of call:

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

After understanding what each bit of code here meant I was able to write my own similar app. Initially the original sample I'm going to show is very similar to the link above, so I cannot take full credit, I'm just sharing resources.
I have now heavily added to the app with shared preferences custom views and content providers etc, I may share the source in later posts.

You will need to write xml layouts to go with the code but the code behind the main application is as follows:

notice the org.jivesoftware.smack imports:

ChatClient.java:

import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
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;

public class ChatClient extends Activity {
   
    private ArrayList<String> messages = new ArrayList();
    private Handler handler = new Handler();
    private xmppsettings settings;
    private EditText recipient;
    private EditText text;
    private ListView list;
    private XMPPConnection connection;
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        recipient = (EditText) this.findViewById(R.id.recipient);
        text = (EditText) this.findViewById(R.id.text);
        list = (ListView) this.findViewById(R.id.messageList);
        setListAdapter();
       
        //Window for getting settings
        settings = new xmppsettings(this);
       
        //Listener for chat message
        Button send = (Button) this.findViewById(R.id.send);
        send.setOnClickListener(new View.OnClickListener() {
           
            @Override
            public void onClick(View v) {
                String to = recipient.getText().toString();
                String text1 = text.getText().toString();
               
                Message msg = new Message(to, Message.Type.chat);
                msg.setBody(text1);
                connection.sendPacket(msg);
                messages.add(connection.getUser() + ":");
                messages.add(text1);
                setListAdapter();               
            }
        });       
    }
   
    //Called by settings when connection is established
   
    public void setConnection (XMPPConnection connection) {
        this.connection = connection;
        if (connection != null) {
            //Packet listener to get messages sent to logged in user
            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());
                        messages.add(fromName + ":");
                        messages.add(message.getBody());
                        handler.post(new Runnable(){
                            public void run() {
                                setListAdapter();
                            }
                        });
                    }
                }
            }, filter);
        }
    }
   
    private void setListAdapter() {
        ArrayAdapter<String> adapter = new ArrayAdapter<String>
            (this, R.layout.list, messages);
        list.setAdapter(adapter);
    }
   
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }
   
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
        case R.id.settings:
            settings.show();
            return true;
        case R.id.quit:
            finish();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
   
    }
}




xmppsettings.java: (I have made this a menu item)


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

//settings get input and then connection is established

public class xmppsettings extends Dialog implements android.view.View.OnClickListener  {
    private ChatClient chatClient;
   
    public xmppsettings(ChatClient chatClient){
        super(chatClient);
        this.chatClient = chatClient;
    }
   
    protected void onStart() {
        super.onStart();
        setContentView(R.layout.settings);
        setTitle("Connection 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 connection
       
        ConnectionConfiguration connectionConfig =
            new ConnectionConfiguration(host, Integer.parseInt(port), service);
        XMPPConnection connection = new XMPPConnection(connectionConfig);
       
        try {
            connection.connect();
        } catch (XMPPException ex) {
            chatClient.setConnection(null);
        }
        try {
            connection.login(username, password);
           
            // Set status to online / available
            Presence presence = new Presence(Presence.Type.available);
            connection.sendPacket(presence);
            chatClient.setConnection(connection);
        } catch (XMPPException ex) {
            chatClient.setConnection(null);
        }
        dismiss();
    }
   
    private String getText(int id) {
        EditText widget = (EditText) this.findViewById(id);
        return widget.getText().toString();
    }
}



After these initial files I then when one to create a shared preferences which will save the settings that a user inputs.
Also then when on to write a separate array adapter within the chatclient.java class which then aided in the creation of a content provider to store the messages in a db.

This is the application at the most basic, but will get you started in developing any high end chat app.

42 comments:

  1. Can you share the code as well?

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  2. Is it only for G-talk or FB also? bcz, Fb is also an XMPP protocol based chat server.

    ReplyDelete
  3. Thanks a lot man. Your article will be very much helpful for my upcoming presentation on XMPP clinet for android. Is it possible to have a glance @ your code as well.

    ReplyDelete
  4. This code was for a test chat application I created when learning android / XMPP initially. The code above is a great start for developing any chat application.
    Unfortunately I do not possess code for this application any more. However will be more than happy to answer any questions you may have.

    ReplyDelete
    Replies
    1. I am using smack and ejabberd 2 for developing a chat engine. I am having a problem in using UserSearch class of smack. Can you please take a look at my problem posted here: http://stackoverflow.com/questions/19808663/search-for-users-on-ejabberd2-using-smack-fails

      Delete
    2. can you please share the smack and ejabberd for android example

      Delete
  5. iam designing a software that can transmitt gps co-ordinates on any specific server ip, can you help me that in any form of code or material?

    ReplyDelete
    Replies
    1. Salman did you complete the application you were talking about?

      Delete
  6. iam doing the above project for andriod systems

    ReplyDelete
    Replies
    1. can you please share the smack and ejabberd for android example

      Delete
  7. thanks buddy! this so helpful and so kind of you to share it. thank you.

    ReplyDelete
  8. Thanks buddy, can I put your blog content in my blog?

    ReplyDelete
  9. Replies
    1. hi lee... can you give me the xml code for it...

      Delete
  10. My xmpp server name is ubuntu.I connected to it by the following snippet.
    ConnectionConfiguration connConfig =
    new ConnectionConfiguration("ubuntu", 9090);
    XMPPConnection connection = new XMPPConnection(connConfig);
    But it didn't connect

    ReplyDelete
    Replies
    1. This post can help anyone with above issue - http://im-a-developer-too.blogspot.ca/2014/04/creating-android-xmpp-client-using.html

      Delete
  11. Could you please also tell how to put password in it while sign in....my logcat is giving me exceptions as:

    12-05 14:33:09.228: W/System.err(906): java.security.KeyStoreException: java.security.NoSuchAlgorithmException: KeyStore jks implementation not found
    12-05 14:33:09.228: W/System.err(906): at java.security.KeyStore.getInstance(KeyStore.java:119)
    12-05 14:33:09.236: W/System.err(906): at org.jivesoftware.smack.ServerTrustManager.(ServerTrustManager.java:61)
    12-05 14:33:09.236: W/System.err(906): at org.jivesoftware.smack.XMPPConnection.proceedTLSReceived(XMPPConnection.java:832)
    12-05 14:33:09.236: W/System.err(906): at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:268)
    12-05 14:33:09.248: W/System.err(906): at org.jivesoftware.smack.PacketReader.access$000(PacketReader.java:44)
    12-05 14:33:09.256: W/System.err(906): at org.jivesoftware.smack.PacketReader$1.run(PacketReader.java:71)

    when I am trying with hardcodded password....

    ReplyDelete
  12. hi.. dear plz share the xml code..

    ReplyDelete
  13. Thank You dude.. It really very useful, I have one question How to send messages to mobile number using same library..? is it possible..?

    ReplyDelete
  14. hi dude
    can u give me a reference or a book about writing a chat app for android using jabber protocol i really need it !
    HELP ME please
    my email : ahmed.medo11@hotmail.com

    ReplyDelete
  15. can u please provide xml for this project??

    ReplyDelete
  16. Hello Sir.I want to create a stand alone chat appliocation without using any accounts like gtalk or fb.Can you suggest some ideas to create an appication like wechat watsapp...etc..

    ReplyDelete
  17. running this gives exception networkonmainthread can you tell me how to use the connection code in async task..???

    ReplyDelete
    Replies
    1. I wrote a post using similar code and hosted it on GitHub. You may download the source code and run the Android App directly.

      http://im-a-developer-too.blogspot.ca/2014/04/creating-android-xmpp-client-using.html

      Delete
  18. hi, nice work..can u please tell more about how to register a new one..becz i want to develop an app for chatting(in contact list)..please send me the idea to my id srijinits@gmail.com
    thanks

    ReplyDelete
  19. Hello,

    I am able to connect to the server and log in in an Activity.
    But I want to be able to reconnect sometime later maybe in another activity.
    Will I have to use the login credentials again or is there a way to store some session is sort of thing in a database which i can use to reconnect.

    ReplyDelete
    Replies
    1. You can add a small sqlLite database in assets folder and store user credentials or his friends list etc

      Delete
  20. can you share this project in archive? we need it.

    ReplyDelete
    Replies
    1. I have developed an android app using this tutorial and published it on Google Play, the source code is available on Github.. here's the link http://im-a-developer-too.blogspot.ca/2014/04/creating-android-xmpp-client-using.html

      Delete
  21. This comment has been removed by the author.

    ReplyDelete
  22. Can you show how to use class like Chat in asmack library.

    ReplyDelete
  23. Hey buddy,
    i am working on File Transfer and i want to try between two android clients.
    FileTransferManager manager = new FileTransferManager(connection);
    OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer("usre2@myHost/Smack");

    How to get resource id(Smack in ) of the user along with jabber id (usre2@myHost/).i am using openfire and asmack lib for android.

    ReplyDelete
  24. Good one buddy thanks..!! :) do you know how to achieve Push Notification from server to app (like new updates notification to all client app or some alert ) any idea to achieve this..?

    ReplyDelete
  25. well explain and visit also
    http://www.javaproficiency.com/2015/04/openfire-server-tutorial.html

    ReplyDelete
  26. Hello man , i had only one question regarding to XMPP chat how to use it in shared server like i want to use in go daddy server how can i used it ?

    ReplyDelete
  27. fffffffffffffffffffffffffffffffffffffff

    ReplyDelete