Showing posts with label app. Show all posts
Showing posts with label app. Show all posts

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.