--- a/src/com/beem/project/beem/ui/Chat.java Fri Nov 06 18:00:19 2009 +0100
+++ b/src/com/beem/project/beem/ui/Chat.java Fri Nov 06 18:00:49 2009 +0100
@@ -1,30 +1,50 @@
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 org.jivesoftware.smackx.ChatState;
import android.app.Activity;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
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.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
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;
public class Chat extends Activity {
@@ -34,17 +54,28 @@
SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
}
- private Handler _handler = new Handler();
+ private Handler mHandler = new Handler();
- private IRoster _roster;
- private Contact _contact;
+ private IRoster mRoster;
+ private Contact mContact;
- private TextView _contactNameTextView;
- private TextView _contactStatusMsgTextView;
- private EditText _input;
+ private TextView mContactNameTextView;
+ private TextView mContactStatusMsgTextView;
+ private ImageView mContactStatusIcon;
+ private ListView mMessagesListView;
+ private EditText mInputField;
+ private Map<Integer, Bitmap> mStatusIconsMap = new HashMap<Integer, Bitmap>();
+
+ private List<MessageText> mListMessages = new ArrayList<MessageText>();
- private final ServiceConnection _conn = new BeemServiceConnection();
- private BeemBroadcastReceiver _broadcastReceiver;
+ private IChat mChat;
+ private IChatManager mChatManager;
+ private IChatManagerListener mChatManagerListener;
+ private IMessageListener mMessageListener;
+ private MessagesListAdapter mMessagesListAdapter;
+
+ private final ServiceConnection mConn = new BeemServiceConnection();
+ private BeemBroadcastReceiver mBroadcastReceiver;
/**
@@ -60,13 +91,30 @@
protected void onCreate(Bundle savedBundle) {
super.onCreate(savedBundle);
- _contactNameTextView = (TextView) findViewById(R.id.chat_contact_name);
- _contactStatusMsgTextView = (TextView) findViewById(R.id.chat_contact_status_msg);
-
+ Log.v(TAG, "BEGIN onCreate.");
setContentView(R.layout.chat);
+ mMessagesListAdapter = new MessagesListAdapter(this);
- _broadcastReceiver = new BeemBroadcastReceiver(_conn);
- this.registerReceiver(_broadcastReceiver, new IntentFilter(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED));
+ mHandler = new Handler();
+
+ // 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);
+
+ prepareIconsStatus();
+
+ Log.v(TAG, "END onCreate.");
}
/**
@@ -74,7 +122,17 @@
*/
protected void onDestroy() {
super.onDestroy();
- this.unregisterReceiver(_broadcastReceiver);
+
+ Log.v(TAG, "BEGIN onDestroy.");
+ this.unregisterReceiver(mBroadcastReceiver);
+ if (mChatManager != null) {
+ try {
+ mChatManager.removeChatCreationListener(mChatManagerListener);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+ Log.v(TAG, "END onDestroy.");
}
/**
@@ -82,6 +140,10 @@
*/
protected void onStart() {
super.onStart();
+
+ Log.v(TAG, "BEGIN onStart.");
+ bindService(new Intent(this, BeemService.class), mConn, BIND_AUTO_CREATE);
+ Log.v(TAG, "END onStart.");
}
/**
@@ -89,12 +151,45 @@
*/
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());
+ }
+ }
+ if (mBroadcastReceiver.isBinded()) {
+ unbindService(mConn);
+ }
+ Log.v(TAG, "END onStop.");
}
+ /**
+ * {@inheritDoc}.
+ */
+ protected void onResume() {
+ super.onResume();
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ protected void onPause() {
+ super.onPause();
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
- _contact = new Contact(intent.getData());
+ Log.v(TAG, "BEGIN onNewIntent.");
+ mContact = new Contact(intent.getData());
+ updateContactInformations();
+ Log.v(TAG, "END onNewIntent.");
}
/**
@@ -104,23 +199,43 @@
*/
private final class BeemServiceConnection implements ServiceConnection {
- private IXmppFacade _xmppFacade;
+ private IXmppFacade mXmppFacade;
+ private final BeemRosterListener mBeemRosterListener = new BeemRosterListener();
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- _xmppFacade = IXmppFacade.Stub.asInterface(service);
- _broadcastReceiver.setBinded(true);
+ Log.v(TAG, "BEGIN onServiceConnected.");
+ mXmppFacade = IXmppFacade.Stub.asInterface(service);
+ mBroadcastReceiver.setBinded(true);
try {
- _roster = _xmppFacade.getRoster();
+ mChatManager = mXmppFacade.getChatManager();
+
+ mRoster = mXmppFacade.getRoster();
+ mRoster.addRosterListener(mBeemRosterListener);
+
+ mChat = mChatManager.createChat((mContact = new Contact(getIntent().getData())), mMessageListener);
+ mChat.setOpen(true);
+ mChatManager.deleteChatNotification(mChat);
+
+ updateContactInformations();
+ updateContactStatusIcon();
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
+ Log.v(TAG, "END onServiceConnected.");
}
@Override
public void onServiceDisconnected(ComponentName name) {
- _xmppFacade = null;
- _broadcastReceiver.setBinded(false);
+ 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.");
}
}
@@ -154,8 +269,17 @@
@Override
public void onPresenceChanged(PresenceAdapter presence) throws RemoteException {
- // TODO Auto-generated method stub
-
+ Log.v(TAG, "BEGIN onPresenceChanged.");
+ if (mContact.getJID().equals(StringUtils.parseBareAddress(presence.getFrom()))) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ updateContactInformations();
+ updateContactStatusIcon();
+ }
+ });
+ }
+ Log.v(TAG, "END onPresenceChanged.");
}
}
@@ -167,14 +291,199 @@
private class OnMessageListener extends IMessageListener.Stub {
@Override
- public void processMessage(IChat chat, Message msg) throws RemoteException {
- // TODO Auto-generated method stub
+ public void processMessage(IChat chat, final Message msg) throws RemoteException {
+ Log.v(TAG, "BEGIN processMessage.");
+ mHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ if (msg.getBody() != null && msg.getType() != Message.MSG_TYPE_ERROR) {
+ mListMessages.add(new MessageText(msg.getFrom(), msg.getBody()));
+ mMessagesListAdapter.notifyDataSetChanged();
+ }
+ }
+ });
+ Log.v(TAG, "END processMessage.");
}
@Override
public void stateChanged(IChat chat) throws RemoteException {
- // TODO Auto-generated method stub
-
+ Log.v(TAG, "BEGIN stateChanged.");
+ mHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ }
+ });
+ Log.v(TAG, "END stateChanged.");
+ }
+
+ }
+
+ /**
+ *
+ * @author Jamu
+ *
+ */
+ private class OnChatManagerListener extends IChatManagerListener.Stub {
+ /**
+ * Constructor.
+ */
+ public OnChatManagerListener() {
+ Log.v(TAG, "OnChatManagerListener constructor.");
+ }
+
+ @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());
+ if (mContact.getMsgState() == null)
+ mContactStatusMsgTextView.setText("Message de status de test de la mort tres tres long, voir meme trop long!");
+ else
+ 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));
+ }
+
+ private class MessagesListAdapter extends BaseAdapter {
+
+ private Context mContext;
+
+ public MessagesListAdapter(Context context) {
+ mContext = context;
+ }
+
+ public int getCount() {
+ return mListMessages.size();
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return 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());
+ }
+
+ return sv;
+ }
+ }
+
+ private class MessageText {
+ private String mName;
+ private String mMessage;
+
+ public MessageText(String name, String message) {
+ mName = name;
+ mMessage = message;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public String getMessage() {
+ return mMessage;
+ }
+
+ public void setName(String name) {
+ mName = name;
+ }
+
+ public void setMessage(String message) {
+ mMessage = message;
+ }
+ }
+
+ /**
+ * We will use a MessageView to display each message.
+ */
+ private class MessageView extends LinearLayout {
+ private TextView mName;
+ private TextView mMessage;
+
+ /**
+ * Constructor.
+ * @param context
+ * @param name
+ * @param message
+ */
+ public MessageView(Context context, String name, String message) {
+ super(context);
+
+ this.setOrientation(VERTICAL);
+
+ mName = new TextView(context);
+ mName.setText(name);
+ addView(mName, new LinearLayout.LayoutParams(
+ LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
+
+ mMessage = new TextView(context);
+ mMessage.setText(message);
+ addView(mMessage, new LinearLayout.LayoutParams(
+ LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
+ }
+
+ /**
+ * Convenience method to set the title of a MessageView
+ */
+ public void setName(String name) {
+ mName.setText(name);
+ }
+
+ /**
+ * Convenience method to set the dialogue of a MessageView
+ */
+ public void setMessage(String message) {
+ mMessage.setText(message);
+ }
+ }
}