Today we will develop a chat application from scratch for android. We will use XMPP (ejabberd) hosted on aws EC2.
I will be developing this app using Eclipse IDE with adt plugin.
Create a new android application project in eclipse.
Choose tabbed activity while creating the project.(see screenshot below)
Select “Action bar tabs (with viewpager)” for Navigation style as show below.
Now as the project is created, just try to run this project and you will see an empty app with three tabs named Secion1, Section2, Section3 as shown below:
Now change name of the three tabs to Favourites, Chats, Contacts respectively.
To do this, change the content of the string.xml file located at res/values/string.xml in your project directory to the code below.
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">MChat</string> <string name="title_section1">Favourites</string> <string name="title_section2">Chats</string> <string name="title_section3">Contacts</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> </resources>
Now run the application.
Now as we have added tabs layout, we will work on the tab “Chats”.
Download the 9 patch images below and and move them to drawable-hdpi in res directory of your project.
Create an xml file res/drawable/send_button.xml. If drawable folder does not exist in your res directory then create it.
The contents for the send_button.xml will be:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/send_selected" /> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/send_selected" /> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/send_selected" /> <item android:drawable="@drawable/send" /> </selector>
Now Create a new layout file chat_layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#e1e1e1" android:orientation="vertical" > <ListView android:id="@+id/msgListView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/form" android:divider="@null" android:dividerHeight="0dp" android:paddingBottom="10dp" android:text="@string/hello_world" /> <LinearLayout android:id="@+id/form" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:background="#91f1f1f1" android:orientation="horizontal" android:paddingBottom="2dp" > <EditText android:id="@+id/messageEditText" android:layout_width="252dp" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignTop="@+id/button1" android:layout_toLeftOf="@+id/sendMessageButton" android:layout_weight="0.72" android:ems="10" android:maxHeight="80dp" /> <ImageButton android:id="@+id/sendMessageButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:background="@drawable/send_button" android:text="d" /> </LinearLayout> </RelativeLayout>
This will be layout file which will provide interface for sending and receiving chat messages.
The layout contains:
i) A Listview which will have entries for sent and received messages.
ii) An EditText view for writing new message.
ii) A Button view to send message.
See the graphical Layout below:
The layout contains:
i) A Listview which will have entries for sent and received messages.
ii) An EditText view for writing new message.
ii) A Button view to send message.
See the graphical Layout below:
We will be using a custom adapter for our Listview. So in order to follow that we will need another layout file for each entry of the listview.
Create another layout file chatbubble.xml as follows:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/bubble_layout_parent" android:layout_width="wrap_content" android:layout_height="wrap_content" > <LinearLayout android:id="@+id/bubble_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bubble1"> <TextView android:id="@+id/message_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxEms="12" android:layout_gravity="center" android:text="Hi! new message" android:textColor="@android:color/primary_text_light" /> </LinearLayout> </LinearLayout>
In this layout file we have another LinearLayout inside the parent LinearLayout. This is done because we need to change the position of the message according to the sender of the message. For example if a message is sent by you, then it should be aligned right of the screen and if the message is received from another user then it should be aligned left of the screen.
Below is the graphical layout of th chatbubble.xml:
Now create a new package named com.marothiatechs.fragments inside src folder of your project.
create a new Java file in this new package and name it Chats.java
The contents of Chats.java will be :
create a new Java file in this new package and name it Chats.java
The contents of Chats.java will be :
package com.marothiatechs.fragments; import java.util.ArrayList; import java.util.Random; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ListView; import com.marothiatechs.mchat.ChatAdapter; import com.marothiatechs.mchat.ChatMessage; import com.marothiatechs.mchat.CommonMethods; import com.marothiatechs.mchat.R; public class Chats extends Fragment implements OnClickListener { private EditText msg_edittext; private String user1 = "khushi", user2 = "khushi1"; private Random random; public static ArrayList<ChatMessage> chatlist; public static ChatAdapter chatAdapter; ListView msgListView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.chat_layout, container, false); random = new Random(); ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle( "Chats"); msg_edittext = (EditText) view.findViewById(R.id.messageEditText); msgListView = (ListView) view.findViewById(R.id.msgListView); ImageButton sendButton = (ImageButton) view .findViewById(R.id.sendMessageButton); sendButton.setOnClickListener(this); // ----Set autoscroll of listview when a new message arrives----// msgListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); msgListView.setStackFromBottom(true); chatlist = new ArrayList<ChatMessage>(); chatAdapter = new ChatAdapter(getActivity(), chatlist); msgListView.setAdapter(chatAdapter); return view; } @Override public void onSaveInstanceState(Bundle outState) { } public void sendTextMessage(View v) { String message = msg_edittext.getEditableText().toString(); if (!message.equalsIgnoreCase("")) { final ChatMessage chatMessage = new ChatMessage(user1, user2, message, "" + random.nextInt(1000), true); chatMessage.setMsgID(); chatMessage.body = message; chatMessage.Date = CommonMethods.getCurrentDate(); chatMessage.Time = CommonMethods.getCurrentTime(); msg_edittext.setText(""); chatAdapter.add(chatMessage); chatAdapter.notifyDataSetChanged(); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.sendMessageButton: sendTextMessage(v); } } }
Create a new file named ChatMessage.java in the package com.marothiatechs.mchat:
package com.marothiatechs.mchat; import java.util.Random; public class ChatMessage { public String body, sender, receiver, senderName; public String Date, Time; public String msgid; public boolean isMine;// Did I send the message. public ChatMessage(String Sender, String Receiver, String messageString, String ID, boolean isMINE) { body = messageString; isMine = isMINE; sender = Sender; msgid = ID; receiver = Receiver; senderName = sender; } public void setMsgID() { msgid += "-" + String.format("%02d", new Random().nextInt(100)); ; } }
Create a new file named ChatAdapter.java in the package com.marothiatechs.mchat:
package com.marothiatechs.mchat; import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.graphics.Color; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.TextView; public class ChatAdapter extends BaseAdapter { private static LayoutInflater inflater = null; ArrayList<ChatMessage> chatMessageList; public ChatAdapter(Activity activity, ArrayList<ChatMessage> list) { chatMessageList = list; inflater = (LayoutInflater) activity .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return chatMessageList.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ChatMessage message = (ChatMessage) chatMessageList.get(position); View vi = convertView; if (convertView == null) vi = inflater.inflate(R.layout.chatbubble, null); TextView msg = (TextView) vi.findViewById(R.id.message_text); msg.setText(message.body); LinearLayout layout = (LinearLayout) vi .findViewById(R.id.bubble_layout); LinearLayout parent_layout = (LinearLayout) vi .findViewById(R.id.bubble_layout_parent); // if message is mine then align to right if (message.isMine) { layout.setBackgroundResource(R.drawable.bubble2); parent_layout.setGravity(Gravity.RIGHT); } // If not mine then align to left else { layout.setBackgroundResource(R.drawable.bubble1); parent_layout.setGravity(Gravity.LEFT); } msg.setTextColor(Color.BLACK); return vi; } public void add(ChatMessage object) { chatMessageList.add(object); } }
Create a new file named CommonMethods.java in the package com.marothiatechs.mchat:
package com.marothiatechs.mchat; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class CommonMethods { private static DateFormat dateFormat = new SimpleDateFormat("d MMM yyyy"); private static DateFormat timeFormat = new SimpleDateFormat("K:mma"); public static String getCurrentTime() { Date today = Calendar.getInstance().getTime(); return timeFormat.format(today); } public static String getCurrentDate() { Date today = Calendar.getInstance().getTime(); return dateFormat.format(today); } }
Modify the contents of MainActivity.java:
You need to replace the getItem() method in SectionsPagerAdapter class inside MainActivity.java as shown below:
public class SectionsPagerAdapter extends FragmentPagerAdapter {public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}@Override
public Fragment getItem(int position) {
if (position == 1) {
return new Chats();
} else
return PlaceholderFragment.newInstance(position + 1);
}@Override
public int getCount() {
// Show 3 total pages.
return 3;
}@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
super(fm);
}@Override
public Fragment getItem(int position) {
if (position == 1) {
return new Chats();
} else
return PlaceholderFragment.newInstance(position + 1);
}@Override
public int getCount() {
// Show 3 total pages.
return 3;
}@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
Now Run the application, go to Chats tab and try to send any message. You will notice that a new entry with a bubble is added to the listview.
The screenshot of the app so far:
We will implement the Smack 4.1 implementation using Android service in Part-2.
183,801 total views, 6 views today
(Visited 161,771 times, 2 visits today)
Pingback: Building your own android chat messenger app similar to Whatsapp using XMPP (Smack 4.1 API) from scratch: Part-2 | Tutorials Face()
Pingback: What are all need to make app? – My library()