ConversationFragment.java

  1package eu.siacs.conversations.ui;
  2
  3import java.util.ArrayList;
  4import java.util.List;
  5import java.util.Set;
  6
  7import net.java.otr4j.session.SessionStatus;
  8import eu.siacs.conversations.R;
  9import eu.siacs.conversations.crypto.PgpEngine;
 10import eu.siacs.conversations.entities.Account;
 11import eu.siacs.conversations.entities.Contact;
 12import eu.siacs.conversations.entities.Conversation;
 13import eu.siacs.conversations.entities.Message;
 14import eu.siacs.conversations.entities.MucOptions;
 15import eu.siacs.conversations.entities.Presences;
 16import eu.siacs.conversations.services.XmppConnectionService;
 17import eu.siacs.conversations.ui.EditMessage.OnEnterPressed;
 18import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected;
 19import eu.siacs.conversations.ui.XmppActivity.OnValueEdited;
 20import eu.siacs.conversations.ui.adapter.MessageAdapter;
 21import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked;
 22import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked;
 23import eu.siacs.conversations.utils.UIHelper;
 24import android.app.AlertDialog;
 25import android.app.Fragment;
 26import android.app.PendingIntent;
 27import android.content.Context;
 28import android.content.DialogInterface;
 29import android.content.Intent;
 30import android.content.IntentSender;
 31import android.content.IntentSender.SendIntentException;
 32import android.os.Bundle;
 33import android.text.Editable;
 34import android.text.Selection;
 35import android.view.Gravity;
 36import android.view.KeyEvent;
 37import android.view.LayoutInflater;
 38import android.view.View;
 39import android.view.View.OnClickListener;
 40import android.view.ViewGroup;
 41import android.view.inputmethod.EditorInfo;
 42import android.view.inputmethod.InputMethodManager;
 43import android.widget.AbsListView.OnScrollListener;
 44import android.widget.TextView.OnEditorActionListener;
 45import android.widget.AbsListView;
 46
 47import android.widget.ListView;
 48import android.widget.ImageButton;
 49import android.widget.RelativeLayout;
 50import android.widget.TextView;
 51import android.widget.Toast;
 52
 53public class ConversationFragment extends Fragment {
 54
 55	protected Conversation conversation;
 56	protected ListView messagesView;
 57	protected LayoutInflater inflater;
 58	protected List<Message> messageList = new ArrayList<Message>();
 59	protected MessageAdapter messageListAdapter;
 60	protected Contact contact;
 61
 62	protected String queuedPqpMessage = null;
 63
 64	private EditMessage mEditMessage;
 65	private ImageButton mSendButton;
 66	private String pastedText = null;
 67	private RelativeLayout snackbar;
 68	private TextView snackbarMessage;
 69	private TextView snackbarAction;
 70
 71	private boolean messagesLoaded = false;
 72
 73	private IntentSender askForPassphraseIntent = null;
 74
 75	private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() {
 76
 77		@Override
 78		public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
 79			if (actionId == EditorInfo.IME_ACTION_DONE) {
 80				InputMethodManager imm = (InputMethodManager) v.getContext()
 81						.getSystemService(Context.INPUT_METHOD_SERVICE);
 82				imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
 83				return true;
 84			} else {
 85				return false;
 86			}
 87		}
 88	};
 89
 90	private OnClickListener mSendButtonListener = new OnClickListener() {
 91
 92		@Override
 93		public void onClick(View v) {
 94			sendMessage();
 95		}
 96	};
 97	protected OnClickListener clickToDecryptListener = new OnClickListener() {
 98
 99		@Override
100		public void onClick(View v) {
101			if (activity.hasPgp() && askForPassphraseIntent != null) {
102				try {
103					getActivity().startIntentSenderForResult(
104							askForPassphraseIntent,
105							ConversationActivity.REQUEST_DECRYPT_PGP, null, 0,
106							0, 0);
107				} catch (SendIntentException e) {
108					//
109				}
110			}
111		}
112	};
113
114	private OnClickListener clickToMuc = new OnClickListener() {
115
116		@Override
117		public void onClick(View v) {
118			Intent intent = new Intent(getActivity(),
119					ConferenceDetailsActivity.class);
120			intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC);
121			intent.putExtra("uuid", conversation.getUuid());
122			startActivity(intent);
123		}
124	};
125
126	private OnClickListener leaveMuc = new OnClickListener() {
127
128		@Override
129		public void onClick(View v) {
130			activity.endConversation(conversation);
131		}
132	};
133
134	private OnClickListener enterPassword = new OnClickListener() {
135
136		@Override
137		public void onClick(View v) {
138			MucOptions muc = conversation.getMucOptions();
139			String password = muc.getPassword();
140			if (password == null) {
141				password = "";
142			}
143			activity.quickPasswordEdit(password, new OnValueEdited() {
144
145				@Override
146				public void onValueEdited(String value) {
147					activity.xmppConnectionService.providePasswordForMuc(
148							conversation, value);
149				}
150			});
151		}
152	};
153
154	private OnScrollListener mOnScrollListener = new OnScrollListener() {
155
156		@Override
157		public void onScrollStateChanged(AbsListView view, int scrollState) {
158			// TODO Auto-generated method stub
159
160		}
161
162		@Override
163		public void onScroll(AbsListView view, int firstVisibleItem,
164				int visibleItemCount, int totalItemCount) {
165			if (firstVisibleItem == 0 && messagesLoaded) {
166				long timestamp = messageList.get(0).getTimeSent();
167				messagesLoaded = false;
168				List<Message> messages = activity.xmppConnectionService
169						.getMoreMessages(conversation, timestamp);
170				messageList.addAll(0, messages);
171				messageListAdapter.notifyDataSetChanged();
172				if (messages.size() != 0) {
173					messagesLoaded = true;
174				}
175				messagesView.setSelectionFromTop(messages.size() + 1, 0);
176			}
177		}
178	};
179
180	private ConversationActivity activity;
181
182	private void sendMessage() {
183		if (this.conversation == null) {
184			return;
185		}
186		if (mEditMessage.getText().length() < 1) {
187			if (this.conversation.getMode() == Conversation.MODE_MULTI) {
188				conversation.setNextPresence(null);
189				updateChatMsgHint();
190			}
191			return;
192		}
193		Message message = new Message(conversation, mEditMessage.getText()
194				.toString(), conversation.getNextEncryption(activity
195				.forceEncryption()));
196		if (conversation.getMode() == Conversation.MODE_MULTI) {
197			if (conversation.getNextPresence() != null) {
198				message.setPresence(conversation.getNextPresence());
199				message.setType(Message.TYPE_PRIVATE);
200				conversation.setNextPresence(null);
201			}
202		}
203		if (conversation.getNextEncryption(activity.forceEncryption()) == Message.ENCRYPTION_OTR) {
204			sendOtrMessage(message);
205		} else if (conversation.getNextEncryption(activity.forceEncryption()) == Message.ENCRYPTION_PGP) {
206			sendPgpMessage(message);
207		} else {
208			sendPlainTextMessage(message);
209		}
210	}
211
212	public void updateChatMsgHint() {
213		if (conversation.getMode() == Conversation.MODE_MULTI
214				&& conversation.getNextPresence() != null) {
215			this.mEditMessage.setHint(getString(
216					R.string.send_private_message_to,
217					conversation.getNextPresence()));
218		} else {
219			switch (conversation.getNextEncryption(activity.forceEncryption())) {
220			case Message.ENCRYPTION_NONE:
221				mEditMessage
222						.setHint(getString(R.string.send_plain_text_message));
223				break;
224			case Message.ENCRYPTION_OTR:
225				mEditMessage.setHint(getString(R.string.send_otr_message));
226				break;
227			case Message.ENCRYPTION_PGP:
228				mEditMessage.setHint(getString(R.string.send_pgp_message));
229				break;
230			default:
231				break;
232			}
233		}
234	}
235
236	@Override
237	public View onCreateView(final LayoutInflater inflater,
238			ViewGroup container, Bundle savedInstanceState) {
239		final View view = inflater.inflate(R.layout.fragment_conversation,
240				container, false);
241		mEditMessage = (EditMessage) view.findViewById(R.id.textinput);
242		mEditMessage.setOnClickListener(new OnClickListener() {
243
244			@Override
245			public void onClick(View v) {
246				if (activity.getSlidingPaneLayout().isSlideable()) {
247					activity.getSlidingPaneLayout().closePane();
248				}
249			}
250		});
251		mEditMessage.setOnEditorActionListener(mEditorActionListener);
252		mEditMessage.setOnEnterPressedListener(new OnEnterPressed() {
253
254			@Override
255			public void onEnterPressed() {
256				sendMessage();
257			}
258		});
259
260		mSendButton = (ImageButton) view.findViewById(R.id.textSendButton);
261		mSendButton.setOnClickListener(this.mSendButtonListener);
262
263		snackbar = (RelativeLayout) view.findViewById(R.id.snackbar);
264		snackbarMessage = (TextView) view.findViewById(R.id.snackbar_message);
265		snackbarAction = (TextView) view.findViewById(R.id.snackbar_action);
266
267		messagesView = (ListView) view.findViewById(R.id.messages_view);
268		messagesView.setOnScrollListener(mOnScrollListener);
269		messagesView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
270		messageListAdapter = new MessageAdapter(
271				(ConversationActivity) getActivity(), this.messageList);
272		messageListAdapter
273				.setOnContactPictureClicked(new OnContactPictureClicked() {
274
275					@Override
276					public void onContactPictureClicked(Message message) {
277						if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
278							if (message.getPresence() != null) {
279								highlightInConference(message.getPresence());
280							} else {
281								highlightInConference(message.getCounterpart());
282							}
283						}
284					}
285				});
286		messageListAdapter
287				.setOnContactPictureLongClicked(new OnContactPictureLongClicked() {
288
289					@Override
290					public void onContactPictureLongClicked(Message message) {
291						if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
292							if (message.getPresence() != null) {
293								privateMessageWith(message.getPresence());
294							} else {
295								privateMessageWith(message.getCounterpart());
296							}
297						}
298					}
299				});
300		messagesView.setAdapter(messageListAdapter);
301
302		return view;
303	}
304
305	protected void privateMessageWith(String counterpart) {
306		this.mEditMessage.setText("");
307		this.conversation.setNextPresence(counterpart);
308		updateChatMsgHint();
309	}
310
311	protected void highlightInConference(String nick) {
312		String oldString = mEditMessage.getText().toString().trim();
313		if (oldString.isEmpty() || mEditMessage.getSelectionStart() == 0) {
314			mEditMessage.getText().insert(0, nick + ": ");
315		} else {
316			if (mEditMessage.getText().charAt(
317					mEditMessage.getSelectionStart() - 1) != ' ') {
318				nick = " " + nick;
319			}
320			mEditMessage.getText().insert(mEditMessage.getSelectionStart(),
321					nick + " ");
322		}
323	}
324
325	@Override
326	public void onStart() {
327		super.onStart();
328		this.activity = (ConversationActivity) getActivity();
329		if (activity.xmppConnectionServiceBound) {
330			this.onBackendConnected();
331		}
332	}
333
334	@Override
335	public void onStop() {
336		super.onStop();
337		if (this.conversation != null) {
338			this.conversation.setNextMessage(mEditMessage.getText().toString());
339		}
340	}
341
342	public void onBackendConnected() {
343		this.activity = (ConversationActivity) getActivity();
344		this.conversation = activity.getSelectedConversation();
345		if (this.conversation == null) {
346			return;
347		}
348		String oldString = conversation.getNextMessage().trim();
349		if (this.pastedText == null) {
350			this.mEditMessage.setText(oldString);
351		} else {
352
353			if (oldString.isEmpty()) {
354				mEditMessage.setText(pastedText);
355			} else {
356				mEditMessage.setText(oldString + " " + pastedText);
357			}
358			pastedText = null;
359		}
360		int position = mEditMessage.length();
361		Editable etext = mEditMessage.getText();
362		Selection.setSelection(etext, position);
363		if (activity.getSlidingPaneLayout().isSlideable()) {
364			if (!activity.shouldPaneBeOpen()) {
365				activity.getSlidingPaneLayout().closePane();
366				activity.getActionBar().setDisplayHomeAsUpEnabled(true);
367				activity.getActionBar().setHomeButtonEnabled(true);
368				activity.getActionBar().setTitle(conversation.getName());
369				activity.invalidateOptionsMenu();
370			}
371		}
372		if (this.conversation.getMode() == Conversation.MODE_MULTI) {
373			conversation.setNextPresence(null);
374		}
375		updateMessages();
376	}
377
378	private void decryptMessage(Message message) {
379		PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
380		if (engine != null) {
381			engine.decrypt(message, new UiCallback<Message>() {
382
383				@Override
384				public void userInputRequried(PendingIntent pi, Message message) {
385					askForPassphraseIntent = pi.getIntentSender();
386					showSnackbar(R.string.openpgp_messages_found,
387							R.string.decrypt, clickToDecryptListener);
388				}
389
390				@Override
391				public void success(Message message) {
392					activity.xmppConnectionService.databaseBackend
393							.updateMessage(message);
394					updateMessages();
395				}
396
397				@Override
398				public void error(int error, Message message) {
399					message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
400					// updateMessages();
401				}
402			});
403		}
404	}
405
406	public void updateMessages() {
407		if (getView() == null) {
408			return;
409		}
410		hideSnackbar();
411		final ConversationActivity activity = (ConversationActivity) getActivity();
412		if (this.conversation != null) {
413			final Contact contact = this.conversation.getContact();
414			if (this.conversation.isMuted()) {
415				showSnackbar(R.string.notifications_disabled, R.string.enable,
416						new OnClickListener() {
417
418							@Override
419							public void onClick(View v) {
420								conversation.setMutedTill(0);
421								updateMessages();
422							}
423						});
424			} else if (!contact.showInRoster()
425					&& contact
426							.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
427				showSnackbar(R.string.contact_added_you, R.string.add_back,
428						new OnClickListener() {
429
430							@Override
431							public void onClick(View v) {
432								activity.xmppConnectionService
433										.createContact(contact);
434								activity.switchToContactDetails(contact);
435							}
436						});
437			}
438			for (Message message : this.conversation.getMessages()) {
439				if ((message.getEncryption() == Message.ENCRYPTION_PGP)
440						&& ((message.getStatus() == Message.STATUS_RECEIVED) || (message
441								.getStatus() == Message.STATUS_SEND))) {
442					decryptMessage(message);
443					break;
444				}
445			}
446			this.messageList.clear();
447			if (this.conversation.getMessages().size() == 0) {
448				messagesLoaded = false;
449			} else {
450				this.messageList.addAll(this.conversation.getMessages());
451				messagesLoaded = true;
452				updateStatusMessages();
453			}
454			this.messageListAdapter.notifyDataSetChanged();
455			if (conversation.getMode() == Conversation.MODE_SINGLE) {
456				if (messageList.size() >= 1) {
457					makeFingerprintWarning(conversation.getLatestEncryption());
458				}
459			} else {
460				if (!conversation.getMucOptions().online()
461						&& conversation.getAccount().getStatus() == Account.STATUS_ONLINE) {
462					int error = conversation.getMucOptions().getError();
463					switch (error) {
464					case MucOptions.ERROR_NICK_IN_USE:
465						showSnackbar(R.string.nick_in_use, R.string.edit,
466								clickToMuc);
467						break;
468					case MucOptions.ERROR_ROOM_NOT_FOUND:
469						showSnackbar(R.string.conference_not_found,
470								R.string.leave, leaveMuc);
471						break;
472					case MucOptions.ERROR_PASSWORD_REQUIRED:
473						showSnackbar(R.string.conference_requires_password,
474								R.string.enter_password, enterPassword);
475						break;
476					default:
477						break;
478					}
479				}
480			}
481			getActivity().invalidateOptionsMenu();
482			updateChatMsgHint();
483			if (!activity.shouldPaneBeOpen()) {
484				activity.xmppConnectionService.markRead(conversation);
485				UIHelper.updateNotification(getActivity(),
486						activity.getConversationList(), null, false);
487				activity.updateConversationList();
488			}
489			this.updateSendButton();
490		}
491	}
492
493	private void messageSent() {
494		int size = this.messageList.size();
495		if (size >= 1) {
496			messagesView.setSelection(size - 1);
497		}
498		mEditMessage.setText("");
499		updateChatMsgHint();
500	}
501
502	public void updateSendButton() {
503		Conversation c = this.conversation;
504		if (activity.useSendButtonToIndicateStatus() && c != null
505				&& c.getAccount().getStatus() == Account.STATUS_ONLINE) {
506			if (c.getMode() == Conversation.MODE_SINGLE) {
507				switch (c.getContact().getMostAvailableStatus()) {
508				case Presences.CHAT:
509					this.mSendButton
510							.setImageResource(R.drawable.ic_action_send_now_online);
511					break;
512				case Presences.ONLINE:
513					this.mSendButton
514							.setImageResource(R.drawable.ic_action_send_now_online);
515					break;
516				case Presences.AWAY:
517					this.mSendButton
518							.setImageResource(R.drawable.ic_action_send_now_away);
519					break;
520				case Presences.XA:
521					this.mSendButton
522							.setImageResource(R.drawable.ic_action_send_now_away);
523					break;
524				case Presences.DND:
525					this.mSendButton
526							.setImageResource(R.drawable.ic_action_send_now_dnd);
527					break;
528				default:
529					this.mSendButton
530							.setImageResource(R.drawable.ic_action_send_now_offline);
531					break;
532				}
533			} else if (c.getMode() == Conversation.MODE_MULTI) {
534				if (c.getMucOptions().online()) {
535					this.mSendButton
536							.setImageResource(R.drawable.ic_action_send_now_online);
537				} else {
538					this.mSendButton
539							.setImageResource(R.drawable.ic_action_send_now_offline);
540				}
541			} else {
542				this.mSendButton
543						.setImageResource(R.drawable.ic_action_send_now_offline);
544			}
545		} else {
546			this.mSendButton
547					.setImageResource(R.drawable.ic_action_send_now_offline);
548		}
549	}
550
551	protected void updateStatusMessages() {
552		if (conversation.getMode() == Conversation.MODE_SINGLE) {
553			for (int i = this.messageList.size() - 1; i >= 0; --i) {
554				if (this.messageList.get(i).getStatus() == Message.STATUS_RECEIVED) {
555					return;
556				} else {
557					if (this.messageList.get(i).getStatus() == Message.STATUS_SEND_DISPLAYED) {
558						this.messageList.add(i + 1,
559								Message.createStatusMessage(conversation));
560						return;
561					}
562				}
563			}
564		}
565	}
566
567	protected void makeFingerprintWarning(int latestEncryption) {
568		Set<String> knownFingerprints = conversation.getContact()
569				.getOtrFingerprints();
570		if ((latestEncryption == Message.ENCRYPTION_OTR)
571				&& (conversation.hasValidOtrSession()
572						&& (!conversation.isMuted())
573						&& (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
574							.contains(conversation.getOtrFingerprint())))) {
575			showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify,
576					new OnClickListener() {
577
578						@Override
579						public void onClick(View v) {
580							if (conversation.getOtrFingerprint() != null) {
581								AlertDialog dialog = UIHelper
582										.getVerifyFingerprintDialog(
583												(ConversationActivity) getActivity(),
584												conversation, snackbar);
585								dialog.show();
586							}
587						}
588					});
589		}
590	}
591
592	protected void showSnackbar(int message, int action,
593			OnClickListener clickListener) {
594		snackbar.setVisibility(View.VISIBLE);
595		snackbar.setOnClickListener(null);
596		snackbarMessage.setText(message);
597		snackbarMessage.setOnClickListener(null);
598		snackbarAction.setText(action);
599		snackbarAction.setOnClickListener(clickListener);
600	}
601
602	protected void hideSnackbar() {
603		snackbar.setVisibility(View.GONE);
604	}
605
606	protected void sendPlainTextMessage(Message message) {
607		ConversationActivity activity = (ConversationActivity) getActivity();
608		activity.xmppConnectionService.sendMessage(message);
609		messageSent();
610	}
611
612	protected void sendPgpMessage(final Message message) {
613		final ConversationActivity activity = (ConversationActivity) getActivity();
614		final XmppConnectionService xmppService = activity.xmppConnectionService;
615		final Contact contact = message.getConversation().getContact();
616		if (activity.hasPgp()) {
617			if (conversation.getMode() == Conversation.MODE_SINGLE) {
618				if (contact.getPgpKeyId() != 0) {
619					xmppService.getPgpEngine().hasKey(contact,
620							new UiCallback<Contact>() {
621
622								@Override
623								public void userInputRequried(PendingIntent pi,
624										Contact contact) {
625									activity.runIntent(
626											pi,
627											ConversationActivity.REQUEST_ENCRYPT_MESSAGE);
628								}
629
630								@Override
631								public void success(Contact contact) {
632									messageSent();
633									activity.encryptTextMessage(message);
634								}
635
636								@Override
637								public void error(int error, Contact contact) {
638
639								}
640							});
641
642				} else {
643					showNoPGPKeyDialog(false,
644							new DialogInterface.OnClickListener() {
645
646								@Override
647								public void onClick(DialogInterface dialog,
648										int which) {
649									conversation
650											.setNextEncryption(Message.ENCRYPTION_NONE);
651									message.setEncryption(Message.ENCRYPTION_NONE);
652									xmppService.sendMessage(message);
653									messageSent();
654								}
655							});
656				}
657			} else {
658				if (conversation.getMucOptions().pgpKeysInUse()) {
659					if (!conversation.getMucOptions().everybodyHasKeys()) {
660						Toast warning = Toast
661								.makeText(getActivity(),
662										R.string.missing_public_keys,
663										Toast.LENGTH_LONG);
664						warning.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
665						warning.show();
666					}
667					activity.encryptTextMessage(message);
668					messageSent();
669				} else {
670					showNoPGPKeyDialog(true,
671							new DialogInterface.OnClickListener() {
672
673								@Override
674								public void onClick(DialogInterface dialog,
675										int which) {
676									conversation
677											.setNextEncryption(Message.ENCRYPTION_NONE);
678									message.setEncryption(Message.ENCRYPTION_NONE);
679									xmppService.sendMessage(message);
680									messageSent();
681								}
682							});
683				}
684			}
685		} else {
686			activity.showInstallPgpDialog();
687		}
688	}
689
690	public void showNoPGPKeyDialog(boolean plural,
691			DialogInterface.OnClickListener listener) {
692		AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
693		builder.setIconAttribute(android.R.attr.alertDialogIcon);
694		if (plural) {
695			builder.setTitle(getString(R.string.no_pgp_keys));
696			builder.setMessage(getText(R.string.contacts_have_no_pgp_keys));
697		} else {
698			builder.setTitle(getString(R.string.no_pgp_key));
699			builder.setMessage(getText(R.string.contact_has_no_pgp_key));
700		}
701		builder.setNegativeButton(getString(R.string.cancel), null);
702		builder.setPositiveButton(getString(R.string.send_unencrypted),
703				listener);
704		builder.create().show();
705	}
706
707	protected void sendOtrMessage(final Message message) {
708		final ConversationActivity activity = (ConversationActivity) getActivity();
709		final XmppConnectionService xmppService = activity.xmppConnectionService;
710		if (conversation.hasValidOtrSession()) {
711			activity.xmppConnectionService.sendMessage(message);
712			messageSent();
713		} else {
714			activity.selectPresence(message.getConversation(),
715					new OnPresenceSelected() {
716
717						@Override
718						public void onPresenceSelected() {
719							message.setPresence(conversation.getNextPresence());
720							xmppService.sendMessage(message);
721							messageSent();
722						}
723					});
724		}
725	}
726
727	public void setText(String text) {
728		this.pastedText = text;
729	}
730
731	public void clearInputField() {
732		this.mEditMessage.setText("");
733	}
734}