/*
BEEM is a videoconference application on the Android Platform.
Copyright (C) 2009 by Frederic-Charles Barthelery,
Jean-Manuel Da Silva,
Nikita Kozlov,
Philippe Lago,
Jean Baptiste Vergely,
Vincent Veronis.
This file is part of BEEM.
BEEM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
BEEM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with BEEM. If not, see <http://www.gnu.org/licenses/>.
Please send bug reports with examples or suggestions to
contact@beem-project.com or http://dev.beem-project.com/
Epitech, hereby disclaims all copyright interest in the program "Beem"
written by Frederic-Charles Barthelery,
Jean-Manuel Da Silva,
Nikita Kozlov,
Philippe Lago,
Jean Baptiste Vergely,
Vincent Veronis.
Nicolas Sadirac, November 26, 2009
President of Epitech.
Flavien Astraud, November 26, 2009
Head of the EIP Laboratory.
*/
package com.beem.project.beem.ui;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jivesoftware.smack.util.StringUtils;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.util.Linkify;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.beem.project.beem.BeemService;
import com.beem.project.beem.R;
import com.beem.project.beem.service.Contact;
import com.beem.project.beem.service.Message;
import com.beem.project.beem.service.PresenceAdapter;
import com.beem.project.beem.service.aidl.IBeemRosterListener;
import com.beem.project.beem.service.aidl.IChat;
import com.beem.project.beem.service.aidl.IChatManager;
import com.beem.project.beem.service.aidl.IChatManagerListener;
import com.beem.project.beem.service.aidl.IMessageListener;
import com.beem.project.beem.service.aidl.IRoster;
import com.beem.project.beem.service.aidl.IXmppFacade;
import com.beem.project.beem.utils.BeemBroadcastReceiver;
import com.beem.project.beem.utils.Status;
// TODO: Auto-generated Javadoc
/**
* This class represents an activity which allows the user to chat with his/her contacts.
* @author Jean-Manuel Da Silva <dasilvj at beem-project dot com>
*/
public class Chat extends Activity implements OnKeyListener {
private static final String TAG = "Chat";
private static final Intent SERVICE_INTENT = new Intent();
static {
SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
}
private Handler mHandler;
private IRoster mRoster;
private Contact mContact;
private TextView mContactNameTextView;
private TextView mContactStatusMsgTextView;
private ImageView mContactStatusIcon;
private ListView mMessagesListView;
private EditText mInputField;
private Button mSendButton;
private final Map<Integer, Bitmap> mStatusIconsMap = new HashMap<Integer, Bitmap>();
private final List<MessageText> mListMessages = new ArrayList<MessageText>();
private IChat mChat;
private IChatManager mChatManager;
private IChatManagerListener mChatManagerListener;
private IMessageListener mMessageListener;
private MessagesListAdapter mMessagesListAdapter;
private final ServiceConnection mConn = new BeemServiceConnection();
private BeemBroadcastReceiver mBroadcastReceiver;
/**
* Constructor.
*/
public Chat() {
super();
}
/**
* {@inheritDoc}.
*/
@Override
protected void onCreate(Bundle savedBundle) {
super.onCreate(savedBundle);
Log.v(TAG, "BEGIN onCreate.");
setContentView(R.layout.chat);
mMessagesListAdapter = new MessagesListAdapter(this);
mHandler = new Handler();
// SVC Bind
bindService(SERVICE_INTENT, mConn, BIND_AUTO_CREATE);
// Listeners
mMessageListener = new OnMessageListener();
mChatManagerListener = new OnChatManagerListener();
mBroadcastReceiver = new BeemBroadcastReceiver(mConn);
this.registerReceiver(mBroadcastReceiver, new IntentFilter(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED));
// UI
mContactNameTextView = (TextView) findViewById(R.id.chat_contact_name);
mContactStatusMsgTextView = (TextView) findViewById(R.id.chat_contact_status_msg);
mContactStatusIcon = (ImageView) findViewById(R.id.chat_contact_status_icon);
mMessagesListView = (ListView) findViewById(R.id.chat_messages);
mMessagesListView.setAdapter(mMessagesListAdapter);
mInputField = (EditText) findViewById(R.id.chat_input);
mInputField.setOnKeyListener(this);
mSendButton = (Button) findViewById(R.id.chat_send_message);
mSendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sendMessage();
}
});
prepareIconsStatus();
Log.v(TAG, "END onCreate.");
}
/**
* {@inheritDoc}.
*/
@Override
protected void onDestroy() {
super.onDestroy();
Log.v(TAG, "BEGIN onDestroy.");
if (mChatManager != null) {
try {
mChatManager.removeChatCreationListener(mChatManagerListener);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
}
this.unregisterReceiver(mBroadcastReceiver);
unbindService(mConn);
Log.v(TAG, "END onDestroy.");
}
/**
* {@inheritDoc}.
*/
@Override
protected void onStart() {
super.onStart();
Log.v(TAG, "BEGIN onStart.");
Log.v(TAG, "END onStart.");
}
/**
* {@inheritDoc}.
*/
@Override
protected void onStop() {
super.onStop();
Log.v(TAG, "BEGIN onStop.");
if (mChat != null) {
try {
mChat.setOpen(false);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
}
Log.v(TAG, "END onStop.");
}
/**
* {@inheritDoc}.
*/
@Override
protected void onResume() {
super.onResume();
}
/**
* {@inheritDoc}.
*/
@Override
protected void onPause() {
super.onPause();
}
/**
* {@inheritDoc}.
*/
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.v(TAG, "BEGIN onNewIntent.");
try {
mContact = new Contact(intent.getData());
changeCurrentChat(mContact);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
Log.v(TAG, "END onNewIntent.");
}
/**
* {@inheritDoc}.
*/
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
// TODO
super.onSaveInstanceState(savedInstanceState);
}
/**
* {@inheritDoc}.
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// TODO
}
/**
* {@inheritDoc}.
*/
@Override
public final boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.chat, menu);
return true;
}
/**
* {@inheritDoc}.
*/
@Override
public final boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.chat_menu_contacts_list:
Intent contactListIntent = new Intent(this, ContactList.class);
contactListIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(contactListIntent);
return true;
case R.id.chat_menu_change_chat:
try {
final List<Contact> openedChats = mChatManager.getOpenedChatList();
if (openedChats.size() > 0)
createChatSwitcherDialog(openedChats);
else
createNoActiveChatsDialog();
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
return true;
case R.id.chat_menu_close_chat:
try {
mChatManager.destroyChat(mChat);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
this.finish();
return true;
default:
return false;
}
}
/**
* Create the change chat dialog.
* @param openedChats A list containing the JID of participants of the opened chats.
*/
private void createChatSwitcherDialog(final List<Contact> openedChats) {
CharSequence[] items = new CharSequence[openedChats.size()];
int i = 0;
for (Contact c : openedChats) {
items[i++] = c.getName();
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.chat_dialog_change_chat_title));
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Intent chatIntent = new Intent(getApplicationContext(), com.beem.project.beem.ui.Chat.class);
chatIntent.setData((openedChats.get(item)).toUri());
Chat.this.onNewIntent(chatIntent);
}
});
AlertDialog chatSwitcherDialog = builder.create();
chatSwitcherDialog.show();
}
/**
* Create a dialog which notify the user that there're not another one active chat.
*/
private void createNoActiveChatsDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.chat_no_more_chats));
AlertDialog noActiveChatsDialog = builder.create();
noActiveChatsDialog.show();
}
/**
* Change the displayed chat.
* @param contact the targeted contact of the new chat
* @throws RemoteException If a Binder remote-invocation error occurred.
*/
private void changeCurrentChat(Contact contact) throws RemoteException {
Log.v(TAG, "BEGIN changeCurrentChat.");
if (mChat != null)
mChat.setOpen(false);
mChat = mChatManager.createChat(contact, mMessageListener);
mChat.setOpen(true);
mChatManager.deleteChatNotification(mChat);
mContact = mRoster.getContact(contact.getJID());
updateContactInformations();
updateContactStatusIcon();
playRegisteredTranscript();
Log.v(TAG, "END changeCurrentChat.");
}
/**
* Get all messages from the current chat and refresh the activity with them.
* @throws RemoteException If a Binder remote-invocation error occurred.
*/
private void playRegisteredTranscript() throws RemoteException {
String fromBareJid = null;
String fromName = null;
List<Message> chatMessages = mChat.getMessages();
Log.v(TAG, "BEGIN playRegisteredTranscript.");
mListMessages.clear();
if (chatMessages.size() > 0) {
MessageText lastMessage = null;
for (Message m : chatMessages) {
fromBareJid = StringUtils.parseBareAddress(m.getFrom());
fromName = mContact.getName();
if (fromBareJid == null) {
fromBareJid = getString(R.string.chat_self);
fromName = getString(R.string.chat_self);
}
if (lastMessage == null) {
lastMessage = new MessageText(fromBareJid, fromName, m.getBody());
continue;
}
if (!lastMessage.getBareJid().equals(fromBareJid)) {
mListMessages.add(lastMessage);
lastMessage = new MessageText(fromBareJid, fromName, m.getBody());
} else
lastMessage.setMessage(lastMessage.getMessage().concat("\n" + m.getBody()));
}
mListMessages.add(lastMessage);
}
mMessagesListAdapter.notifyDataSetChanged();
Log.v(TAG, "END playRegisteredTranscript.");
}
/**
* {@inheritDoc}.
*/
private final class BeemServiceConnection implements ServiceConnection {
private IXmppFacade mXmppFacade;
private final BeemRosterListener mBeemRosterListener = new BeemRosterListener();
/**
* {@inheritDoc}.
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.v(TAG, "BEGIN onServiceConnected.");
mXmppFacade = IXmppFacade.Stub.asInterface(service);
mBroadcastReceiver.setBinded(true);
try {
mChatManager = mXmppFacade.getChatManager();
mRoster = mXmppFacade.getRoster();
mRoster.addRosterListener(mBeemRosterListener);
mContact = new Contact(getIntent().getData());
changeCurrentChat(mContact);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
Log.v(TAG, "END onServiceConnected.");
}
/**
* {@inheritDoc}.
*/
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v(TAG, "BEGIN onServiceDisconnected.");
mXmppFacade = null;
mBroadcastReceiver.setBinded(false);
try {
mRoster.removeRosterListener(mBeemRosterListener);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
Log.v(TAG, "END onServiceDisconnected.");
}
}
/**
* {@inheritDoc}.
*/
private class BeemRosterListener extends IBeemRosterListener.Stub {
/**
* {@inheritDoc}.
*/
@Override
public void onEntriesAdded(List<String> addresses) throws RemoteException {
Log.v(TAG, "BEGIN onEntriesAdded.");
Log.v(TAG, "END onEntriesAdded.");
}
/**
* {@inheritDoc}.
*/
@Override
public void onEntriesDeleted(List<String> addresses) throws RemoteException {
Log.v(TAG, "BEGIN onEntriesDeleted.");
Log.v(TAG, "END onEntriesDeleted.");
}
/**
* {@inheritDoc}.
*/
@Override
public void onEntriesUpdated(List<String> addresses) throws RemoteException {
Log.v(TAG, "BEGIN onEntriesUpdated.");
Log.v(TAG, "END onEntriesUpdated.");
}
/**
* {@inheritDoc}.
*/
@Override
public void onEntryDeleteFromGroup(String group, String jid) throws RemoteException {
Log.v(TAG, "BEGIN onEntryDeleteFromGroup.");
Log.v(TAG, "END onEntryDeleteFromGroup.");
}
/**
* {@inheritDoc}.
*/
@Override
public void onPresenceChanged(final PresenceAdapter presence) throws RemoteException {
Log.v(TAG, "BEGIN onPresenceChanged.");
if (mContact.getJID().equals(StringUtils.parseBareAddress(presence.getFrom()))) {
mHandler.post(new Runnable() {
@Override
public void run() {
mContact.setStatus(presence.getStatus());
mContact.setMsgState(presence.getStatusText());
updateContactInformations();
updateContactStatusIcon();
}
});
}
Log.v(TAG, "END onPresenceChanged.");
}
}
/**
* {@inheritDoc}.
*/
private class OnMessageListener extends IMessageListener.Stub {
/**
* {@inheritDoc}.
*/
@Override
public void processMessage(IChat chat, final Message msg) throws RemoteException {
Log.v(TAG, "BEGIN processMessage.");
final String fromBareJid = StringUtils.parseBareAddress(msg.getFrom());
if (mContact.getJID().equals(fromBareJid)) {
mHandler.post(new Runnable() {
/**
* {@inheritDoc}.
*/
@Override
public void run() {
if (msg.getBody() != null && msg.getType() != Message.MSG_TYPE_ERROR) {
MessageText lastMessage = mListMessages.size() != 0 ? mListMessages.get(mListMessages
.size() - 1) : null;
if (lastMessage != null && lastMessage.getBareJid().equals(fromBareJid)) {
lastMessage.setMessage(lastMessage.getMessage().concat("\n" + msg.getBody()));
mListMessages.set(mListMessages.size() - 1, lastMessage);
} else
mListMessages.add(new MessageText(fromBareJid, mContact.getName(), msg.getBody()));
mMessagesListAdapter.notifyDataSetChanged();
}
}
});
}
Log.v(TAG, "END processMessage.");
}
/**
* {@inheritDoc}.
*/
@Override
public void stateChanged(IChat chat) throws RemoteException {
Log.v(TAG, "BEGIN stateChanged.");
mHandler.post(new Runnable() {
/**
* {@inheritDoc}.
*/
@Override
public void run() {
}
});
Log.v(TAG, "END stateChanged.");
}
}
/**
* This class serve to listen on ChatManager events.
* @author Jean-Manuel Da Silva <dasilvj at beem-project dot com>
*/
private class OnChatManagerListener extends IChatManagerListener.Stub {
/**
* Constructor.
*/
public OnChatManagerListener() {
Log.v(TAG, "OnChatManagerListener constructor.");
}
/**
* {@inheritDoc}.
*/
@Override
public void chatCreated(IChat chat, boolean locally) throws RemoteException {
Log.i(TAG, "Chat has been created.");
}
}
/**
* Update the contact informations.
*/
private void updateContactInformations() {
Log.v(TAG, "BEGIN updateContactInformations.");
// Check for a contact name update
if (!(mContactNameTextView.getText().toString().equals(mContact.getName())))
mContactNameTextView.setText(mContact.getName());
// Check for a contact status message update
if (!(mContactStatusMsgTextView.getText().toString().equals(mContact.getMsgState()))) {
Log.d(TAG, "Setting status message - " + mContact.getMsgState());
mContactStatusMsgTextView.setText(mContact.getMsgState());
Linkify.addLinks(mContactStatusMsgTextView, Linkify.WEB_URLS);
}
Log.v(TAG, "END updateContactInformations.");
}
/**
* Update the contact status icon.
*/
private void updateContactStatusIcon() {
Log.v(TAG, "BEGIN updateContactStatusIcon.");
mContactStatusIcon.setImageBitmap(mStatusIconsMap.get(mContact.getStatus()));
Log.v(TAG, "END updateContactStatusIcon.");
}
/**
* Prepare the status icons map.
*/
private void prepareIconsStatus() {
mStatusIconsMap.put(Status.CONTACT_STATUS_AVAILABLE, BitmapFactory.decodeResource(getResources(),
R.drawable.status_available));
mStatusIconsMap.put(Status.CONTACT_STATUS_AVAILABLE_FOR_CHAT, BitmapFactory.decodeResource(getResources(),
R.drawable.status_available));
mStatusIconsMap.put(Status.CONTACT_STATUS_AWAY, BitmapFactory.decodeResource(getResources(),
R.drawable.status_away));
mStatusIconsMap.put(Status.CONTACT_STATUS_BUSY, BitmapFactory.decodeResource(getResources(),
R.drawable.status_dnd));
mStatusIconsMap.put(Status.CONTACT_STATUS_DISCONNECT, BitmapFactory.decodeResource(getResources(),
R.drawable.status_offline));
mStatusIconsMap.put(Status.CONTACT_STATUS_UNAVAILABLE, BitmapFactory.decodeResource(getResources(),
R.drawable.status_requested));
}
/**
* {@inheritDoc}.
*/
private class MessagesListAdapter extends BaseAdapter {
private final Context mContext;
/**
* Constructor.
* @param context The MessagesListAdapter context.
*/
public MessagesListAdapter(final Context context) {
mContext = context;
}
/**
* Returns the number of messages contained in the messages list.
* @return The number of messages contained in the messages list.
*/
public int getCount() {
return mListMessages.size();
}
/**
* Return an item from the messages list that is positioned at the position passed by parameter.
* @param position The position of the requested item.
* @return The item from the messages list at the requested position.
*/
public Object getItem(int position) {
return position;
}
/**
* Return the id of an item from the messages list that is positioned at the position passed by parameter.
* @param position The position of the requested item.
* @return The id of an item from the messages list at the requested position.
*/
public long getItemId(int position) {
return position;
}
/**
* Return the view of an item from the messages list.
* @param position The position of the requested item.
* @param convertView The old view to reuse if possible.
* @param parent The parent that this view will eventually be attached to.
* @return A View corresponding to the data at the specified position.
*/
public View getView(int position, View convertView, ViewGroup parent) {
MessageView sv;
if (convertView == null) {
sv = new MessageView(mContext, mListMessages.get(position).getName(), mListMessages.get(position)
.getMessage());
} else {
sv = (MessageView) convertView;
sv.setName(mListMessages.get(position).getName());
sv.setMessage(mListMessages.get(position).getMessage());
}
sv.setPadding(2, 2, 2, 4);
sv.mName.setTextSize(16);
sv.mName.setTextColor(Color.WHITE);
sv.mName.setTypeface(Typeface.DEFAULT_BOLD);
sv.mMessage.setLinkTextColor(Color.WHITE);
sv.mMessage.setPadding(0, 4, 0, 4);
Linkify.addLinks(sv.mMessage, Linkify.WEB_URLS);
return sv;
}
}
/**
* Class which simplify an Xmpp text message.
* @author Jean-Manuel Da Silva <dasilvj at beem-project dot com>
*/
private class MessageText {
private String mBareJid;
private String mName;
private String mMessage;
/**
* Constructor.
* @param bareJid A String containing the bare JID of the message's author.
* @param name A String containing the name of the message's author.
* @param message A String containing the message.
*/
public MessageText(final String bareJid, final String name, final String message) {
mBareJid = bareJid;
mName = name;
mMessage = message;
}
/**
* JID attribute accessor.
* @return A String containing the bare JID of the message's author.
*/
public String getBareJid() {
return mBareJid;
}
/**
* Name attribute accessor.
* @return A String containing the name of the message's author.
*/
public String getName() {
return mName;
}
/**
* Message attribute accessor.
* @return A String containing the message.
*/
public String getMessage() {
return mMessage;
}
/**
* JID attribute mutator.
* @param bareJid A String containing the author's bare JID of the message.
*/
@SuppressWarnings("unused")
public void setBareJid(String bareJid) {
mBareJid = bareJid;
}
/**
* Name attribute mutator.
* @param name A String containing the author's name of the message.
*/
@SuppressWarnings("unused")
public void setName(String name) {
mName = name;
}
/**
* Message attribute mutator.
* @param message A String containing a message.
*/
public void setMessage(String message) {
mMessage = message;
}
}
/**
* We will use a MessageView to display each message.
*/
private class MessageView extends LinearLayout {
private final TextView mName;
private final TextView mMessage;
/**
* Constructor.
* @param context The context of the MessageView
* @param name A String containing the message's author.
* @param message A String containing the message.
*/
public MessageView(final Context context, final String name, final String message) {
super(context);
this.setOrientation(VERTICAL);
mName = new TextView(context);
mName.setText(name);
addView(mName, new LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
mMessage = new TextView(context);
mMessage.setText(message);
addView(mMessage, new LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
}
/**
* Convenience method to set the title of a MessageView.
* @param name A String containing the message's author.
*/
public void setName(String name) {
mName.setText(name);
}
/**
* Convenience method to set the dialogue of a MessageView.
* @param message A String containing the message.
*/
public void setMessage(String message) {
mMessage.setText(message);
}
}
/**
* {@inheritDoc}.
*/
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.d(TAG, "KeyEvent = " + event.getAction());
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
sendMessage();
return true;
default:
return false;
}
}
return false;
}
/**
* Send an XMPP message.
*/
private void sendMessage() {
final String inputContent = mInputField.getText().toString();
Log.v(TAG, "BEGIN sendMessage.");
if (!"".equals(inputContent)) {
Message msgToSend = new Message(mContact.getJID(), Message.MSG_TYPE_CHAT);
msgToSend.setBody(inputContent);
try {
mChat.sendMessage(msgToSend);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
final String self = getString(R.string.chat_self);
MessageText lastMessage = mListMessages.size() != 0 ? mListMessages.get(mListMessages.size() - 1) : null;
if (lastMessage != null && lastMessage.getName().equals(self)) {
lastMessage.setMessage(lastMessage.getMessage().concat("\n" + inputContent));
mListMessages.set(mListMessages.size() - 1, lastMessage);
} else
mListMessages.add(new MessageText(self, self, inputContent));
mMessagesListAdapter.notifyDataSetChanged();
mInputField.setText(null);
}
Log.v(TAG, "END sendMessage.");
}
}