Lot of modification.
author"Vincent Veronis"
Fri, 14 Oct 2011 18:57:07 +0200
changeset 904 c067ee9a604c
parent 903 ac9461be2bd7
child 905 dfbc48b4eae1
Lot of modification. I dont remember .... i know nc !
AndroidManifest.xml
res/layout/chat.xml
src/com/beem/project/beem/BeemService.java
src/com/beem/project/beem/BeemSync.java
src/com/beem/project/beem/providers/MessageProvider.java
src/com/beem/project/beem/providers/Messages.java
src/com/beem/project/beem/service/BeemChatManager.java
src/com/beem/project/beem/service/ChatAdapter.java
src/com/beem/project/beem/service/XmppConnectionAdapter.java
src/com/beem/project/beem/ui/Chat.java
src/com/beem/project/beem/ui/ContactList.java
--- a/AndroidManifest.xml	Mon Aug 22 22:43:19 2011 +0200
+++ b/AndroidManifest.xml	Fri Oct 14 18:57:07 2011 +0200
@@ -162,8 +162,7 @@
 		<provider
 			android:name=".providers.MessageProvider"
 			android:label="Message Provider"
-			android:authorities="com.beem.project.beem.providers.messageprovider"
-			android:exported="false" />
+			android:authorities="com.beem.project.beem.providers.messageprovider" />
 		<service
 			android:name=".account.AuthenticatorService"
 			android:exported="true"
@@ -244,8 +243,8 @@
 	<uses-permission
 		android:name="android.permission.WRITE_SYNC_SETTINGS" />
 	<uses-sdk
-		android:minSdkVersion="8"
-		android:targetSdkVersion="8" />
+		android:minSdkVersion="7"
+		android:targetSdkVersion="7" />
 	<supports-screens
 		android:largeScreens="true"
 		android:normalScreens="true"
--- a/res/layout/chat.xml	Mon Aug 22 22:43:19 2011 +0200
+++ b/res/layout/chat.xml	Fri Oct 14 18:57:07 2011 +0200
@@ -8,8 +8,8 @@
 		android:background="#222222" android:padding="4px">
 		<ImageView android:id="@+id/chat_contact_status_icon"
 			android:src="@drawable/avatar_status"
-			android:layout_width="48dip"
-			android:layout_height="48dip"
+			android:layout_width="24dip"
+			android:layout_height="24dip"
 			/>
 		<LinearLayout android:orientation="vertical"
 			android:layout_width="fill_parent" android:layout_height="wrap_content"
--- a/src/com/beem/project/beem/BeemService.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/BeemService.java	Fri Oct 14 18:57:07 2011 +0200
@@ -64,6 +64,7 @@
 import android.app.NotificationManager;
 import android.app.Service;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -96,468 +97,435 @@
  */
 public class BeemService extends Service {
 
-    /** The id to use for status notification. */
-    public static final int NOTIFICATION_STATUS_ID = 100;
-
-    private static final String TAG = "BeemService";
-    private static final int MESSAGE_CONNECT = 0x1;
-    private static final int MESSAGE_DISCONNECT = 0x2;
-    private static final int MESSAGE_SEND_MSG = 0x3;
-    private static final int MESSAGE_SYNC = 0x4;
-
-    private NotificationManager mNotificationManager;
-    private Map<String, XmppConnectionAdapter> mConnection = new HashMap<String, XmppConnectionAdapter>();
-    private Map<String, BeemConnection> mBeemConnection = new HashMap<String, BeemConnection>();
-    private Map<String, IXmppFacade.Stub> mBind = new HashMap<String, IXmppFacade.Stub>();
-
-    private boolean mOnOffReceiverIsRegistered;
-    private Handler mHandler;
-    private Looper mServiceLooper;
-    private BeemBroadcastReceiver mReceiver = new BeemBroadcastReceiver();
-    private BeemServicePreferenceListener mPreferenceListener = new BeemServicePreferenceListener();
-    private BeemServiceBroadcastReceiver mOnOffReceiver = new BeemServiceBroadcastReceiver();
-
-    /**
-     * Constructor.
-     */
-    public BeemService() {
-    }
-
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-	if (intent != null) {
-	    handleIntent(intent);
-	}
-	return Service.START_STICKY;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public IBinder onBind(Intent intent) {
-	Log.d(TAG, "ONBIND()");
-	return null;//(IBinder) mBind.get(accountName);
-    }
-
-    @Override
-    public boolean onUnbind(Intent intent) {
-	Log.d(TAG, "ONUNBIND()");
-	boolean isConnected = true;
-	for (XmppConnectionAdapter connection : mConnection.values()) {
-	    if (!connection.getAdaptee().isConnected())
-		isConnected = false;
-	}
-	if (!isConnected) {
-	    this.stopSelf();
-	}
-	return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onCreate() {
-	super.onCreate();
-
-	HandlerThread thread = new HandlerThread("BeemServiceThread");
-	thread.start();
-	mServiceLooper = thread.getLooper();
-	mHandler = new BeemServiceHandler(mServiceLooper);
+	/** The id to use for status notification. */
+	public static final int NOTIFICATION_STATUS_ID = 100;
 
-	//	AccountManager am = AccountManager.get(BeemService.this);
-	//	Account allAccount[] = am.getAccountsByType("com.beem.project.com");
-	//	for (Account account : allAccount) {
-	//	    BeemConnection beemco = new BeemConnection(BeemService.this
-	//		.getSharedPreferences(account.name, MODE_PRIVATE), mPreferenceListener);
-	//	    if (beemco.getSettings().getBoolean("settings_away_chk", false)) {
-	//		mOnOffReceiverIsRegistered = true;
-	//		registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
-	//		registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
-	//	    }
-	//	    mBeemConnection.put(account.name, beemco);
-	//	    XmppConnectionAdapter beemcoAdapter = new XmppConnectionAdapter(beemco.getConnectionConfiguration(), beemco
-	//		.getJid(), beemco.getPassword(), this);
-	//	    mConnection.put(account.name, beemcoAdapter);
-	//	    mBind.put(account.name, new XmppFacade(beemcoAdapter));
-	//	    Log.e(TAG, "Account configuration : " + account.toString() + " DONE");
-	//	}
-	registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
-
-	configure(ProviderManager.getInstance());
-	mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-	Roster.setDefaultSubscriptionMode(SubscriptionMode.manual);
-	Log.d(TAG, "ONCREATE");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onDestroy() {
-	super.onDestroy();
-	mNotificationManager.cancelAll();
-	unregisterReceiver(mReceiver);
-
-	if (mOnOffReceiverIsRegistered)
-	    unregisterReceiver(mOnOffReceiver);
-	for (XmppConnectionAdapter connection : mConnection.values()) {
-	    if (connection.isAuthentificated() && BeemConnectivity.isConnected(this))
-		connection.disconnect();
-	}
-	Log.d(TAG, "ONDESTROY");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onStart(Intent intent, int startId) {
-	super.onStart(intent, startId);
-	Log.d(TAG, "onStart");
-	//	try {
-	//	    for (XmppConnectionAdapter connection : mConnection.values())
-	//		connection.connectAsync();
-	//	} catch (RemoteException e) {
-	//	    e.printStackTrace();
-	//	}
-    }
-
-    public XmppConnectionAdapter getConnection(String accountName) {
-	return mConnection.get(accountName);
-    }
-
-    /**
-     * Show a notification using the preference of the user.
-     * @param id the id of the notification.
-     * @param notif the notification to show
-     */
-    public void sendNotification(int id, Notification notif) {
-	//	if (mSettings.getBoolean(BeemApplication.NOTIFICATION_VIBRATE_KEY, true))
-	//	    notif.defaults |= Notification.DEFAULT_VIBRATE;
-	//	notif.defaults |= Notification.DEFAULT_LIGHTS;
-	//	String ringtoneStr = mSettings.getString(BeemApplication.NOTIFICATION_SOUND_KEY, "");
-	//	notif.sound = Uri.parse(ringtoneStr);
-	//	mNotificationManager.notify(id, notif);
-    }
-
-    /**
-     * Delete a notification.
-     * @param id the id of the notification
-     */
-    public void deleteNotification(int id) {
-	mNotificationManager.cancel(id);
-    }
+	private static final String TAG = "BeemService";
+	private static final int MESSAGE_CONNECT = 0x1;
+	private static final int MESSAGE_DISCONNECT = 0x2;
+	private static final int MESSAGE_SEND_MSG = 0x3;
+	private static final int MESSAGE_SYNC = 0x4;
 
-    /**
-     * Reset the status to online after a disconnect.
-     */
-    public void resetStatus() {
-	for (BeemConnection beemco : mBeemConnection.values()) {
-	    Editor edit = beemco.getSettings().edit();
-	    edit.putInt(BeemApplication.STATUS_KEY, 1);
-	    edit.commit();
-	}
-
-    }
-
-    /**
-     * Initialize Jingle from an XmppConnectionAdapter.
-     * @param adaptee XmppConnection used for jingle.
-     */
-    public void initJingle(XMPPConnection adaptee) {
-    }
-
-    /**
-     * Return a bind to an XmppFacade instance.
-     * @return IXmppFacade a bind to an XmppFacade instance
-     */
-    public IXmppFacade getBind() {
-	//TODO: Prendre le bon mbind dans le tableau
-	return mBind.get(0);
-    }
-
-    /**
-     * Get the preference of the service.
-     * @return the preference
-     */
-    public SharedPreferences getServicePreference(String accountName) {
-	return mBeemConnection.get(accountName).getSettings();
-    }
-
-    /**
-     * Get the notification manager system service.
-     * @return the notification manager service.
-     */
-    public NotificationManager getNotificationManager() {
-	return mNotificationManager;
-    }
-
-    /**
-     * A sort of patch from this thread: http://www.igniterealtime.org/community/thread/31118. Avoid ClassCastException
-     * by bypassing the classloading shit of Smack.
-     * @param pm The ProviderManager.
-     */
-    private void configure(ProviderManager pm) {
-	Log.d(TAG, "configure");
-	// Service Discovery # Items
-	pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
-	// Service Discovery # Info
-	pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
-
-	// Privacy
-	//pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
-	// Delayed Delivery only the new version
-	pm.addExtensionProvider("delay", "urn:xmpp:delay", new DelayInfoProvider());
-
-	// Service Discovery # Items
-	pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
-	// Service Discovery # Info
-	pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
-
-	// Chat State
-	ChatStateExtension.Provider chatState = new ChatStateExtension.Provider();
-	pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", chatState);
-	pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", chatState);
-	pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", chatState);
-	pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", chatState);
-	pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", chatState);
-	// capabilities
-	pm.addExtensionProvider("c", "http://jabber.org/protocol/caps", new CapsProvider());
-	//Pubsub
-	pm.addIQProvider("pubsub", "http://jabber.org/protocol/pubsub", new PubSubProvider());
-	pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider());
-	pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider());
-	pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub", new ItemProvider());
+	private NotificationManager mNotificationManager;
+	private Map<String, XmppConnectionAdapter> mConnection = new HashMap<String, XmppConnectionAdapter>();
+	private Map<String, BeemConnection> mBeemConnection = new HashMap<String, BeemConnection>();
+	private Map<String, IXmppFacade.Stub> mBind = new HashMap<String, IXmppFacade.Stub>();
 
-	pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub#event", new ItemsProvider());
-	pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub#event", new ItemProvider());
-	pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", new EventProvider());
-	//TODO rajouter les manquants pour du full pubsub
-
-	//PEP avatar
-	pm.addExtensionProvider("metadata", "urn:xmpp:avatar:metadata", new AvatarMetadataProvider());
-	pm.addExtensionProvider("data", "urn:xmpp:avatar:data", new AvatarProvider());
-
-	//         PEPProvider pep  = new PEPProvider();
-	//         AvatarMetadataProvider avaMeta  = new AvatarMetadataProvider();
-	//         pep.registerPEPParserExtension("urn:xmpp:avatar:metadata", avaMeta);
-	//         pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", pep);
-
-	/*
-	 * // Private Data Storage pm.addIQProvider("query", "jabber:iq:private", new
-	 * PrivateDataManager.PrivateDataIQProvider()); // Time try { pm.addIQProvider("query", "jabber:iq:time",
-	 * Class.forName("org.jivesoftware.smackx.packet.Time")); } catch (ClassNotFoundException e) {
-	 * Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Time"); } // Roster Exchange
-	 * pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider()); // Message Events
-	 * pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider()); // XHTML
-	 * pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider()); //
-	 * Group Chat Invitations pm.addExtensionProvider("x", "jabber:x:conference", new
-	 * GroupChatInvitation.Provider()); // Data Forms pm.addExtensionProvider("x", "jabber:x:data", new
-	 * DataFormProvider()); // MUC User pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new
-	 * MUCUserProvider()); // MUC Admin pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new
-	 * MUCAdminProvider()); // MUC Owner pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new
-	 * MUCOwnerProvider()); // Version try { pm.addIQProvider("query", "jabber:iq:version",
-	 * Class.forName("org.jivesoftware.smackx.packet.Version")); } catch (ClassNotFoundException e) { // Not sure
-	 * what's happening here. Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Version"); }
-	 * // VCard pm.addIQProvider("vCard", "vcard-temp", new VCardProvider()); // Offline Message Requests
-	 * pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider()); //
-	 * Offline Message Indicator pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new
-	 * OfflineMessageInfo.Provider()); // Last Activity pm.addIQProvider("query", "jabber:iq:last", new
-	 * LastActivity.Provider()); // User Search pm.addIQProvider("query", "jabber:iq:search", new
-	 * UserSearch.Provider()); // SharedGroupsInfo pm.addIQProvider("sharedgroup",
-	 * "http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider()); // JEP-33: Extended
-	 * Stanza Addressing pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new
-	 * MultipleAddressesProvider()); // FileTransfer pm.addIQProvider("si", "http://jabber.org/protocol/si", new
-	 * StreamInitiationProvider()); pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new
-	 * BytestreamsProvider()); pm.addIQProvider("open", "http://jabber.org/protocol/ibb", new IBBProviders.Open());
-	 * pm.addIQProvider("close", "http://jabber.org/protocol/ibb", new IBBProviders.Close());
-	 * pm.addExtensionProvider("data", "http://jabber.org/protocol/ibb", new IBBProviders.Data());
-	 * pm.addIQProvider("command", COMMAND_NAMESPACE, new AdHocCommandDataProvider());
-	 * pm.addExtensionProvider("malformed-action", COMMAND_NAMESPACE, new
-	 * AdHocCommandDataProvider.MalformedActionError()); pm.addExtensionProvider("bad-locale", COMMAND_NAMESPACE,
-	 * new AdHocCommandDataProvider.BadLocaleError()); pm.addExtensionProvider("bad-payload", COMMAND_NAMESPACE, new
-	 * AdHocCommandDataProvider.BadPayloadError()); pm.addExtensionProvider("bad-sessionid", COMMAND_NAMESPACE, new
-	 * AdHocCommandDataProvider.BadSessionIDError()); pm.addExtensionProvider("session-expired", COMMAND_NAMESPACE,
-	 * new AdHocCommandDataProvider.SessionExpiredError());
-	 */
-    }
-
-    /**
-     * Listen on preference changes.
-     */
-    public class BeemServicePreferenceListener implements SharedPreferences.OnSharedPreferenceChangeListener {
-
-	/**
-	 * ctor.
-	 */
-	public BeemServicePreferenceListener() {
-	}
-
-	@Override
-	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
-	    if ("settings_away_chk".equals(key)) {
-		if (sharedPreferences.getBoolean("settings_away_chk", false)) {
-		    mOnOffReceiverIsRegistered = true;
-		    registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
-		    registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
-		} else {
-		    mOnOffReceiverIsRegistered = false;
-		    unregisterReceiver(mOnOffReceiver);
-		}
-	    }
-	}
-    }
-
-    /**
-     * Listen on some Intent broadcast, ScreenOn and ScreenOff.
-     */
-    private class BeemServiceBroadcastReceiver extends BroadcastReceiver {
-
-	private String mOldStatus;
-	private int mOldMode;
+	private boolean mOnOffReceiverIsRegistered;
+	private Handler mHandler;
+	private Looper mServiceLooper;
+	private BeemBroadcastReceiver mReceiver = new BeemBroadcastReceiver();
+	private BeemServicePreferenceListener mPreferenceListener = new BeemServicePreferenceListener();
+	private BeemServiceBroadcastReceiver mOnOffReceiver = new BeemServiceBroadcastReceiver();
 
 	/**
 	 * Constructor.
 	 */
-	public BeemServiceBroadcastReceiver() {
+	public BeemService() {
 	}
 
 	@Override
-	public void onReceive(final Context context, final Intent intent) {
-	    String intentAction = intent.getAction();
-	    if (intentAction.equals(Intent.ACTION_SCREEN_OFF)) {
-		for (Map.Entry<String, XmppConnectionAdapter> item : mConnection.entrySet()) {
-		    XmppConnectionAdapter connection = item.getValue();
-		    mOldMode = connection.getPreviousMode();
-		    mOldStatus = connection.getPreviousStatus();
-		    if (connection.isAuthentificated())
-			connection.changeStatus(Status.CONTACT_STATUS_AWAY, mBeemConnection.get(item.getKey())
-			    .getSettings().getString("settings_away_message", "Away"));
+	public int onStartCommand(Intent intent, int flags, int startId) {
+		if (intent != null) {
+			handleIntent(intent);
 		}
-	    } else if (intentAction.equals(Intent.ACTION_SCREEN_ON)) {
-		for (XmppConnectionAdapter connection : mConnection.values()) {
-		    if (connection.isAuthentificated())
-			connection.changeStatus(mOldMode, mOldStatus);
-		}
-	    }
+		return Service.START_STICKY;
 	}
-    }
 
-    private void handleIntent(Intent intent) {
-	Message msg = null;
-	String action = intent.getAction();
-	if (BeemIntent.ACTION_CONNECT.equals(action)) {
-	    msg = mHandler.obtainMessage(MESSAGE_CONNECT, intent.getExtras());
-	} else if (BeemIntent.ACTION_DISCONNECT.equals(action)) {
-	    msg = mHandler.obtainMessage(MESSAGE_DISCONNECT, intent.getExtras());
-	} else if (BeemIntent.ACTION_SEND_MESSAGE.equals(action)) {
-	    msg = mHandler.obtainMessage(MESSAGE_SEND_MSG, intent.getExtras());
-	} else if (BeemIntent.ACTION_SYNC.equals(action)) {
-	    msg = mHandler.obtainMessage(MESSAGE_SYNC, intent.getExtras());
-	} else {
-	    Log.w(TAG, "Unknown intent " + intent);
-	}
-	if (msg != null)
-	    mHandler.sendMessage(msg);
-    }
-
-    private class BeemServiceHandler extends Handler {
-
-	public BeemServiceHandler(Looper looper) {
-	    super(looper);
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public IBinder onBind(Intent intent) {
+		Log.d(TAG, "ONBIND()");
+		return null;//(IBinder) mBind.get(accountName);
 	}
 
 	@Override
-	public void handleMessage(Message msg) {
-	    Bundle b = (Bundle) msg.obj;
-	    switch (msg.what) {
-		case MESSAGE_CONNECT:
-		    handleConnect(b);
-		    break;
-		case MESSAGE_DISCONNECT:
-		    handleDisconnect(b);
-		    break;
-		case MESSAGE_SEND_MSG:
-		    String account = b.getString(BeemIntent.EXTRA_ACCOUNT);
-		    XmppConnectionAdapter con = mConnection.get(account);
-		    if (con != null) {
-			con.handleMessage(msg);
-		    }
-		    break;
-		case MESSAGE_SYNC:
-		    Account a = b.getParcelable(BeemIntent.EXTRA_ACCOUNT);
-		    Bundle accountName = new Bundle();
-		    accountName.putString(BeemIntent.EXTRA_ACCOUNT, a.name);
-		    //TODO: Connect with option to not show status
-		    handleConnect(accountName);
-		    XmppConnectionAdapter co = mConnection.get(a.name);
-		    if (co != null) {
-			BeemSync sync = new BeemSync(getBaseContext());
-			if (co.getAdaptee() != null)
-			    sync.manageRoster(co.getAdaptee().getRoster(), a);
-		    }
-		    break;
-		default:
-		    Log.w(TAG, "Unknown message " + msg);
-	    }
+	public boolean onUnbind(Intent intent) {
+		Log.d(TAG, "ONUNBIND()");
+		boolean isConnected = true;
+		for (XmppConnectionAdapter connection : mConnection.values()) {
+			if (!connection.getAdaptee().isConnected())
+				isConnected = false;
+		}
+		if (!isConnected) {
+			this.stopSelf();
+		}
+		return true;
 	}
-    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void onCreate() {
+		super.onCreate();
 
-    private void handleConnect(Bundle b) {
-	Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED);
-	res.putExtra(BeemIntent.EXTRA_MESSAGE, R.string.contact_status_msg_offline);
+		HandlerThread thread = new HandlerThread("BeemServiceThread");
+		thread.start();
+		mServiceLooper = thread.getLooper();
+		mHandler = new BeemServiceHandler(mServiceLooper);
+		registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+		configure(ProviderManager.getInstance());
+		mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+		Roster.setDefaultSubscriptionMode(SubscriptionMode.manual);
+		Log.d(TAG, "ONCREATE");
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void onDestroy() {
+		super.onDestroy();
+		mNotificationManager.cancelAll();
+		unregisterReceiver(mReceiver);
 
-	String account = null;
-	if (b != null) {
-	    account = b.getString(BeemIntent.EXTRA_ACCOUNT);
-	    res.putExtra(BeemIntent.EXTRA_ACCOUNT, account);
+		if (mOnOffReceiverIsRegistered)
+			unregisterReceiver(mOnOffReceiver);
+		for (XmppConnectionAdapter connection : mConnection.values()) {
+			if (connection.isAuthentificated() && BeemConnectivity.isConnected(this))
+				connection.disconnect();
+		}
+		Log.d(TAG, "ONDESTROY");
+	}
+
+	public XmppConnectionAdapter getConnection(String accountName) {
+		return mConnection.get(accountName);
 	}
-	if (mConnection.containsKey(account)) {
-	    res.setAction(BeemIntent.ACTION_CONNECTED);
-	} else {
-	    if (account == null) //TODO temporary
-		account = "dummy";
-	    if (account == null) {
-		//connect all
-	    } else {
-		BeemConnection beemco = new BeemConnection(
-		    BeemService.this.getSharedPreferences(account, MODE_PRIVATE), mPreferenceListener);
-		if (beemco.getSettings().getBoolean("settings_away_chk", false)) {
-		    mOnOffReceiverIsRegistered = true;
-		    registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
-		    registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
-		}
-		mBeemConnection.put(account, beemco);
-		XmppConnectionAdapter beemcoAdapter = new XmppConnectionAdapter(beemco.getConnectionConfiguration(),
-		    beemco.getJid(), beemco.getPassword(), this);
+
+	/**
+	 * Show a notification using the preference of the user.
+	 * @param id the id of the notification.
+	 * @param notif the notification to show
+	 */
+	public void sendNotification(int id, Notification notif) {
+		//	if (mSettings.getBoolean(BeemApplication.NOTIFICATION_VIBRATE_KEY, true))
+		//	    notif.defaults |= Notification.DEFAULT_VIBRATE;
+		//	notif.defaults |= Notification.DEFAULT_LIGHTS;
+		//	String ringtoneStr = mSettings.getString(BeemApplication.NOTIFICATION_SOUND_KEY, "");
+		//	notif.sound = Uri.parse(ringtoneStr);
+		//	mNotificationManager.notify(id, notif);
+	}
 
-		try {
-		    Log.i(TAG, "Starting connection of " + account);
-		    if (beemcoAdapter.connectSync()) {
-			mConnection.put(account, beemcoAdapter);
-			mBind.put(account, new XmppFacade(beemcoAdapter));
-			res.setAction(BeemIntent.ACTION_CONNECTED);
-			Log.e(TAG, "Account configuration : " + account.toString() + " DONE");
-		    } else {
-			Log.w(TAG, "Unable to connect " + account);
-			res.putExtra(BeemIntent.EXTRA_MESSAGE, beemcoAdapter.getErrorMessage());
-		    }
-		} catch (RemoteException e) {
-			res.putExtra(BeemIntent.EXTRA_MESSAGE, beemcoAdapter.getErrorMessage());
-		    Log.e(TAG, "Unable to connect " + account, e);
+	/**
+	 * Delete a notification.
+	 * @param id the id of the notification
+	 */
+	public void deleteNotification(int id) {
+		mNotificationManager.cancel(id);
+	}
+
+	/**
+	 * Reset the status to online after a disconnect.
+	 */
+	public void resetStatus() {
+		for (BeemConnection beemco : mBeemConnection.values()) {
+			Editor edit = beemco.getSettings().edit();
+			edit.putInt(BeemApplication.STATUS_KEY, 1);
+			edit.commit();
 		}
 
-	    }	    
+	}
+
+	/**
+	 * Initialize Jingle from an XmppConnectionAdapter.
+	 * @param adaptee XmppConnection used for jingle.
+	 */
+	public void initJingle(XMPPConnection adaptee) {
+	}
+
+	/**
+	 * Return a bind to an XmppFacade instance.
+	 * @return IXmppFacade a bind to an XmppFacade instance
+	 */
+	public IXmppFacade getBind() {
+		//TODO: Prendre le bon mbind dans le tableau
+		return mBind.get(0);
+	}
+
+	/**
+	 * Get the preference of the service.
+	 * @return the preference
+	 */
+	public SharedPreferences getServicePreference(String accountName) {
+		Log.e(TAG, "Account name:" + accountName);
+		return mBeemConnection.get(accountName).getSettings();
+	}
+
+	/**
+	 * Get the notification manager system service.
+	 * @return the notification manager service.
+	 */
+	public NotificationManager getNotificationManager() {
+		return mNotificationManager;
 	}
-	sendBroadcast(res);
-    }
+
+	/**
+	 * A sort of patch from this thread: http://www.igniterealtime.org/community/thread/31118. Avoid ClassCastException
+	 * by bypassing the classloading shit of Smack.
+	 * @param pm The ProviderManager.
+	 */
+	private void configure(ProviderManager pm) {
+		Log.d(TAG, "configure");
+		// Service Discovery # Items
+		pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
+		// Service Discovery # Info
+		pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
+
+		// Privacy
+		//pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
+		// Delayed Delivery only the new version
+		pm.addExtensionProvider("delay", "urn:xmpp:delay", new DelayInfoProvider());
+
+		// Service Discovery # Items
+		pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
+		// Service Discovery # Info
+		pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
+
+		// Chat State
+		ChatStateExtension.Provider chatState = new ChatStateExtension.Provider();
+		pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", chatState);
+		pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", chatState);
+		pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", chatState);
+		pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", chatState);
+		pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", chatState);
+		// capabilities
+		pm.addExtensionProvider("c", "http://jabber.org/protocol/caps", new CapsProvider());
+		//Pubsub
+		pm.addIQProvider("pubsub", "http://jabber.org/protocol/pubsub", new PubSubProvider());
+		pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider());
+		pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider());
+		pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub", new ItemProvider());
+
+		pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub#event", new ItemsProvider());
+		pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub#event", new ItemProvider());
+		pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", new EventProvider());
+		//TODO rajouter les manquants pour du full pubsub
+
+		//PEP avatar
+		pm.addExtensionProvider("metadata", "urn:xmpp:avatar:metadata", new AvatarMetadataProvider());
+		pm.addExtensionProvider("data", "urn:xmpp:avatar:data", new AvatarProvider());
+
+		//         PEPProvider pep  = new PEPProvider();
+		//         AvatarMetadataProvider avaMeta  = new AvatarMetadataProvider();
+		//         pep.registerPEPParserExtension("urn:xmpp:avatar:metadata", avaMeta);
+		//         pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", pep);
+
+		/*
+		 * // Private Data Storage pm.addIQProvider("query", "jabber:iq:private", new
+		 * PrivateDataManager.PrivateDataIQProvider()); // Time try { pm.addIQProvider("query", "jabber:iq:time",
+		 * Class.forName("org.jivesoftware.smackx.packet.Time")); } catch (ClassNotFoundException e) {
+		 * Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Time"); } // Roster Exchange
+		 * pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider()); // Message Events
+		 * pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider()); // XHTML
+		 * pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider()); //
+		 * Group Chat Invitations pm.addExtensionProvider("x", "jabber:x:conference", new
+		 * GroupChatInvitation.Provider()); // Data Forms pm.addExtensionProvider("x", "jabber:x:data", new
+		 * DataFormProvider()); // MUC User pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new
+		 * MUCUserProvider()); // MUC Admin pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new
+		 * MUCAdminProvider()); // MUC Owner pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new
+		 * MUCOwnerProvider()); // Version try { pm.addIQProvider("query", "jabber:iq:version",
+		 * Class.forName("org.jivesoftware.smackx.packet.Version")); } catch (ClassNotFoundException e) { // Not sure
+		 * what's happening here. Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Version"); }
+		 * // VCard pm.addIQProvider("vCard", "vcard-temp", new VCardProvider()); // Offline Message Requests
+		 * pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider()); //
+		 * Offline Message Indicator pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new
+		 * OfflineMessageInfo.Provider()); // Last Activity pm.addIQProvider("query", "jabber:iq:last", new
+		 * LastActivity.Provider()); // User Search pm.addIQProvider("query", "jabber:iq:search", new
+		 * UserSearch.Provider()); // SharedGroupsInfo pm.addIQProvider("sharedgroup",
+		 * "http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider()); // JEP-33: Extended
+		 * Stanza Addressing pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new
+		 * MultipleAddressesProvider()); // FileTransfer pm.addIQProvider("si", "http://jabber.org/protocol/si", new
+		 * StreamInitiationProvider()); pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new
+		 * BytestreamsProvider()); pm.addIQProvider("open", "http://jabber.org/protocol/ibb", new IBBProviders.Open());
+		 * pm.addIQProvider("close", "http://jabber.org/protocol/ibb", new IBBProviders.Close());
+		 * pm.addExtensionProvider("data", "http://jabber.org/protocol/ibb", new IBBProviders.Data());
+		 * pm.addIQProvider("command", COMMAND_NAMESPACE, new AdHocCommandDataProvider());
+		 * pm.addExtensionProvider("malformed-action", COMMAND_NAMESPACE, new
+		 * AdHocCommandDataProvider.MalformedActionError()); pm.addExtensionProvider("bad-locale", COMMAND_NAMESPACE,
+		 * new AdHocCommandDataProvider.BadLocaleError()); pm.addExtensionProvider("bad-payload", COMMAND_NAMESPACE, new
+		 * AdHocCommandDataProvider.BadPayloadError()); pm.addExtensionProvider("bad-sessionid", COMMAND_NAMESPACE, new
+		 * AdHocCommandDataProvider.BadSessionIDError()); pm.addExtensionProvider("session-expired", COMMAND_NAMESPACE,
+		 * new AdHocCommandDataProvider.SessionExpiredError());
+		 */
+	}
+
+	/**
+	 * Listen on preference changes.
+	 */
+	public class BeemServicePreferenceListener implements SharedPreferences.OnSharedPreferenceChangeListener {
+
+		/**
+		 * ctor.
+		 */
+		public BeemServicePreferenceListener() {
+		}
+
+		@Override
+		public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+			if ("settings_away_chk".equals(key)) {
+				if (sharedPreferences.getBoolean("settings_away_chk", false)) {
+					mOnOffReceiverIsRegistered = true;
+					registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+					registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
+				} else {
+					mOnOffReceiverIsRegistered = false;
+					unregisterReceiver(mOnOffReceiver);
+				}
+			}
+		}
+	}
 
-    private void handleDisconnect(Bundle b) {
-	Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED);
-	String account = b.getString(BeemIntent.EXTRA_ACCOUNT);
-	mConnection.remove(account);
-	sendBroadcast(res);
-    }
+	/**
+	 * Listen on some Intent broadcast, ScreenOn and ScreenOff.
+	 */
+	private class BeemServiceBroadcastReceiver extends BroadcastReceiver {
+
+		private String mOldStatus;
+		private int mOldMode;
+
+		/**
+		 * Constructor.
+		 */
+		public BeemServiceBroadcastReceiver() {
+		}
+
+		@Override
+		public void onReceive(final Context context, final Intent intent) {
+			String intentAction = intent.getAction();
+			if (intentAction.equals(Intent.ACTION_SCREEN_OFF)) {
+				for (Map.Entry<String, XmppConnectionAdapter> item : mConnection.entrySet()) {
+					XmppConnectionAdapter connection = item.getValue();
+					mOldMode = connection.getPreviousMode();
+					mOldStatus = connection.getPreviousStatus();
+					if (connection.isAuthentificated())
+						connection.changeStatus(Status.CONTACT_STATUS_AWAY, mBeemConnection.get(item.getKey())
+							.getSettings().getString("settings_away_message", "Away"));
+				}
+			} else if (intentAction.equals(Intent.ACTION_SCREEN_ON)) {
+				for (XmppConnectionAdapter connection : mConnection.values()) {
+					if (connection.isAuthentificated())
+						connection.changeStatus(mOldMode, mOldStatus);
+				}
+			}
+		}
+	}
+
+	private void handleIntent(Intent intent) {
+		Message msg = null;
+		String action = intent.getAction();
+		if (BeemIntent.ACTION_CONNECT.equals(action)) {
+			msg = mHandler.obtainMessage(MESSAGE_CONNECT, intent.getExtras());
+		} else if (BeemIntent.ACTION_DISCONNECT.equals(action)) {
+			msg = mHandler.obtainMessage(MESSAGE_DISCONNECT, intent.getExtras());
+		} else if (BeemIntent.ACTION_SEND_MESSAGE.equals(action)) {
+			msg = mHandler.obtainMessage(MESSAGE_SEND_MSG, intent.getExtras());
+		} else if (BeemIntent.ACTION_SYNC.equals(action)) {
+			msg = mHandler.obtainMessage(MESSAGE_SYNC, intent.getExtras());
+		} else {
+			Log.w(TAG, "Unknown intent " + intent);
+		}
+		if (msg != null)
+			mHandler.sendMessage(msg);
+	}
+
+	private class BeemServiceHandler extends Handler {
+
+		public BeemServiceHandler(Looper looper) {
+			super(looper);
+		}
+
+		@Override
+		public void handleMessage(Message msg) {
+			Bundle b = (Bundle) msg.obj;
+			switch (msg.what) {
+				case MESSAGE_CONNECT:
+					handleConnect(b);
+					break;
+				case MESSAGE_DISCONNECT:
+					handleDisconnect(b);
+					break;
+				case MESSAGE_SEND_MSG:
+					String account = b.getString(BeemIntent.EXTRA_ACCOUNT);
+					XmppConnectionAdapter con = mConnection.get(account);
+					if (con != null) {
+						con.handleMessage(msg);
+					}
+					break;
+				case MESSAGE_SYNC:
+					Account a = b.getParcelable(BeemIntent.EXTRA_ACCOUNT);
+					Bundle accountName = new Bundle();
+					accountName.putString(BeemIntent.EXTRA_ACCOUNT, a.name);
+					//TODO: Connect with option to not show status
+					handleConnect(accountName);
+					XmppConnectionAdapter co = mConnection.get(a.name);
+					if (co != null) {
+						BeemSync sync = new BeemSync(getBaseContext());
+						if (co.getAdaptee() != null)
+							sync.manageRoster(co.getAdaptee().getRoster(), a);
+					}
+					break;
+				default:
+					Log.w(TAG, "Unknown message " + msg);
+			}
+		}
+	}
+
+	private void handleConnect(Bundle b) {
+		Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED);
+		res.putExtra(BeemIntent.EXTRA_MESSAGE, R.string.contact_status_msg_offline);
+
+		String account = null;
+		if (b != null) {
+			account = b.getString(BeemIntent.EXTRA_ACCOUNT);
+			res.putExtra(BeemIntent.EXTRA_ACCOUNT, account);
+		}
+		if (mConnection.containsKey(account)) {
+			res.setAction(BeemIntent.ACTION_CONNECTED);
+		} else {
+			if (account == null) //TODO temporary
+				account = "dummy";
+			if (account == null) {
+				//connect all
+			} else {
+				BeemConnection beemco = new BeemConnection(
+					BeemService.this.getSharedPreferences(account, MODE_PRIVATE), mPreferenceListener);
+				if (beemco.getSettings().getBoolean("settings_away_chk", false)) {
+					mOnOffReceiverIsRegistered = true;
+					registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+					registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
+				}
+				mBeemConnection.put(account, beemco);
+				XmppConnectionAdapter beemcoAdapter = new XmppConnectionAdapter(beemco.getConnectionConfiguration(),
+					beemco.getJid(), beemco.getPassword(), this);
+
+				try {
+					Log.i(TAG, "Starting connection of " + account);
+					if (beemcoAdapter.connectSync()) {
+						mConnection.put(account, beemcoAdapter);
+						mBind.put(account, new XmppFacade(beemcoAdapter));
+						res.setAction(BeemIntent.ACTION_CONNECTED);
+						Log.e(TAG, "Account configuration : " + account.toString() + " DONE");
+					} else {
+						Log.w(TAG, "Unable to connect " + account);
+						res.putExtra(BeemIntent.EXTRA_MESSAGE, beemcoAdapter.getErrorMessage());
+					}
+				} catch (RemoteException e) {
+					res.putExtra(BeemIntent.EXTRA_MESSAGE, beemcoAdapter.getErrorMessage());
+					Log.e(TAG, "Unable to connect " + account, e);
+				}
+
+			}
+		}
+		sendBroadcast(res);
+	}
+
+	private void handleDisconnect(Bundle b) {
+		Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED);
+		String account = b.getString(BeemIntent.EXTRA_ACCOUNT);
+		mConnection.remove(account);
+		sendBroadcast(res);
+	}
 }
--- a/src/com/beem/project/beem/BeemSync.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/BeemSync.java	Fri Oct 14 18:57:07 2011 +0200
@@ -58,288 +58,288 @@
  */
 public class BeemSync {
 
-    private static final String TAG = "BeemSync";
-    private static final int NB_DB_OPERATION = 50;
+	private static final String TAG = "BeemSync";
+	private static final int NB_DB_OPERATION = 50;
 
-    private Context mContext;
+	private Context mContext;
 
-    /**
-     * Constructor.
-     * @param c the context parameter.
-     */
-    public BeemSync(Context c) {
-	mContext = c;
-    }
+	/**
+	 * Constructor.
+	 * @param c the context parameter.
+	 */
+	public BeemSync(Context c) {
+		mContext = c;
+	}
 
-    /**
-     * Method to execute content provider operation.
-     * @param ops
-     */
-    private void executeOperation(final ArrayList<ContentProviderOperation> ops) {
-	try {
-	    mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
-	} catch (RemoteException e) {
-	    Log.d(TAG, "Error during sync of contact", e);
-	} catch (OperationApplicationException e) {
-	    Log.d(TAG, "Error during sync of contact", e);
+	/**
+	 * Method to execute content provider operation.
+	 * @param ops
+	 */
+	private void executeOperation(final ArrayList<ContentProviderOperation> ops) {
+		try {
+			mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+		} catch (RemoteException e) {
+			Log.d(TAG, "Error during sync of contact", e);
+		} catch (OperationApplicationException e) {
+			Log.d(TAG, "Error during sync of contact", e);
+		}
+		ops.clear();
 	}
-	ops.clear();
-    }
 
-    /**
-     * Roster sync method.
-     * @param r The roster to sync
-     * @param a The account related
-     */
-    public void manageRoster(final Roster r, final Account a) {
-	if (r == null) {
-	    Log.w(TAG, "Roster is null cant sync informations");
-	    return;
+	/**
+	 * Roster sync method.
+	 * @param r The roster to sync
+	 * @param a The account related
+	 */
+	public void manageRoster(final Roster r, final Account a) {
+		if (r == null) {
+			Log.w(TAG, "Roster is null cant sync informations");
+			return;
+		}
+		ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+		for (RosterGroup group : r.getGroups()) {
+			if (group != null) {
+				manageGroup(ops, a, group);
+			}
+			if (ops.size() > NB_DB_OPERATION)
+				executeOperation(ops);
+		}
+		if (ops.size() > 0)
+			executeOperation(ops);
+		for (RosterEntry entry : r.getEntries()) {
+			if (entry != null) {
+				long rawContactID = manageEntry(ops, a, entry);
+				addUpdateStatus(ops, entry, r.getPresence(entry.getUser()), rawContactID);
+			}
+			if (ops.size() > NB_DB_OPERATION)
+				executeOperation(ops);
+		}
+		if (ops.size() > 0)
+			executeOperation(ops);
 	}
-	ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
-	for (RosterGroup group : r.getGroups()) {
-	    if (group != null) {
-		manageGroup(ops, a, group);
-	    }
-	    if (ops.size() > NB_DB_OPERATION)
-		executeOperation(ops);
-	}
-	if (ops.size() > 0)
-	    executeOperation(ops);
-	for (RosterEntry entry : r.getEntries()) {
-	    if (entry != null) {
-		long rawContactID = manageEntry(ops, a, entry);
-		addUpdateStatus(ops, entry, r.getPresence(entry.getUser()), rawContactID);
-	    }
-	    if (ops.size() > NB_DB_OPERATION)
-		executeOperation(ops);
-	}
-	if (ops.size() > 0)
-	    executeOperation(ops);
-    }
 
-    private void manageGroup(ArrayList<ContentProviderOperation> ops, Account account, RosterGroup group) {
-	Log.i(TAG, "Sync group : " + group.getName() + " " + group.getEntryCount());
-	long rawGroupID = getRawGroupID(account.name, group.getName());
-	if (rawGroupID == -1) {
-	    ContentProviderOperation.Builder builder = ContentProviderOperation
-		.newInsert(ContactsContract.Groups.CONTENT_URI);
-	    builder.withValue(ContactsContract.Groups.ACCOUNT_NAME, account.name);
-	    builder.withValue(ContactsContract.Groups.ACCOUNT_TYPE, account.type);
-	    builder.withValue(ContactsContract.Groups.TITLE, group.getName());
-	    ops.add(builder.build());
+	private void manageGroup(ArrayList<ContentProviderOperation> ops, Account account, RosterGroup group) {
+		Log.i(TAG, "Sync group : " + group.getName() + " " + group.getEntryCount());
+		long rawGroupID = getRawGroupID(account.name, group.getName());
+		if (rawGroupID == -1) {
+			ContentProviderOperation.Builder builder = ContentProviderOperation
+				.newInsert(ContactsContract.Groups.CONTENT_URI);
+			builder.withValue(ContactsContract.Groups.ACCOUNT_NAME, account.name);
+			builder.withValue(ContactsContract.Groups.ACCOUNT_TYPE, account.type);
+			builder.withValue(ContactsContract.Groups.TITLE, group.getName());
+			ops.add(builder.build());
+		}
 	}
-    }
 
-    /**
-     * RosterEntry sync method.
-     * @param ops The content provider operation
-     * @param account The account related
-     * @param entry The roster entry to sync
-     * @return The raw contact ID
-     */
-    private long manageEntry(ArrayList<ContentProviderOperation> ops, Account account, RosterEntry entry) {
-	long rawContactID = getRawContactID(account.name, entry.getUser());
-	Log.i(TAG, "Sync Contact : " + entry.getUser() + " RawContactID : " + rawContactID);
-	if (rawContactID == -1) { // Not found in database, add new
-	    ContentValues values = new ContentValues();
-	    values.put(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type);
-	    values.put(ContactsContract.RawContacts.ACCOUNT_NAME, account.name);
-	    values.put(ContactsContract.RawContacts.SOURCE_ID, entry.getUser());
-	    Uri rawContactUri = mContext.getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values);
-	    rawContactID = ContentUris.parseId(rawContactUri);
-	    values.clear();
-	    ContentProviderOperation.Builder builder = addUpdateStructuredName(entry, rawContactID, true);
-	    ops.add(builder.build());
-	    for (RosterGroup group : entry.getGroups()) {
-		builder = addUpdateGroup(entry, rawContactID, getRawGroupID(account.name, group.getName()), true);
-		ops.add(builder.build());
-	    }
-	    builder = createProfile(entry, rawContactID, account);
-	    ops.add(builder.build());
-	} else { // Found, update	   
-	    ContentProviderOperation.Builder builder = addUpdateStructuredName(entry, rawContactID, false);
-	    ops.add(builder.build());
-	    //TODO: ADD AVATAR
-	    //builder = addUpdatePhoto(entry, rawContactID, false);
-	    //ops.add(builder.build());
+	/**
+	 * RosterEntry sync method.
+	 * @param ops The content provider operation
+	 * @param account The account related
+	 * @param entry The roster entry to sync
+	 * @return The raw contact ID
+	 */
+	private long manageEntry(ArrayList<ContentProviderOperation> ops, Account account, RosterEntry entry) {
+		long rawContactID = getRawContactID(account.name, entry.getUser());
+		Log.i(TAG, "Sync Contact : " + entry.getUser() + " RawContactID : " + rawContactID);
+		if (rawContactID == -1) { // Not found in database, add new
+			ContentValues values = new ContentValues();
+			values.put(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type);
+			values.put(ContactsContract.RawContacts.ACCOUNT_NAME, account.name);
+			values.put(ContactsContract.RawContacts.SOURCE_ID, entry.getUser());
+			Uri rawContactUri = mContext.getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values);
+			rawContactID = ContentUris.parseId(rawContactUri);
+			values.clear();
+			ContentProviderOperation.Builder builder = addUpdateStructuredName(entry, rawContactID, true);
+			ops.add(builder.build());
+			for (RosterGroup group : entry.getGroups()) {
+				builder = addUpdateGroup(entry, rawContactID, getRawGroupID(account.name, group.getName()), true);
+				ops.add(builder.build());
+			}
+			builder = createProfile(entry, rawContactID, account);
+			ops.add(builder.build());
+		} else { // Found, update
+			ContentProviderOperation.Builder builder = addUpdateStructuredName(entry, rawContactID, false);
+			ops.add(builder.build());
+			// TODO: ADD AVATAR
+			// builder = addUpdatePhoto(entry, rawContactID, false);
+			// ops.add(builder.build());
+		}
+		return rawContactID;
 	}
-	return rawContactID;
-    }
 
-    /**
-     * Method to insert or update structured name informations.
-     * @param entry The roster entry to sync
-     * @param rawContactID The contact ID in the android database
-     * @param isInsert Insert boolean
-     * @return
-     */
-    private ContentProviderOperation.Builder addUpdateStructuredName(RosterEntry entry, long rawContactID,
-	boolean isInsert) {
-	String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
-	ContentProviderOperation.Builder builder;
-	if (isInsert) {
-	    builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
-	    builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID);
-	    builder.withValue(ContactsContract.Data.MIMETYPE,
-		ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
-	    builder.withValue(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, rawContactID);
-	} else {
-	    builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
-	    builder.withSelection(
-		ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID + " =? AND "
-		    + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
-		    + "'", new String[] { String.valueOf(rawContactID) });
+	/**
+	 * Method to insert or update structured name informations.
+	 * @param entry The roster entry to sync
+	 * @param rawContactID The contact ID in the android database
+	 * @param isInsert Insert boolean
+	 * @return
+	 */
+	private ContentProviderOperation.Builder addUpdateStructuredName(RosterEntry entry, long rawContactID,
+		boolean isInsert) {
+		String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
+		ContentProviderOperation.Builder builder;
+		if (isInsert) {
+			builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
+			builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID);
+			builder.withValue(ContactsContract.Data.MIMETYPE,
+				ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
+			builder.withValue(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, rawContactID);
+		} else {
+			builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
+			builder.withSelection(
+				ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID + " =? AND "
+					+ ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
+					+ "'", new String[] { String.valueOf(rawContactID) });
+		}
+		builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName);
+		builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, displayName);
+		builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, displayName);
+		return builder;
 	}
-	builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName);
-	builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, displayName);
-	builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, displayName);
-	return builder;
-    }
 
-    /**
-     * Method to insert or update avatar.
-     * @param entry The roster entry to sync
-     * @param rawContactID The contact ID in the android database
-     * @param isInsert Insert boolean
-     * @return
-     */
-    private ContentProviderOperation.Builder addUpdatePhoto(RosterEntry entry, long rawContactID, boolean isInsert) {
-	String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
-	ContentProviderOperation.Builder builder;
-	if (isInsert) {
-	    builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
-	    builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID);
-	    builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
-	    builder.withValue(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID, rawContactID);
-	} else {
-	    builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
-	    builder.withSelection(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID + " =? AND "
-		+ ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
-		+ "'", new String[] { String.valueOf(rawContactID) });
-	}
-	BeemAvatarCache bac = new BeemAvatarCache(mContext);
-	try {
-	    builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bac.get(entry.getUser()));
-	} catch (IOException e) {
-	    Log.e(TAG, "Error cache beem avatar", e);
+	/**
+	 * Method to insert or update avatar.
+	 * @param entry The roster entry to sync
+	 * @param rawContactID The contact ID in the android database
+	 * @param isInsert Insert boolean
+	 * @return
+	 */
+	private ContentProviderOperation.Builder addUpdatePhoto(RosterEntry entry, long rawContactID, boolean isInsert) {
+		String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
+		ContentProviderOperation.Builder builder;
+		if (isInsert) {
+			builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
+			builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID);
+			builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
+			builder.withValue(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID, rawContactID);
+		} else {
+			builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
+			builder.withSelection(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID + " =? AND "
+				+ ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
+				+ "'", new String[] { String.valueOf(rawContactID) });
+		}
+		BeemAvatarCache bac = new BeemAvatarCache(mContext);
+		try {
+			builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bac.get(entry.getUser()));
+		} catch (IOException e) {
+			Log.e(TAG, "Error cache beem avatar", e);
+		}
+		return builder;
 	}
-	return builder;
-    }
 
-    /**
-     * Method to insert or update group name informations.
-     * @param entry The roster entry to sync
-     * @param rawContactID The contact ID in the android database
-     * @param rawGroupID The group ID in the android database
-     * @param isInsert Insert boolean
-     * @return
-     */
-    private ContentProviderOperation.Builder addUpdateGroup(RosterEntry entry, long rawContactID, long rawGroupID,
-	boolean isInsert) {
-	String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
-	Log.e(TAG + "UPDATE GROUP", "Contact : " + displayName + " GroupID :" + rawGroupID);
-	ContentProviderOperation.Builder builder = null;
-	if (isInsert) {
-	    builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
-	    builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID);
-	    builder.withValue(ContactsContract.Data.MIMETYPE,
-		ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE);
-	    builder.withValue(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, rawGroupID);
+	/**
+	 * Method to insert or update group name informations.
+	 * @param entry The roster entry to sync
+	 * @param rawContactID The contact ID in the android database
+	 * @param rawGroupID The group ID in the android database
+	 * @param isInsert Insert boolean
+	 * @return
+	 */
+	private ContentProviderOperation.Builder addUpdateGroup(RosterEntry entry, long rawContactID, long rawGroupID,
+		boolean isInsert) {
+		String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
+		Log.e(TAG + "UPDATE GROUP", "Contact : " + displayName + " GroupID :" + rawGroupID);
+		ContentProviderOperation.Builder builder = null;
+		if (isInsert) {
+			builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
+			builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID);
+			builder.withValue(ContactsContract.Data.MIMETYPE,
+				ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE);
+			builder.withValue(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, rawGroupID);
+		}
+		// TODO: delete - contact doesnt appear anymore in this group
+		return builder;
 	}
-	//TODO: delete - contact doesnt appear anymore in this group 
-	return builder;
-    }
 
-    /**
-     * Method to insert or update IM informations.
-     * @param entry The roster entry to sync
-     * @param rawContactID The contact ID in the android database
-     * @param isInsert Insert boolean
-     * @return
-     */
-    private ContentProviderOperation.Builder createProfile(RosterEntry entry, long rawContactID, Account account) {
-	String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
-	ContentProviderOperation.Builder builder;
-	builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
-	builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID);
-	builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
-	builder.withValue(ContactsContract.CommonDataKinds.Im.RAW_CONTACT_ID, rawContactID);
-	builder.withValue(ContactsContract.CommonDataKinds.Im.DATA1, displayName);
-	builder.withValue(ContactsContract.CommonDataKinds.Im.PROTOCOL,
-	    ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER);
-	return builder;
-    }
+	/**
+	 * Method to insert or update IM informations.
+	 * @param entry The roster entry to sync
+	 * @param rawContactID The contact ID in the android database
+	 * @param isInsert Insert boolean
+	 * @return
+	 */
+	private ContentProviderOperation.Builder createProfile(RosterEntry entry, long rawContactID, Account account) {
+		String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
+		ContentProviderOperation.Builder builder;
+		builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
+		builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID);
+		builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
+		builder.withValue(ContactsContract.CommonDataKinds.Im.RAW_CONTACT_ID, rawContactID);
+		builder.withValue(ContactsContract.CommonDataKinds.Im.DATA1, displayName);
+		builder.withValue(ContactsContract.CommonDataKinds.Im.PROTOCOL,
+			ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER);
+		return builder;
+	}
 
-    /**
-     * Method to insert or update IM informations.
-     * @param entry The roster entry to sync
-     * @param rawContactID The contact ID in the android database
-     * @param isInsert Insert boolean
-     * @return
-     */
-    private void addUpdateStatus(ArrayList<ContentProviderOperation> ops, RosterEntry entry, Presence p,
-	long rawContactID) {
-	String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
-	Log.i(TAG + "UPDATESTATUS", "Contact : " + displayName + " Presence status : " + p.getStatus()
-	    + " Presence status state : " + Status.getStatusFromPresence(p));
-	ContentProviderOperation.Builder builder;
-	builder = ContentProviderOperation.newInsert(ContactsContract.StatusUpdates.CONTENT_URI);
-	builder.withValue(ContactsContract.StatusUpdates.PROTOCOL, ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER);
-	builder.withValue(ContactsContract.StatusUpdates.IM_HANDLE, displayName);
-	//TODO: Get account name
-	builder.withValue(ContactsContract.StatusUpdates.IM_ACCOUNT, "beem@elyzion.net");
-	builder.withValue(ContactsContract.StatusUpdates.STATUS, p.getStatus());
-	builder.withValue(ContactsContract.StatusUpdates.STATUS_RES_PACKAGE, "com.beem.project.beem");
-	builder.withValue(ContactsContract.StatusUpdates.STATUS_LABEL, R.string.app_name);
-	//TODO: Get status icon
-	builder.withValue(ContactsContract.StatusUpdates.STATUS_ICON, R.drawable.beem_status_icon);
-	//TODO: Pb presence ... 2 appear on 3 raw .... random appear
-	builder.withValue(ContactsContract.StatusUpdates.PRESENCE, Status.getStatusFromPresence(p));
-	ops.add(builder.build());
-    }
+	/**
+	 * Method to insert or update IM informations.
+	 * @param entry The roster entry to sync
+	 * @param rawContactID The contact ID in the android database
+	 * @param isInsert Insert boolean
+	 * @return
+	 */
+	private void addUpdateStatus(ArrayList<ContentProviderOperation> ops, RosterEntry entry, Presence p,
+		long rawContactID) {
+		String displayName = entry.getName() != null ? entry.getName() : entry.getUser();
+		Log.i(TAG + "UPDATESTATUS", "Contact : " + displayName + " Presence status : " + p.getStatus()
+			+ " Presence status state : " + Status.getStatusFromPresence(p));
+		ContentProviderOperation.Builder builder;
+		builder = ContentProviderOperation.newInsert(ContactsContract.StatusUpdates.CONTENT_URI);
+		builder.withValue(ContactsContract.StatusUpdates.PROTOCOL, ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER);
+		builder.withValue(ContactsContract.StatusUpdates.IM_HANDLE, displayName);
+		// TODO: Get account name
+		builder.withValue(ContactsContract.StatusUpdates.IM_ACCOUNT, "beem@elyzion.net");
+		builder.withValue(ContactsContract.StatusUpdates.STATUS, p.getStatus());
+		builder.withValue(ContactsContract.StatusUpdates.STATUS_RES_PACKAGE, "com.beem.project.beem");
+		builder.withValue(ContactsContract.StatusUpdates.STATUS_LABEL, R.string.app_name);
+		// TODO: Get status icon
+		builder.withValue(ContactsContract.StatusUpdates.STATUS_ICON, R.drawable.beem_status_icon);
+		// TODO: Pb presence ... 2 appear on 3 raw .... random appear
+		builder.withValue(ContactsContract.StatusUpdates.PRESENCE, Status.getStatusFromPresence(p));
+		ops.add(builder.build());
+	}
 
-    /**
-     * Get contact ID from android database.
-     * @param account The account related
-     * @param jid The jid related
-     * @return ID in the database of the jid
-     */
-    private long getRawContactID(String account, String jid) {
-	long authorId = -1;
-	final Cursor c = mContext.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI,
-	    new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.SOURCE_ID },
-	    ContactsContract.RawContacts.ACCOUNT_NAME + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?",
-	    new String[] { account, jid }, null);
-	try {
-	    if (c.moveToFirst())
-		authorId = c.getInt(c.getColumnIndex(ContactsContract.RawContacts._ID));
-	} finally {
-	    if (c != null)
-		c.close();
+	/**
+	 * Get contact ID from android database.
+	 * @param account The account related
+	 * @param jid The jid related
+	 * @return ID in the database of the jid
+	 */
+	private long getRawContactID(String account, String jid) {
+		long authorId = -1;
+		final Cursor c = mContext.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI,
+			new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.SOURCE_ID },
+			ContactsContract.RawContacts.ACCOUNT_NAME + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?",
+			new String[] { account, jid }, null);
+		try {
+			if (c.moveToFirst())
+				authorId = c.getInt(c.getColumnIndex(ContactsContract.RawContacts._ID));
+		} finally {
+			if (c != null)
+				c.close();
+		}
+		return authorId;
 	}
-	return authorId;
-    }
 
-    /**
-     * Get group ID from android database.
-     * @param account The account related
-     * @param group The group related
-     * @return ID in the database of the jid
-     */
-    private long getRawGroupID(String account, String group) {
-	long authorId = -1;
-	final Cursor c = mContext.getContentResolver().query(ContactsContract.Groups.CONTENT_URI,
-	    new String[] { ContactsContract.Groups._ID },
-	    ContactsContract.Groups.ACCOUNT_NAME + "=? AND " + ContactsContract.Groups.TITLE + "=?",
-	    new String[] { account, group }, null);
-	try {
-	    if (c.moveToFirst())
-		authorId = c.getInt(c.getColumnIndex(ContactsContract.Groups._ID));
-	} finally {
-	    if (c != null)
-		c.close();
+	/**
+	 * Get group ID from android database.
+	 * @param account The account related
+	 * @param group The group related
+	 * @return ID in the database of the jid
+	 */
+	private long getRawGroupID(String account, String group) {
+		long authorId = -1;
+		final Cursor c = mContext.getContentResolver().query(ContactsContract.Groups.CONTENT_URI,
+			new String[] { ContactsContract.Groups._ID },
+			ContactsContract.Groups.ACCOUNT_NAME + "=? AND " + ContactsContract.Groups.TITLE + "=?",
+			new String[] { account, group }, null);
+		try {
+			if (c.moveToFirst())
+				authorId = c.getInt(c.getColumnIndex(ContactsContract.Groups._ID));
+		} finally {
+			if (c != null)
+				c.close();
+		}
+		return authorId;
 	}
-	return authorId;
-    }
 }
--- a/src/com/beem/project/beem/providers/MessageProvider.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/providers/MessageProvider.java	Fri Oct 14 18:57:07 2011 +0200
@@ -44,6 +44,8 @@
 
 package com.beem.project.beem.providers;
 
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.HashMap;
 
 import android.content.ContentProvider;
@@ -54,193 +56,203 @@
 import android.database.Cursor;
 import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.util.Log;
 
+import com.beem.project.beem.service.Message;
+
 /**
  * Provider to store messages send/receive.
  * @author marseille
  */
 public class MessageProvider extends ContentProvider {
 
-    private static final String TAG = "MessageProvider";
-    private static final String DATABASE_NAME = "messages.db";
-    private static final int DATABASE_VERSION = 1;
-    private static final int MESSAGES = 1;
-    private static final String MESSAGES_TABLE_NAME = "messages";
-    private static final UriMatcher sUriMatcher;
+	private static final String TAG = "MessageProvider";
+	private static final String DATABASE_NAME = "messages.db";
+	private static final int DATABASE_VERSION = 1;
+	private static final int MESSAGES = 1;
+	private static final String MESSAGES_TABLE_NAME = "messages";
+	private static final UriMatcher sUriMatcher;
 
-    public static final String AUTHORITY = "com.beem.project.beem.providers.messageprovider";
+	public static final String AUTHORITY = "com.beem.project.beem.providers.messageprovider";
 
-    private static HashMap<String, String> messagesProjectionMap;
-    private DatabaseHelper dbHelper = null;
+	private static HashMap<String, String> messagesProjectionMap;
+	private DatabaseHelper mDbHelper;
+	private Context mContext;
 
-    /**
-     * Constructor.
-     */
-    public MessageProvider() {
-	Log.e(TAG, "MessageProvider");
-	if (dbHelper == null)
-	    dbHelper = new DatabaseHelper(getContext());
-	Log.e(TAG, "MessageProvider" + dbHelper.toString());
-    }
+	/**
+	 * Constructor.
+	 */
+	public MessageProvider() {
+		Log.i(TAG, "Constructeur MessageProvider");
+	}
 
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-	SQLiteDatabase db = dbHelper.getWritableDatabase();
-	int count;
-	switch (sUriMatcher.match(uri)) {
-	    case MESSAGES:
-		count = db.delete(MESSAGES_TABLE_NAME, selection, selectionArgs);
-		break;
+	@Override
+	public boolean onCreate() {
+		Log.i(TAG, "On Create MessageProvider");
+		mDbHelper = new DatabaseHelper(getContext());
+		return true;
 
-	    default:
-		throw new IllegalArgumentException("Unknown URI " + uri);
 	}
 
-	getContext().getContentResolver().notifyChange(uri, null);
-	return count;
-    }
 
-    @Override
-    public String getType(Uri uri) {
-	switch (sUriMatcher.match(uri)) {
-	    case MESSAGES:
-		return Messages.CONTENT_TYPE;
-	    default:
-		throw new IllegalArgumentException("Unknown URI " + uri);
-	}
-    }
+	@Override
+	public Uri insert(Uri uri, ContentValues initialValues) {
+		Log.i(TAG, "insert1");
+		if (sUriMatcher.match(uri) != MESSAGES) {
+			throw new IllegalArgumentException("Unknown URI " + uri);
+		}
+		Log.i(TAG, "insert2");
+		ContentValues values;
+		if (initialValues != null)
+			values = new ContentValues(initialValues);
+		else
+			values = new ContentValues();
 
-    @Override
-    public Uri insert(Uri uri, ContentValues initialValues) {
-	Log.e(TAG, "INSERT");
-	if (sUriMatcher.match(uri) != MESSAGES) {
-	    throw new IllegalArgumentException("Unknown URI " + uri);
-	}
-	Log.e(TAG, "INSERT");
-	ContentValues values;
-	if (initialValues != null) {
-	    values = new ContentValues(initialValues);
-	} else {
-	    values = new ContentValues();
-	}
-	Log.e(TAG, "INSERT");
-	SQLiteDatabase db = dbHelper.getWritableDatabase();
-	long rowId = db.insert(MESSAGES_TABLE_NAME, Messages.BODY, values);
-	if (rowId > 0) {
-	    Uri messageUri = ContentUris.withAppendedId(Messages.CONTENT_URI, rowId);
-	    getContext().getContentResolver().notifyChange(messageUri, null);
-	    return messageUri;
-	}
-	Log.e(TAG, "INSERT");
-	throw new SQLException("Failed to insert row into " + uri);
-    }
+		Log.i(TAG, "insert3");
+		if (mDbHelper == null)
+			Log.e("mDbHelper", "NULL");
+		SQLiteDatabase db = null;
+		try {
+		 db = mDbHelper.getWritableDatabase();
+		} catch (SQLiteException e) {
+			Log.e("SQLITEEXCEPTION", "OOOO", e);
+		}
+		Log.i(TAG, "insert3.5");
+		if (db == null)
+			Log.e("db", "NULL");
+		long rowId = db.insert(MESSAGES_TABLE_NAME, Messages.BODY, values);
+		Log.i(TAG, "insert4");
+		if (rowId == -1)
+			throw new SQLException("Failed to insert row into " + uri);
+		Uri messageUri = ContentUris.withAppendedId(Messages.CONTENT_URI, rowId);
+		mContext.getContentResolver().notifyChange(messageUri, null);
+		Log.i(TAG, "Message inserted in database ");
+		return messageUri;
 
-    @Override
-    public boolean onCreate() {
-	Log.e(TAG, "ONCREATE");
-	dbHelper = new DatabaseHelper(getContext());
-	return true;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
-	SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
-
-	switch (sUriMatcher.match(uri)) {
-	    case MESSAGES:
-		qb.setTables(MESSAGES_TABLE_NAME);
-		qb.setProjectionMap(messagesProjectionMap);
-		break;
-
-	    default:
-		throw new IllegalArgumentException("Unknown URI " + uri);
 	}
 
-	SQLiteDatabase db = dbHelper.getReadableDatabase();
-	Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
-
-	c.setNotificationUri(getContext().getContentResolver(), uri);
-	return c;
-    }
+	@Override
+	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
 
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-	SQLiteDatabase db = dbHelper.getWritableDatabase();
-	int count;
-	switch (sUriMatcher.match(uri)) {
-	    case MESSAGES:
-		count = db.update(MESSAGES_TABLE_NAME, values, selection, selectionArgs);
-		break;
+		switch (sUriMatcher.match(uri)) {
+			case MESSAGES:
+				qb.setTables(MESSAGES_TABLE_NAME);
+				qb.setProjectionMap(messagesProjectionMap);
+				break;
 
-	    default:
-		throw new IllegalArgumentException("Unknown URI " + uri);
-	}
-
-	getContext().getContentResolver().notifyChange(uri, null);
-	return count;
-    }
-
-    private static class DatabaseHelper extends SQLiteOpenHelper {
-
-	DatabaseHelper(Context context) {
-	    super(context, DATABASE_NAME, null, DATABASE_VERSION);
-	    Log.e(TAG, "Constructor");
+			default:
+				throw new IllegalArgumentException("Unknown URI " + uri);
+		}
+		SQLiteDatabase db = mDbHelper.getReadableDatabase();
+		Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
+		c.setNotificationUri(mContext.getContentResolver(), uri);
+		return c;
 	}
 
 	@Override
-	public void onCreate(SQLiteDatabase db) {
-	    Log.e(TAG, "onCreate");
-	    String createDatabase = "CREATE TABLE " + MESSAGES_TABLE_NAME + " (";
-	    createDatabase += Messages._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,";
-	    createDatabase += Messages.FROM + " VARCHAR(255),";
-	    createDatabase += Messages.MESSAGE_ID + " VARCHAR(255),";
-	    createDatabase += Messages.TO + " VARCHAR(255),";
-	    createDatabase += Messages.TYPE + " VARCHAR(255),";
-	    createDatabase += Messages.SUBJECT + " VARCHAR(255),";
-	    createDatabase += Messages.BODY + " LONGTEXT,";
-	    createDatabase += Messages.THREAD + " VARCHAR(255),";
-	    createDatabase += Messages.EXTRAS + " VARCHAR(255),";
-	    createDatabase += Messages.IS_RECEIVE + " BOOLEAN,";
-	    createDatabase += Messages.DATE_RECEIVE + " DATE,";
-	    createDatabase += Messages.DATE_READ + "DATE";
-	    createDatabase += ");";
-	    try {
-		db.execSQL(createDatabase);
-	    } catch (SQLException e) {
-		Log.e(TAG, "CREATE DB PROBLEM");
-	    }
+	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+		int count;
+		SQLiteDatabase db = mDbHelper.getWritableDatabase();
+		switch (sUriMatcher.match(uri)) {
+			case MESSAGES:
+				count = db.update(MESSAGES_TABLE_NAME, values, selection, selectionArgs);
+				break;
+
+			default:
+				throw new IllegalArgumentException("Unknown URI " + uri);
+		}
+		mContext.getContentResolver().notifyChange(uri, null);
+		return count;
+	}
+
+	@Override
+	public int delete(Uri uri, String selection, String[] selectionArgs) {
+		int count;
+		SQLiteDatabase db = mDbHelper.getWritableDatabase();
+		switch (sUriMatcher.match(uri)) {
+			case MESSAGES:
+				count = db.delete(MESSAGES_TABLE_NAME, selection, selectionArgs);
+				break;
+
+			default:
+				throw new IllegalArgumentException("Unknown URI " + uri);
+		}
+		mContext.getContentResolver().notifyChange(uri, null);
+		return count;
 	}
 
 	@Override
-	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-	    Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion
-		+ ", which will destroy all old data");
-	    db.execSQL("DROP TABLE IF EXISTS " + MESSAGES_TABLE_NAME);
-	    onCreate(db);
+	public String getType(Uri uri) {
+		switch (sUriMatcher.match(uri)) {
+			case MESSAGES:
+				return Messages.CONTENT_TYPE;
+			default:
+				throw new IllegalArgumentException("Unknown URI " + uri);
+		}
 	}
-    }
+
+	private class DatabaseHelper extends SQLiteOpenHelper {
 
-    static {
-	sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-	sUriMatcher.addURI(AUTHORITY, MESSAGES_TABLE_NAME, MESSAGES);
+		DatabaseHelper(Context context) {
+			super(context, DATABASE_NAME, null, DATABASE_VERSION);
+			Log.e(TAG, "ConStructeur");
+		}
 
-	messagesProjectionMap = new HashMap<String, String>();
-	messagesProjectionMap.put(Messages._ID, Messages._ID);
-	messagesProjectionMap.put(Messages.FROM, Messages.FROM);
-	messagesProjectionMap.put(Messages.MESSAGE_ID, Messages.MESSAGE_ID);
-	messagesProjectionMap.put(Messages.TO, Messages.TO);
-	messagesProjectionMap.put(Messages.TYPE, Messages.TYPE);
-	messagesProjectionMap.put(Messages.SUBJECT, Messages.SUBJECT);
-	messagesProjectionMap.put(Messages.BODY, Messages.BODY);
-	messagesProjectionMap.put(Messages.THREAD, Messages.THREAD);
-	messagesProjectionMap.put(Messages.EXTRAS, Messages.EXTRAS);
-	messagesProjectionMap.put(Messages.IS_RECEIVE, Messages.IS_RECEIVE);
-	messagesProjectionMap.put(Messages.DATE_RECEIVE, Messages.IS_RECEIVE);
-	messagesProjectionMap.put(Messages.DATE_READ, Messages.DATE_READ);
-    }
+		@Override
+		public void onCreate(SQLiteDatabase db) {
+			Log.e(TAG, "onCreate");
+			String createDatabase = "CREATE TABLE " + MESSAGES_TABLE_NAME + " (";
+			createDatabase += Messages._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,";
+			createDatabase += Messages.FROM + " VARCHAR(255),";
+			createDatabase += Messages.MESSAGE_ID + " VARCHAR(255),";
+			createDatabase += Messages.TO + " VARCHAR(255),";
+			createDatabase += Messages.TYPE + " VARCHAR(255),";
+			createDatabase += Messages.SUBJECT + " VARCHAR(255),";
+			createDatabase += Messages.BODY + " LONGTEXT,";
+			createDatabase += Messages.THREAD + " VARCHAR(255),";
+			createDatabase += Messages.EXTRAS + " VARCHAR(255),";
+			createDatabase += Messages.IS_RECEIVE + " BOOLEAN,";
+			createDatabase += Messages.DATE_RECEIVE + " DATE,";
+			createDatabase += Messages.DATE_READ + " DATE";
+			createDatabase += ");";
+			try {
+				db.execSQL(createDatabase);
+			} catch (SQLException e) {
+				Log.e(TAG, "CREATE DB PROBLEM", e);
+			}
+		}
+
+		@Override
+		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+			Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion
+				+ ", which will destroy all old data");
+			db.execSQL("DROP TABLE IF EXISTS " + MESSAGES_TABLE_NAME);
+			onCreate(db);
+		}
+	}
+
+	static {
+		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+		sUriMatcher.addURI(AUTHORITY, MESSAGES_TABLE_NAME, MESSAGES);
+
+		messagesProjectionMap = new HashMap<String, String>();
+		messagesProjectionMap.put(Messages._ID, Messages._ID);
+		messagesProjectionMap.put(Messages.FROM, Messages.FROM);
+		messagesProjectionMap.put(Messages.MESSAGE_ID, Messages.MESSAGE_ID);
+		messagesProjectionMap.put(Messages.TO, Messages.TO);
+		messagesProjectionMap.put(Messages.TYPE, Messages.TYPE);
+		messagesProjectionMap.put(Messages.SUBJECT, Messages.SUBJECT);
+		messagesProjectionMap.put(Messages.BODY, Messages.BODY);
+		messagesProjectionMap.put(Messages.THREAD, Messages.THREAD);
+		messagesProjectionMap.put(Messages.EXTRAS, Messages.EXTRAS);
+		messagesProjectionMap.put(Messages.IS_RECEIVE, Messages.IS_RECEIVE);
+		messagesProjectionMap.put(Messages.DATE_RECEIVE, Messages.DATE_RECEIVE);
+		messagesProjectionMap.put(Messages.DATE_READ, Messages.DATE_READ);
+	}
 
 }
--- a/src/com/beem/project/beem/providers/Messages.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/providers/Messages.java	Fri Oct 14 18:57:07 2011 +0200
@@ -16,17 +16,17 @@
     public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.beem.project.beem.provider.messages";
 
     public static final String _ID = "_id";
-    public static final String FROM = "FROM";
-    public static final String MESSAGE_ID = "MESSAGE_ID";	
-    public static final String TO = "TO";
-    public static final String TYPE = "TYPE";
-    public static final String SUBJECT = "SUBJECT";
-    public static final String BODY = "BODY";
-    public static final String THREAD = "THREAD";
-    public static final String EXTRAS = "EXTRAS";
-    public static final String IS_RECEIVE = "IS_RECEIVE";
-    public static final String DATE_RECEIVE = "DATE_RECEIVE";
-    public static final String DATE_READ = "DATE_READ";
+    public static final String FROM = "_FROM";
+    public static final String MESSAGE_ID = "_MESSAGE_ID";	
+    public static final String TO = "_TO";
+    public static final String TYPE = "_TYPE";
+    public static final String SUBJECT = "_SUBJECT";
+    public static final String BODY = "_BODY";
+    public static final String THREAD = "_THREAD";
+    public static final String EXTRAS = "_EXTRAS";
+    public static final String IS_RECEIVE = "_IS_RECEIVE";
+    public static final String DATE_RECEIVE = "_DATE_RECEIVE";
+    public static final String DATE_READ = "_DATE_READ";
     
 
 }
--- a/src/com/beem/project/beem/service/BeemChatManager.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/service/BeemChatManager.java	Fri Oct 14 18:57:07 2011 +0200
@@ -40,11 +40,13 @@
     Flavien Astraud, November 26, 2009
     Head of the EIP Laboratory.
 
-*/
+ */
 package com.beem.project.beem.service;
 
 import java.io.File;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -55,6 +57,7 @@
 
 import android.app.Notification;
 import android.app.PendingIntent;
+import android.content.ContentValues;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.os.Environment;
@@ -65,6 +68,8 @@
 
 import com.beem.project.beem.BeemApplication;
 import com.beem.project.beem.BeemService;
+import com.beem.project.beem.providers.MessageProvider;
+import com.beem.project.beem.providers.Messages;
 import com.beem.project.beem.service.aidl.IChat;
 import com.beem.project.beem.service.aidl.IChatManager;
 import com.beem.project.beem.service.aidl.IChatManagerListener;
@@ -77,248 +82,263 @@
  */
 public class BeemChatManager extends IChatManager.Stub {
 
-    private static final String TAG = "BeemChatManager";
-    private final ChatManager mAdaptee;
-    private final Map<String, ChatAdapter> mChats = new HashMap<String, ChatAdapter>();
-    private final ChatListener mChatListener = new ChatListener();
-    private final RemoteCallbackList<IChatManagerListener> mRemoteChatCreationListeners =
-	new RemoteCallbackList<IChatManagerListener>();
-    private final BeemService mService;
-
-    /**
-     * Constructor.
-     * @param chatManager the smack ChatManager to adapt
-     * @param service the service which runs the chat manager
-     */
-    public BeemChatManager(final ChatManager chatManager, final BeemService service) {
-	mService = service;
-	mAdaptee = chatManager;
-	mAdaptee.addChatListener(mChatListener);
-    }
-
-    @Override
-    public void addChatCreationListener(IChatManagerListener listener) throws RemoteException {
-	if (listener != null)
-	    mRemoteChatCreationListeners.register(listener);
-    }
-
-    /**
-     * Create a chat session.
-     * @param contact the contact you want to chat with
-     * @param listener listener to use for chat events on this chat session
-     * @return the chat session
-     */
-    @Override
-    public IChat createChat(Contact contact, IMessageListener listener) {
-	String jid = contact.getJIDWithRes();
-	Log.d(TAG, "Get chat key1 = ");
-
-	return createChat(jid, listener);
-    }
-
-    /**
-     * Create a chat session.
-     * @param jid the jid of the contact you want to chat with
-     * @param listener listener to use for chat events on this chat session
-     * @return the chat session
-     */
-    public IChat createChat(String jid, IMessageListener listener) {
-	String key = jid;
-	ChatAdapter result;
-	Log.d(TAG, "Get chat key2 = ");
-	if (mChats.containsKey(key)) {
-	    result = mChats.get(key);
-	    result.addMessageListener(listener);
-	    return result;
-	}
-	Chat c = mAdaptee.createChat(key, null);
-	// maybe a little probleme of thread synchronization
-	// if so use an HashTable instead of a HashMap for mChats
-	result = getChat(c);
-	result.addMessageListener(listener);
-	return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void destroyChat(IChat chat) throws RemoteException {
-	// Can't remove it. otherwise we will lose all futur message in this chat
-	// chat.removeMessageListener(mChatListener);
-	if (chat == null)
-	    return;
-	deleteChatNotification(chat);
-	mChats.remove(chat.getParticipant().getJID());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void deleteChatNotification(IChat chat) {
-	try {
-	    mService.deleteNotification(chat.getParticipant().getJID().hashCode());
-	} catch (RemoteException e) {
-	    Log.v(TAG, "Remote exception ", e);
-	}
-    }
-
-    /**
-     * Get an existing ChatAdapter or create it if necessary.
-     * @param chat The real instance of smack chat
-     * @return a chat adapter register in the manager
-     */
-    private ChatAdapter getChat(Chat chat) {
-	String key = chat.getParticipant();
-	if (mChats.containsKey(key)) {
-	    return mChats.get(key);
-	}
-	ChatAdapter res = new ChatAdapter(chat);
-	boolean history = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getBoolean(
-	    "settings_key_history", false);
-	String accountUser = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getString(
-	    BeemApplication.ACCOUNT_USERNAME_KEY, "");
-	String historyPath = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getString(
-	    BeemApplication.CHAT_HISTORY_KEY, "");
-	if ("".equals(historyPath)) historyPath = "/Android/data/com.beem.project.beem/chat/";
-	res.setHistory(history);
-	res.setAccountUser(accountUser);
-	res.setHistoryPath(new File(Environment.getExternalStorageDirectory(), historyPath));
-	Log.d(TAG, "getChat put " + key);
-	mChats.put(key, res);
-	return res;
-    }
-
-    @Override
-    public ChatAdapter getChat(Contact contact) {
-	String key = contact.getJIDWithRes();
-	return mChats.get(key);
-    }
-
-    /**
-     * This methods permits to retrieve the list of contacts who have an opened chat session with us.
-     * @return An List containing Contact instances.
-     * @throws RemoteException If a Binder remote-invocation error occurred.
-     */
-    public List<Contact> getOpenedChatList() throws RemoteException {
-	List<Contact> openedChats = new ArrayList<Contact>();
-	IRoster mRoster = mService.getBind().getRoster();
-
-	for (ChatAdapter chat : mChats.values()) {
-	    if (chat.getMessages().size() > 0) {
-		Contact t = mRoster.getContact(chat.getParticipant().getJID());
-		if (t == null)
-		    t = new Contact(chat.getParticipant().getJID());
-		openedChats.add(t);
-	    }
-	}
-	return openedChats;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void removeChatCreationListener(IChatManagerListener listener) throws RemoteException {
-	if (listener != null)
-	    mRemoteChatCreationListeners.unregister(listener);
-    }
-
-    /**
-     * A listener for all the chat creation event that happens on the connection.
-     * @author darisk
-     */
-    private class ChatListener extends IMessageListener.Stub implements ChatManagerListener {
+	private static final String TAG = "BeemChatManager";
+	private final ChatManager mAdaptee;
+	private final Map<String, ChatAdapter> mChats = new HashMap<String, ChatAdapter>();
+	private final ChatListener mChatListener = new ChatListener();
+	private final RemoteCallbackList<IChatManagerListener> mRemoteChatCreationListeners = new RemoteCallbackList<IChatManagerListener>();
+	private final BeemService mService;
 
 	/**
 	 * Constructor.
+	 * @param chatManager the smack ChatManager to adapt
+	 * @param service the service which runs the chat manager
 	 */
-	public ChatListener() {
+	public BeemChatManager(final ChatManager chatManager, final BeemService service) {
+		mService = service;
+		mAdaptee = chatManager;
+		mAdaptee.addChatListener(mChatListener);		
+	}
+
+	@Override
+	public void addChatCreationListener(IChatManagerListener listener) throws RemoteException {
+		if (listener != null)
+			mRemoteChatCreationListeners.register(listener);
+	}
+
+	/**
+	 * Create a chat session.
+	 * @param contact the contact you want to chat with
+	 * @param listener listener to use for chat events on this chat session
+	 * @return the chat session
+	 */
+	@Override
+	public IChat createChat(Contact contact, IMessageListener listener) {
+		String jid = contact.getJIDWithRes();
+		Log.d(TAG, "Get chat key1 = ");
+
+		return createChat(jid, listener);
+	}
+
+	/**
+	 * Create a chat session.
+	 * @param jid the jid of the contact you want to chat with
+	 * @param listener listener to use for chat events on this chat session
+	 * @return the chat session
+	 */
+	public IChat createChat(String jid, IMessageListener listener) {
+		String key = jid;
+		ChatAdapter result;
+		Log.d(TAG, "Get chat key2 = ");
+		if (mChats.containsKey(key)) {
+			result = mChats.get(key);
+			result.addMessageListener(listener);
+			return result;
+		}
+		Chat c = mAdaptee.createChat(key, null);
+		// maybe a little probleme of thread synchronization
+		// if so use an HashTable instead of a HashMap for mChats
+		result = getChat(c);
+		result.addMessageListener(listener);
+		return result;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void destroyChat(IChat chat) throws RemoteException {
+		// Can't remove it. otherwise we will lose all futur message in this chat
+		// chat.removeMessageListener(mChatListener);
+		if (chat == null)
+			return;
+		deleteChatNotification(chat);
+		mChats.remove(chat.getParticipant().getJID());
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
-	public void chatCreated(Chat chat, boolean locally) {
-	    IChat newchat = getChat(chat);
-	    Log.d(TAG, "Chat" + chat.toString() + " created locally " + locally + "with " + chat.getParticipant());
-	    try {
-		newchat.addMessageListener(mChatListener);
-		final int n = mRemoteChatCreationListeners.beginBroadcast();
-
-		for (int i = 0; i < n; i++) {
-		    IChatManagerListener listener = mRemoteChatCreationListeners.getBroadcastItem(i);
-		    listener.chatCreated(newchat, locally);
+	public void deleteChatNotification(IChat chat) {
+		try {
+			mService.deleteNotification(chat.getParticipant().getJID().hashCode());
+		} catch (RemoteException e) {
+			Log.v(TAG, "Remote exception ", e);
 		}
-		mRemoteChatCreationListeners.finishBroadcast();
-	    } catch (RemoteException e) {
-		// The RemoteCallbackList will take care of removing the
-		// dead listeners.
-		Log.w(TAG, " Error while triggering remote connection listeners in chat creation", e);
-	    }
 	}
 
 	/**
-	 * Create the PendingIntent to launch our activity if the user select this chat notification.
-	 * @param chat A ChatAdapter instance
-	 * @return A Chat activity PendingIntent
+	 * Get an existing ChatAdapter or create it if necessary.
+	 * @param chat The real instance of smack chat
+	 * @return a chat adapter register in the manager
 	 */
-	private PendingIntent makeChatIntent(IChat chat) {
-	    Intent chatIntent = new Intent(mService, com.beem.project.beem.ui.Chat.class);
-	    chatIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP
-		| Intent.FLAG_ACTIVITY_NEW_TASK);
-	    try {
-		chatIntent.setData(chat.getParticipant().toUri());
-	    } catch (RemoteException e) {
-		Log.e(TAG, e.getMessage());
-	    }
-	    PendingIntent contentIntent = PendingIntent.getActivity(mService, 0, chatIntent,
-		PendingIntent.FLAG_UPDATE_CURRENT);
-	    return contentIntent;
+	private ChatAdapter getChat(Chat chat) {
+		String key = chat.getParticipant();
+		if (mChats.containsKey(key)) {
+			return mChats.get(key);
+		}
+		ChatAdapter res = new ChatAdapter(chat);
+		boolean history = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getBoolean(
+			"settings_key_history", false);
+		String accountUser = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getString(
+			BeemApplication.ACCOUNT_USERNAME_KEY, "");
+		String historyPath = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getString(
+			BeemApplication.CHAT_HISTORY_KEY, "");
+		if ("".equals(historyPath))
+			historyPath = "/Android/data/com.beem.project.beem/chat/";
+		res.setHistory(history);
+		res.setAccountUser(accountUser);
+		res.setHistoryPath(new File(Environment.getExternalStorageDirectory(), historyPath));
+		Log.d(TAG, "getChat put " + key);
+		mChats.put(key, res);
+		return res;
+	}
+
+	@Override
+	public ChatAdapter getChat(Contact contact) {
+		String key = contact.getJIDWithRes();
+		return mChats.get(key);
 	}
 
 	/**
-	 * Set a notification of a new chat.
-	 * @param chat The chat to access by the notification
-	 * @param msgBody the body of the new message
+	 * This methods permits to retrieve the list of contacts who have an opened chat session with us.
+	 * @return An List containing Contact instances.
+	 * @throws RemoteException If a Binder remote-invocation error occurred.
 	 */
-	private void notifyNewChat(IChat chat, String msgBody) {
-	    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mService);
-	    try {
-		CharSequence tickerText = mService.getBind().getRoster().getContact(chat.getParticipant().getJID())
-		    .getName();
-		Notification notification = new Notification(android.R.drawable.stat_notify_chat, tickerText, System
-		    .currentTimeMillis());
-		notification.flags = Notification.FLAG_AUTO_CANCEL;
-		notification.setLatestEventInfo(mService, tickerText, msgBody, makeChatIntent(chat));
-		mService.sendNotification(chat.getParticipant().getJID().hashCode(), notification);
-	    } catch (RemoteException e) {
-		Log.e(TAG, e.getMessage());
-	    }
+	public List<Contact> getOpenedChatList() throws RemoteException {
+		List<Contact> openedChats = new ArrayList<Contact>();
+		IRoster mRoster = mService.getBind().getRoster();
+
+		for (ChatAdapter chat : mChats.values()) {
+			if (chat.getMessages().size() > 0) {
+				Contact t = mRoster.getContact(chat.getParticipant().getJID());
+				if (t == null)
+					t = new Contact(chat.getParticipant().getJID());
+				openedChats.add(t);
+			}
+		}
+		return openedChats;
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
-	public void processMessage(final IChat chat, Message message) {
-	    try {
-		String body = message.getBody();
-		if (!chat.isOpen() && body != null) {
-		    if (chat instanceof ChatAdapter) {
-			mChats.put(chat.getParticipant().getJID(), (ChatAdapter) chat);
-		    }
-		    notifyNewChat(chat, body);
-		}
-	    } catch (RemoteException e) {
-		Log.e(TAG, e.getMessage());
-	    }
+	public void removeChatCreationListener(IChatManagerListener listener) throws RemoteException {
+		if (listener != null)
+			mRemoteChatCreationListeners.unregister(listener);
 	}
 
-	@Override
-	public void stateChanged(final IChat chat) {
+	/**
+	 * A listener for all the chat creation event that happens on the connection.
+	 * @author darisk
+	 */
+	private class ChatListener extends IMessageListener.Stub implements ChatManagerListener {
+
+		/**
+		 * Constructor.
+		 */
+		public ChatListener() {
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void chatCreated(Chat chat, boolean locally) {
+			IChat newchat = getChat(chat);
+			Log.d(TAG, "Chat" + chat.toString() + " created locally " + locally + "with " + chat.getParticipant());
+			try {
+				newchat.addMessageListener(mChatListener);
+				final int n = mRemoteChatCreationListeners.beginBroadcast();
+
+				for (int i = 0; i < n; i++) {
+					IChatManagerListener listener = mRemoteChatCreationListeners.getBroadcastItem(i);
+					listener.chatCreated(newchat, locally);
+				}
+				mRemoteChatCreationListeners.finishBroadcast();
+			} catch (RemoteException e) {
+				// The RemoteCallbackList will take care of removing the
+				// dead listeners.
+				Log.w(TAG, " Error while triggering remote connection listeners in chat creation", e);
+			}
+		}
+
+		/**
+		 * Create the PendingIntent to launch our activity if the user select this chat notification.
+		 * @param chat A ChatAdapter instance
+		 * @return A Chat activity PendingIntent
+		 */
+		private PendingIntent makeChatIntent(IChat chat) {
+			Intent chatIntent = new Intent(mService, com.beem.project.beem.ui.Chat.class);
+			chatIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP
+				| Intent.FLAG_ACTIVITY_NEW_TASK);
+			try {
+				chatIntent.setData(chat.getParticipant().toUri());
+			} catch (RemoteException e) {
+				Log.e(TAG, e.getMessage());
+			}
+			PendingIntent contentIntent = PendingIntent.getActivity(mService, 0, chatIntent,
+				PendingIntent.FLAG_UPDATE_CURRENT);
+			return contentIntent;
+		}
+
+		/**
+		 * Set a notification of a new chat.
+		 * @param chat The chat to access by the notification
+		 * @param msgBody the body of the new message
+		 */
+		private void notifyNewChat(IChat chat, String msgBody) {
+			SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mService);
+			try {
+				CharSequence tickerText = mService.getBind().getRoster().getContact(chat.getParticipant().getJID())
+					.getName();
+				Notification notification = new Notification(android.R.drawable.stat_notify_chat, tickerText, System
+					.currentTimeMillis());
+				notification.flags = Notification.FLAG_AUTO_CANCEL;
+				notification.setLatestEventInfo(mService, tickerText, msgBody, makeChatIntent(chat));
+				mService.sendNotification(chat.getParticipant().getJID().hashCode(), notification);
+			} catch (RemoteException e) {
+				Log.e(TAG, e.getMessage());
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void processMessage(final IChat chat, Message message) {
+			try {
+								SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+				// note that we don't have to add an id as our table set id as autoincrement
+				ContentValues values = new ContentValues();
+				values.put(Messages.FROM, message.getFrom());
+				values.put(Messages.MESSAGE_ID, "message id");
+				values.put(Messages.TO, message.getTo());
+				values.put(Messages.TYPE, message.getType());
+				values.put(Messages.SUBJECT, "SUBJECT");
+				values.put(Messages.BODY, message.getBody());
+				values.put(Messages.THREAD, "THREAD");
+				values.put(Messages.EXTRAS, "EXTRAS");
+				values.put(Messages.IS_RECEIVE, true);
+				values.put(Messages.DATE_RECEIVE, dateFormat.format(new Date()));
+				values.put(Messages.DATE_READ, dateFormat.format(message.getTimestamp()));
+				mService.getContentResolver().insert(Messages.CONTENT_URI, values);
+				String body = message.getBody();
+				if (!chat.isOpen() && body != null) {
+					if (chat instanceof ChatAdapter) {
+						mChats.put(chat.getParticipant().getJID(), (ChatAdapter) chat);
+					}
+					notifyNewChat(chat, body);
+				}
+			} catch (RemoteException e) {
+				Log.e(TAG, e.getMessage());
+			}
+		}
+
+		@Override
+		public void stateChanged(final IChat chat) {
+		}
 	}
-    }
 }
--- a/src/com/beem/project/beem/service/ChatAdapter.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/service/ChatAdapter.java	Fri Oct 14 18:57:07 2011 +0200
@@ -40,7 +40,7 @@
     Flavien Astraud, November 26, 2009
     Head of the EIP Laboratory.
 
-*/
+ */
 package com.beem.project.beem.service;
 
 import java.io.File;
@@ -56,14 +56,11 @@
 import org.jivesoftware.smackx.ChatState;
 import org.jivesoftware.smackx.ChatStateListener;
 
-import android.content.ContentValues;
 import android.os.Environment;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.util.Log;
 
-import com.beem.project.beem.providers.MessageProvider;
-import com.beem.project.beem.providers.Messages;
 import com.beem.project.beem.service.aidl.IChat;
 import com.beem.project.beem.service.aidl.IMessageListener;
 
@@ -72,269 +69,264 @@
  * @author darisk
  */
 public class ChatAdapter extends IChat.Stub {
-    private static final int HISTORY_MAX_SIZE = 50;
-    private static final String TAG = "ChatAdapter";
-
-    private final Chat mAdaptee;
-    private final Contact mParticipant;
-    private String mState;
-    private boolean mIsOpen;
-    private final List<Message> mMessages;
-    private final RemoteCallbackList<IMessageListener> mRemoteListeners = new RemoteCallbackList<IMessageListener>();
-    private final MsgListener mMsgListener = new MsgListener();
-    private boolean mIsHistory;
-    private File mHistoryPath;
-    private String mAccountUser;
-
-    /**
-     * Constructor.
-     * @param chat The chat to adapt
-     */
-    public ChatAdapter(final Chat chat) {
-	mAdaptee = chat;
-	mParticipant = new Contact(chat.getParticipant());
-	mMessages = new LinkedList<Message>();
-	mAdaptee.addMessageListener(mMsgListener);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Contact getParticipant() throws RemoteException {
-	return mParticipant;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void sendMessage(com.beem.project.beem.service.Message message) throws RemoteException {
-	org.jivesoftware.smack.packet.Message send = new org.jivesoftware.smack.packet.Message();
-	send.setTo(message.getTo());
-	send.setBody(message.getBody());
-	send.setThread(message.getThread());
-	send.setSubject(message.getSubject());
-	send.setType(org.jivesoftware.smack.packet.Message.Type.chat);
-	// TODO gerer les messages contenant des XMPPError
-	// send.set
-	try {
-	    mAdaptee.sendMessage(send);
-	    mMessages.add(message);
-	} catch (XMPPException e) {
-	    e.printStackTrace();
-	}
-	String state = Environment.getExternalStorageState();
-	if (mIsHistory && Environment.MEDIA_MOUNTED.equals(state))
-	    saveHistory(message, mAccountUser);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void addMessageListener(IMessageListener listen) {
-	if (listen != null)
-	    mRemoteListeners.register(listen);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void removeMessageListener(IMessageListener listen) {
-	if (listen != null) {
-	    mRemoteListeners.unregister(listen);
-	}
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String getState() throws RemoteException {
-	return mState;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setState(String state) throws RemoteException {
-	mState = state;
-    }
-
-    /**
-     * Get the adaptee for the Chat.
-     * @return The real chat object
-     */
-    public Chat getAdaptee() {
-	return mAdaptee;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setOpen(boolean isOpen) {
-	this.mIsOpen = isOpen;
-    }
+	private static final int HISTORY_MAX_SIZE = 50;
+	private static final String TAG = "ChatAdapter";
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean isOpen() {
-	return mIsOpen;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public List<Message> getMessages() throws RemoteException {
-	return Collections.unmodifiableList(mMessages);
-    }
-
-    /**
-     * Add a message in the chat history.
-     * @param msg the message to add
-     */
-    void addMessage(Message msg) {
-	if (mMessages.size() == HISTORY_MAX_SIZE)
-	    mMessages.remove(0);
-	MessageProvider mp = new MessageProvider();
-	ContentValues contentValue = new ContentValues();
-	// note that we don't have to add an id as our table set id as autoincrement
-	//contentValue.put(Messages.FROM, msg.getFrom());
-	Log.e(TAG, "xxxxxxxxxxxxxxMESSAGExxxxxxxxxxxxxxxxxxx");
-	contentValue.put(Messages.BODY, msg.getBody());
-	mp.insert(Messages.CONTENT_URI, contentValue);
-	mMessages.add(msg);
-	if (!"".equals(msg.getBody()) && msg.getBody() != null) {
-	    String state = Environment.getExternalStorageState();
-	    if (mIsHistory && Environment.MEDIA_MOUNTED.equals(state))
-		saveHistory(msg, msg.getFrom());
-	}
-    }
+	private final Chat mAdaptee;
+	private final Contact mParticipant;
+	private String mState;
+	private boolean mIsOpen;
+	private final List<Message> mMessages;
+	private final RemoteCallbackList<IMessageListener> mRemoteListeners = new RemoteCallbackList<IMessageListener>();
+	private final MsgListener mMsgListener = new MsgListener();
+	private boolean mIsHistory;
+	private File mHistoryPath;
+	private String mAccountUser;
 
-    /**
-     * Save message in SDCard.
-     * @param msg the message receive
-     * @param contactName the name of the contact
-     */
-    public void saveHistory(Message msg, String contactName) {
-	File path = getHistoryPath();
-    	File filepath;
-    	if (contactName.equals(msg.getFrom()))
-    	    filepath = new File(path, StringUtils.parseBareAddress(contactName));
-    	else
-    	    filepath = new File(path, StringUtils.parseBareAddress(msg.getTo()));
-    	path.mkdirs();
-	try {
-	    FileWriter file = new FileWriter(filepath, true);
-	    String log = msg.getTimestamp() + " " + contactName + " " + msg.getBody()
-		+ System.getProperty("line.separator");
-	    file.write(log);
-	    file.close();
-	} catch (IOException e) {
-	    Log.e(TAG, "Error writing chat history", e);
-	}
-    }
-
-    /**
-     * set History enable/disable.
-     * @param isHisory history state
-     */
-    public void setHistory(boolean isHisory) {
-	this.mIsHistory = isHisory;
-    }
-
-    /**
-     * get History state.
-     * @return mIsHistory
-     */
-    public boolean getHistory() {
-	return mIsHistory;
-    }
-
-    /**
-     * Set Account user name.
-     * @param accountUser user name
-     */
-    public void setAccountUser(String accountUser) {
-	mAccountUser = accountUser;
-    }
-
-    /**
-     * get Account user name.
-     * @return mAccountUser
-     */
-    public String getAccountUser() {
-	return mAccountUser;
-    }
-
-    /**
-     * set History path.
-     * @param historyPath history path
-     */
-    public void setHistoryPath(File historyPath) {
-	this.mHistoryPath = historyPath;
-    }
-
-    /**
-     * get History path.
-     * @return mHistoryPath;
-     */
-    public File getHistoryPath() {
-	return mHistoryPath;
-    }
-
-    /**
-     * Listener.
-     */
-    private class MsgListener implements ChatStateListener {
 	/**
 	 * Constructor.
+	 * @param chat The chat to adapt
 	 */
-	public MsgListener() {
+	public ChatAdapter(final Chat chat) {
+		mAdaptee = chat;
+		mParticipant = new Contact(chat.getParticipant());
+		mMessages = new LinkedList<Message>();
+		mAdaptee.addMessageListener(mMsgListener);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Contact getParticipant() throws RemoteException {
+		return mParticipant;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void sendMessage(com.beem.project.beem.service.Message message) throws RemoteException {
+		org.jivesoftware.smack.packet.Message send = new org.jivesoftware.smack.packet.Message();
+		send.setTo(message.getTo());
+		send.setBody(message.getBody());
+		send.setThread(message.getThread());
+		send.setSubject(message.getSubject());
+		send.setType(org.jivesoftware.smack.packet.Message.Type.chat);
+		// TODO gerer les messages contenant des XMPPError
+		// send.set
+		try {
+			mAdaptee.sendMessage(send);
+			mMessages.add(message);
+		} catch (XMPPException e) {
+			e.printStackTrace();
+		}
+		String state = Environment.getExternalStorageState();
+		if (mIsHistory && Environment.MEDIA_MOUNTED.equals(state))
+			saveHistory(message, mAccountUser);
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	@Override
-	public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) {
-	    Message msg = new Message(message);
-	    //TODO add que les message pas de type errors
-	    ChatAdapter.this.addMessage(msg);
-	    final int n = mRemoteListeners.beginBroadcast();
-	    for (int i = 0; i < n; i++) {
-		IMessageListener listener = mRemoteListeners.getBroadcastItem(i);
-		try {
-		    if (listener != null)
-			listener.processMessage(ChatAdapter.this, msg);
-		} catch (RemoteException e) {
-		    Log.w(TAG, "Error while diffusing message to listener", e);
+	public void addMessageListener(IMessageListener listen) {
+		if (listen != null)
+			mRemoteListeners.register(listen);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void removeMessageListener(IMessageListener listen) {
+		if (listen != null) {
+			mRemoteListeners.unregister(listen);
 		}
-	    }
-	    mRemoteListeners.finishBroadcast();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getState() throws RemoteException {
+		return mState;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setState(String state) throws RemoteException {
+		mState = state;
+	}
+
+	/**
+	 * Get the adaptee for the Chat.
+	 * @return The real chat object
+	 */
+	public Chat getAdaptee() {
+		return mAdaptee;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setOpen(boolean isOpen) {
+		this.mIsOpen = isOpen;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isOpen() {
+		return mIsOpen;
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
-	public void stateChanged(Chat chat, ChatState state) {
-	    mState = state.name();
-	    final int n = mRemoteListeners.beginBroadcast();
+	public List<Message> getMessages() throws RemoteException {
+		return Collections.unmodifiableList(mMessages);
+	}
 
-	    for (int i = 0; i < n; i++) {
-		IMessageListener listener = mRemoteListeners.getBroadcastItem(i);
+	/**
+	 * Add a message in the chat history.
+	 * @param msg the message to add
+	 */
+	void addMessage(Message msg) {
+		if (mMessages.size() == HISTORY_MAX_SIZE)
+			mMessages.remove(0);
+		// note that we don't have to add an id as our table set id as autoincrement
+		//contentValue.put(Messages.FROM, msg.getFrom());
+		mMessages.add(msg);
+		if (!"".equals(msg.getBody()) && msg.getBody() != null) {
+			String state = Environment.getExternalStorageState();
+			if (mIsHistory && Environment.MEDIA_MOUNTED.equals(state))
+				saveHistory(msg, msg.getFrom());
+		}
+	}
+
+	/**
+	 * Save message in SDCard.
+	 * @param msg the message receive
+	 * @param contactName the name of the contact
+	 */
+	public void saveHistory(Message msg, String contactName) {
+		File path = getHistoryPath();
+		File filepath;
+		if (contactName.equals(msg.getFrom()))
+			filepath = new File(path, StringUtils.parseBareAddress(contactName));
+		else
+			filepath = new File(path, StringUtils.parseBareAddress(msg.getTo()));
+		path.mkdirs();
 		try {
-		    listener.stateChanged(ChatAdapter.this);
-		} catch (RemoteException e) {
-		    Log.w(TAG, e.getMessage());
+			FileWriter file = new FileWriter(filepath, true);
+			String log = msg.getTimestamp() + " " + contactName + " " + msg.getBody()
+				+ System.getProperty("line.separator");
+			file.write(log);
+			file.close();
+		} catch (IOException e) {
+			Log.e(TAG, "Error writing chat history", e);
 		}
-	    }
-	    mRemoteListeners.finishBroadcast();
+	}
+
+	/**
+	 * set History enable/disable.
+	 * @param isHisory history state
+	 */
+	public void setHistory(boolean isHisory) {
+		this.mIsHistory = isHisory;
+	}
+
+	/**
+	 * get History state.
+	 * @return mIsHistory
+	 */
+	public boolean getHistory() {
+		return mIsHistory;
+	}
+
+	/**
+	 * Set Account user name.
+	 * @param accountUser user name
+	 */
+	public void setAccountUser(String accountUser) {
+		mAccountUser = accountUser;
+	}
+
+	/**
+	 * get Account user name.
+	 * @return mAccountUser
+	 */
+	public String getAccountUser() {
+		return mAccountUser;
+	}
+
+	/**
+	 * set History path.
+	 * @param historyPath history path
+	 */
+	public void setHistoryPath(File historyPath) {
+		this.mHistoryPath = historyPath;
+	}
+
+	/**
+	 * get History path.
+	 * @return mHistoryPath;
+	 */
+	public File getHistoryPath() {
+		return mHistoryPath;
 	}
-    }
+
+	/**
+	 * Listener.
+	 */
+	private class MsgListener implements ChatStateListener {
+		/**
+		 * Constructor.
+		 */
+		public MsgListener() {
+		}
+
+		@Override
+		public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) {
+			Message msg = new Message(message);
+			//TODO add que les message pas de type errors
+			ChatAdapter.this.addMessage(msg);
+			final int n = mRemoteListeners.beginBroadcast();
+			for (int i = 0; i < n; i++) {
+				IMessageListener listener = mRemoteListeners.getBroadcastItem(i);
+				try {
+					if (listener != null)
+						listener.processMessage(ChatAdapter.this, msg);
+				} catch (RemoteException e) {
+					Log.w(TAG, "Error while diffusing message to listener", e);
+				}
+			}
+			mRemoteListeners.finishBroadcast();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void stateChanged(Chat chat, ChatState state) {
+			mState = state.name();
+			final int n = mRemoteListeners.beginBroadcast();
+
+			for (int i = 0; i < n; i++) {
+				IMessageListener listener = mRemoteListeners.getBroadcastItem(i);
+				try {
+					listener.stateChanged(ChatAdapter.this);
+				} catch (RemoteException e) {
+					Log.w(TAG, e.getMessage());
+				}
+			}
+			mRemoteListeners.finishBroadcast();
+		}
+	}
 }
--- a/src/com/beem/project/beem/service/XmppConnectionAdapter.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/service/XmppConnectionAdapter.java	Fri Oct 14 18:57:07 2011 +0200
@@ -91,624 +91,625 @@
  */
 public class XmppConnectionAdapter extends IXmppConnection.Stub {
 
-    /**
-     * Beem connection closed Intent name.
-     */
-
-    private static final int SMACK_PRIORITY_MIN = -128;
-    private static final int SMACK_PRIORITY_MAX = 128;
-    private static final String TAG = "XMPPConnectionAdapter";
-    private final XMPPConnection mAdaptee;
-    private IChatManager mChatManager;
-    private final String mLogin;
-    private final String mPassword;
-    private String mResource;
-    private String mErrorMsg;
-    private RosterAdapter mRoster;
-    private int mPreviousPriority;
-    private int mPreviousMode;
-    private String mPreviousStatus;
-    private PrivacyListManagerAdapter mPrivacyListManager;
-    private ChatStateManager mChatStateManager;
-    private final BeemService mService;
-    private BeemApplication mApplication;
-    private AvatarManager mAvatarManager;
-    private PepSubManager mPepManager;
-    private SharedPreferences mPref;
-    private final RemoteCallbackList<IBeemConnectionListener> mRemoteConnListeners = new RemoteCallbackList<IBeemConnectionListener>();
-    private final SubscribePacketListener mSubscribePacketListener = new SubscribePacketListener();
-
-    private final ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter();
-
-    /**
-     * Constructor.
-     * @param config Configuration to use in order to connect
-     * @param login login to use on connect
-     * @param password password to use on connect
-     * @param service the background service associated with the connection.
-     */
-    public XmppConnectionAdapter(final ConnectionConfiguration config, final String login, final String password,
-	final BeemService service) {
-	this(new XMPPConnection(config), login, password, service);
-    }
-
-    /**
-     * Constructor.
-     * @param serviceName name of the service to connect to
-     * @param login login to use on connect
-     * @param password password to use on connect
-     * @param service the background service associated with the connection.
-     */
-    public XmppConnectionAdapter(final String serviceName, final String login, final String password,
-	final BeemService service) {
-	this(new XMPPConnection(serviceName), login, password, service);
-    }
-
-    /**
-     * Constructor.
-     * @param con The connection to adapt
-     * @param login The login to use
-     * @param password The password to use
-     * @param service the background service associated with the connection.
-     */
-    public XmppConnectionAdapter(final XMPPConnection con, final String login, final String password,
-	final BeemService service) {
-	mAdaptee = con;
-	PrivacyListManager.getInstanceFor(mAdaptee);
-	mLogin = StringUtils.parseName(login);
-
-	mPassword = password;
-	mService = service;
-	Context ctx = mService.getApplicationContext();
-	if (ctx instanceof BeemApplication) {
-	    mApplication = (BeemApplication) ctx;
-	}
-	mPref = mService.getServicePreference(login); // login is the jid
-	try {
-	    mPreviousPriority = Integer.parseInt(mPref.getString("settings_key_priority", "0"));
-	} catch (NumberFormatException ex) {
-	    mPreviousPriority = 0;
-	}
-	mResource = mPref.getString("settings_key_resource", "BEEM");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void addConnectionListener(IBeemConnectionListener listen) throws RemoteException {
-	if (listen != null)
-	    mRemoteConnListeners.register(listen);
-    }
+	/**
+	 * Beem connection closed Intent name.
+	 */
 
-    @Override
-    public boolean connect() throws RemoteException {
-	if (mAdaptee.isConnected())
-	    return true;
-	else {
-	    try {
-		mAdaptee.connect();
-		mAdaptee.addConnectionListener(mConListener);
-		return true;
-	    } catch (XMPPException e) {
-		Log.e(TAG, "Error while connecting", e);
-		try {
-		    //TODO NIKITA DOES SOME SHIT !!! Fix this monstruosity
-		    String str = mService.getResources().getString(
-			mService.getResources().getIdentifier(e.getXMPPError().getCondition().replace("-", "_"),
-			    "string", "com.beem.project.beem"));
-		    mErrorMsg = str;
-		} catch (NullPointerException e2) {
-		    if (!"".equals(e.getMessage()))
-			mErrorMsg = e.getMessage();
-		    else
-			mErrorMsg = e.toString();
-		}
-	    }
-	    return false;
-	}
-    }
-
-    @Override
-    public boolean login() throws RemoteException {
-	if (mAdaptee.isAuthenticated())
-	    return true;
-	if (!mAdaptee.isConnected())
-	    return false;
-	try {
-
-	    this.initFeatures(); // pour declarer les features xmpp qu'on
-	    // supporte
-
-	    PacketFilter filter = new PacketFilter() {
-
-		@Override
-		public boolean accept(Packet packet) {
-		    if (packet instanceof Presence) {
-			Presence pres = (Presence) packet;
-			if (pres.getType() == Presence.Type.subscribe)
-			    return true;
-		    }
-		    return false;
-		}
-	    };
+	private static final int SMACK_PRIORITY_MIN = -128;
+	private static final int SMACK_PRIORITY_MAX = 128;
+	private static final String TAG = "XMPPConnectionAdapter";
+	private final XMPPConnection mAdaptee;
+	private IChatManager mChatManager;
+	private final String mLogin;
+	private final String mPassword;
+	private String mResource;
+	private String mErrorMsg;
+	private RosterAdapter mRoster;
+	private int mPreviousPriority;
+	private int mPreviousMode;
+	private String mPreviousStatus;
+	private PrivacyListManagerAdapter mPrivacyListManager;
+	private ChatStateManager mChatStateManager;
+	private final BeemService mService;
+	private BeemApplication mApplication;
+	private AvatarManager mAvatarManager;
+	private PepSubManager mPepManager;
+	private SharedPreferences mPref;
+	private final RemoteCallbackList<IBeemConnectionListener> mRemoteConnListeners = new RemoteCallbackList<IBeemConnectionListener>();
+	private final SubscribePacketListener mSubscribePacketListener = new SubscribePacketListener();
 
-	    mAdaptee.addPacketListener(mSubscribePacketListener, filter);
-	    Log.e(TAG, mLogin + mPassword + mResource);
-	    mAdaptee.login(mLogin, mPassword, mResource);
-	    mChatManager = new BeemChatManager(mAdaptee.getChatManager(), mService);
-	    //nikita: I commented this line because of the logs provided in http://www.beem-project.com/issues/321
-	    //Also, since the privacylistmanager isn't finished and used, it will be safer to not initialize it
-	    //mPrivacyListManager = new PrivacyListManagerAdapter(PrivacyListManager.getInstanceFor(mAdaptee));
-	    mService.initJingle(mAdaptee);
-	    discoverServerFeatures();
-
-	    mRoster = new RosterAdapter(mAdaptee.getRoster(), mService, mAvatarManager);
-	    mApplication.setConnected(true);
-	    int mode = mPref.getInt(BeemApplication.STATUS_KEY, 0);
-	    String status = mPref.getString(BeemApplication.STATUS_TEXT_KEY, "");
-	    changeStatus(mode, status);
-	    return true;
-	} catch (XMPPException e) {
-	    Log.e(TAG, "Error while connecting", e);
-	    mErrorMsg = mService.getString(R.string.error_login_authentication);
-	    return false;
-	}
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public final void connectAsync() throws RemoteException {
-	if (mAdaptee.isConnected() || mAdaptee.isAuthenticated())
-	    return;
-	Thread t = new Thread(new Runnable() {
-
-	    @Override
-	    public void run() {
-		try {
-		    connectSync();
-		} catch (RemoteException e) {
-		    Log.e(TAG, "Error while connecting asynchronously", e);
-		}
-	    }
-	});
-	t.start();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean connectSync() throws RemoteException {
-	if (connect())
-	    return login();
-	return false;
-    }
+	private final ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter();
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void changeStatusAndPriority(int status, String msg, int priority) {
-	Presence pres = new Presence(Presence.Type.available);
-	String m;
-	if (msg != null)
-	    m = msg;
-	else
-	    m = mPreviousStatus;
-	pres.setStatus(m);
-	mPreviousStatus = m;
-	Presence.Mode mode = Status.getPresenceModeFromStatus(status);
-	if (mode != null) {
-	    pres.setMode(mode);
-	    mPreviousMode = status;
-	} else {
-	    pres.setMode(Status.getPresenceModeFromStatus(mPreviousMode));
+	/**
+	 * Constructor.
+	 * @param config Configuration to use in order to connect
+	 * @param login login to use on connect
+	 * @param password password to use on connect
+	 * @param service the background service associated with the connection.
+	 */
+	public XmppConnectionAdapter(final ConnectionConfiguration config, final String login, final String password,
+		final BeemService service) {
+		this(new XMPPConnection(config), login, password, service);
 	}
-	int p = priority;
-	if (priority < SMACK_PRIORITY_MIN)
-	    p = SMACK_PRIORITY_MIN;
-	if (priority > SMACK_PRIORITY_MAX)
-	    p = SMACK_PRIORITY_MAX;
-	mPreviousPriority = p;
-	pres.setPriority(p);
-	mAdaptee.sendPacket(pres);
-	updateNotification(m);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void changeStatus(int status, String msg) {
-	changeStatusAndPriority(status, msg, mPreviousPriority);
-    }
-
-    /**
-     * Get the AvatarManager of this connection.
-     * @return the AvatarManager or null if there is not
-     */
-    public AvatarManager getAvatarManager() {
-	return mAvatarManager;
-    }
 
-    /**
-     * get the previous status.
-     * @return previous status.
-     */
-    public String getPreviousStatus() {
-	return mPreviousStatus;
-    }
-
-    /**
-     * get the previous mode.
-     * @return previous mode.
-     */
-    public int getPreviousMode() {
-	return mPreviousMode;
-    }
-
-    /**
-     * Update the notification for the Beem status.
-     * @param text the text to display.
-     */
-    private void updateNotification(String text) {
-	Notification mStatusNotification;
-	mStatusNotification = new Notification(com.beem.project.beem.R.drawable.beem_status_icon, text, System
-	    .currentTimeMillis());
-	mStatusNotification.defaults = Notification.DEFAULT_LIGHTS;
-	mStatusNotification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
-
-	mStatusNotification.setLatestEventInfo(mService, "Beem Status", text, PendingIntent.getActivity(mService, 0,
-	    new Intent(mService, ChangeStatus.class), 0));
-	// bypass the preferences for notification
-	mService.getNotificationManager().notify(BeemService.NOTIFICATION_STATUS_ID, mStatusNotification);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean disconnect() {
-	if (mAdaptee != null && mAdaptee.isConnected())
-	    mAdaptee.disconnect();
-	return true;
-    }
-
-    /**
-     * Get the Smack XmppConnection.
-     * @return Smack XmppConnection
-     */
-    public XMPPConnection getAdaptee() {
-	return mAdaptee;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public IChatManager getChatManager() throws RemoteException {
-	return mChatManager;
-    }
+	/**
+	 * Constructor.
+	 * @param serviceName name of the service to connect to
+	 * @param login login to use on connect
+	 * @param password password to use on connect
+	 * @param service the background service associated with the connection.
+	 */
+	public XmppConnectionAdapter(final String serviceName, final String login, final String password,
+		final BeemService service) {
+		this(new XMPPConnection(serviceName), login, password, service);
+	}
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public IRoster getRoster() throws RemoteException {
-	if (mRoster != null)
-	    return mRoster;
-	Roster adap = mAdaptee.getRoster();
-	if (adap == null)
-	    return null;
-	mRoster = new RosterAdapter(adap, mService, mAvatarManager);
-	return mRoster;
-    }
-
-    /**
-     * Returns true if currently authenticated by successfully calling the login method.
-     * @return true when successfully authenticated
-     */
-    public boolean isAuthentificated() {
-	return mAdaptee.isAuthenticated();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void removeConnectionListener(IBeemConnectionListener listen) throws RemoteException {
-	if (listen != null)
-	    mRemoteConnListeners.unregister(listen);
-    }
+	/**
+	 * Constructor.
+	 * @param con The connection to adapt
+	 * @param login The login to use
+	 * @param password The password to use
+	 * @param service the background service associated with the connection.
+	 */
+	public XmppConnectionAdapter(final XMPPConnection con, final String login, final String password,
+		final BeemService service) {
+		mAdaptee = con;
+		PrivacyListManager.getInstanceFor(mAdaptee);
+		mLogin = StringUtils.parseName(login);
 
-    /**
-     * PrivacyListManagerAdapter mutator.
-     * @param privacyListManager the privacy list manager
-     */
-    public void setPrivacyListManager(PrivacyListManagerAdapter privacyListManager) {
-	this.mPrivacyListManager = privacyListManager;
-    }
-
-    /**
-     * PrivacyListManagerAdapter accessor.
-     * @return the mPrivacyList
-     */
-    public PrivacyListManagerAdapter getPrivacyListManager() {
-	return mPrivacyListManager;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String getErrorMessage() {
-	return mErrorMsg;
-    }
-
-    public void handleMessage(android.os.Message msg) {
-	Bundle b = (Bundle) msg.obj;
-	switch (msg.what) {
-
-	    default:
-		Log.w(TAG, "Unknown message " + msg);
+		mPassword = password;
+		mService = service;
+		Context ctx = mService.getApplicationContext();
+		if (ctx instanceof BeemApplication) {
+			mApplication = (BeemApplication) ctx;
+		}
+		mPref = mService.getServicePreference(login); // login is the jid
+		try {
+			mPreviousPriority = Integer.parseInt(mPref.getString("settings_key_priority", "0"));
+		} catch (NumberFormatException ex) {
+			mPreviousPriority = 0;
+		}
+		mResource = mPref.getString("settings_key_resource", "BEEM");
 	}
-    }
-
-    /**
-     * Initialize the features provided by beem.
-     */
-    private void initFeatures() {
-	ServiceDiscoveryManager.setIdentityName("Beem");
-	ServiceDiscoveryManager.setIdentityType("phone");
-	ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
-	if (sdm == null)
-	    sdm = new ServiceDiscoveryManager(mAdaptee);
-
-	sdm.addFeature("http://jabber.org/protocol/disco#info");
-	//nikita: must be uncommented when the feature will be enabled
-	//sdm.addFeature("jabber:iq:privacy");
-	sdm.addFeature("http://jabber.org/protocol/caps");
-	sdm.addFeature("urn:xmpp:avatar:metadata");
-	sdm.addFeature("urn:xmpp:avatar:metadata+notify");
-	sdm.addFeature("urn:xmpp:avatar:data");
-	sdm.addFeature("http://jabber.org/protocol/nick");
-	sdm.addFeature("http://jabber.org/protocol/nick+notify");
-
-	mChatStateManager = ChatStateManager.getInstance(mAdaptee);
-	BeemCapsManager caps = new BeemCapsManager(sdm, mAdaptee, mService);
-	caps.setNode("http://www.beem-project.com");
-    }
-
-    /**
-     * Discover the features provided by the server.
-     */
-    private void discoverServerFeatures() {
-	try {
-	    // jid et server
-	    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
-	    DiscoverInfo info = sdm.discoverInfo(mAdaptee.getServiceName());
-	    Iterator<DiscoverInfo.Identity> it = info.getIdentities();
-	    while (it.hasNext()) {
-		DiscoverInfo.Identity identity = it.next();
-		if ("pubsub".equals(identity.getCategory()) && "pep".equals(identity.getType())) {
-		    initPEP();
-		}
-	    }
-	} catch (XMPPException e) {
-	    // No Pep
-	}
-    }
-
-    /**
-     * Initialize PEP.
-     */
-    private void initPEP() {
-	// Enable pep sending
-	// API 8
-	// mService.getExternalCacheDir()
-	mPepManager = new PepSubManager(mAdaptee);
-	AvatarCache avatarCache = new BeemAvatarCache(mService);
-	mAvatarManager = new AvatarManager(mAdaptee, mPepManager, avatarCache, true);
-    }
-
-    /**
-     * Listener for XMPP connection events. It will calls the remote listeners for connection events.
-     * @author darisk
-     */
-    private class ConnexionListenerAdapter implements ConnectionListener {
 
 	/**
-	 * Defaut constructor.
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void addConnectionListener(IBeemConnectionListener listen) throws RemoteException {
+		if (listen != null)
+			mRemoteConnListeners.register(listen);
+	}
+
+	@Override
+	public boolean connect() throws RemoteException {
+		if (mAdaptee.isConnected())
+			return true;
+		else {
+			try {
+				mAdaptee.connect();
+				mAdaptee.addConnectionListener(mConListener);
+				return true;
+			} catch (XMPPException e) {
+				Log.e(TAG, "Error while connecting", e);
+				try {
+					//TODO NIKITA DOES SOME SHIT !!! Fix this monstruosity
+					String str = mService.getResources().getString(
+						mService.getResources().getIdentifier(e.getXMPPError().getCondition().replace("-", "_"),
+							"string", "com.beem.project.beem"));
+					mErrorMsg = str;
+				} catch (NullPointerException e2) {
+					if (!"".equals(e.getMessage()))
+						mErrorMsg = e.getMessage();
+					else
+						mErrorMsg = e.toString();
+				}
+			}
+			return false;
+		}
+	}
+
+	@Override
+	public boolean login() throws RemoteException {
+		if (mAdaptee.isAuthenticated())
+			return true;
+		if (!mAdaptee.isConnected())
+			return false;
+		try {
+
+			this.initFeatures(); // pour declarer les features xmpp qu'on
+			// supporte
+
+			PacketFilter filter = new PacketFilter() {
+
+				@Override
+				public boolean accept(Packet packet) {
+					if (packet instanceof Presence) {
+						Presence pres = (Presence) packet;
+						if (pres.getType() == Presence.Type.subscribe)
+							return true;
+					}
+					return false;
+				}
+			};
+
+			mAdaptee.addPacketListener(mSubscribePacketListener, filter);
+			Log.e(TAG, mLogin + mPassword + mResource);
+			mAdaptee.login(mLogin, mPassword, mResource);
+			mChatManager = new BeemChatManager(mAdaptee.getChatManager(), mService);
+			//nikita: I commented this line because of the logs provided in http://www.beem-project.com/issues/321
+			//Also, since the privacylistmanager isn't finished and used, it will be safer to not initialize it
+			//mPrivacyListManager = new PrivacyListManagerAdapter(PrivacyListManager.getInstanceFor(mAdaptee));
+			mService.initJingle(mAdaptee);
+			discoverServerFeatures();
+
+			mRoster = new RosterAdapter(mAdaptee.getRoster(), mService, mAvatarManager);
+			mApplication.setConnected(true);
+			int mode = mPref.getInt(BeemApplication.STATUS_KEY, 0);
+			String status = mPref.getString(BeemApplication.STATUS_TEXT_KEY, "");
+			changeStatus(mode, status);
+			return true;
+		} catch (XMPPException e) {
+			Log.e(TAG, "Error while connecting", e);
+			mErrorMsg = mService.getString(R.string.error_login_authentication);
+			return false;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final void connectAsync() throws RemoteException {
+		if (mAdaptee.isConnected() || mAdaptee.isAuthenticated())
+			return;
+		Thread t = new Thread(new Runnable() {
+
+			@Override
+			public void run() {
+				try {
+					connectSync();
+				} catch (RemoteException e) {
+					Log.e(TAG, "Error while connecting asynchronously", e);
+				}
+			}
+		});
+		t.start();
+	}
+
+	/**
+	 * {@inheritDoc}
 	 */
-	public ConnexionListenerAdapter() {
+	@Override
+	public boolean connectSync() throws RemoteException {
+		if (connect())
+			return login();
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void changeStatusAndPriority(int status, String msg, int priority) {
+		Presence pres = new Presence(Presence.Type.available);
+		String m;
+		if (msg != null)
+			m = msg;
+		else
+			m = mPreviousStatus;
+		pres.setStatus(m);
+		mPreviousStatus = m;
+		Presence.Mode mode = Status.getPresenceModeFromStatus(status);
+		if (mode != null) {
+			pres.setMode(mode);
+			mPreviousMode = status;
+		} else {
+			pres.setMode(Status.getPresenceModeFromStatus(mPreviousMode));
+		}
+		int p = priority;
+		if (priority < SMACK_PRIORITY_MIN)
+			p = SMACK_PRIORITY_MIN;
+		if (priority > SMACK_PRIORITY_MAX)
+			p = SMACK_PRIORITY_MAX;
+		mPreviousPriority = p;
+		pres.setPriority(p);
+		mAdaptee.sendPacket(pres);
+		updateNotification(m);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void changeStatus(int status, String msg) {
+		changeStatusAndPriority(status, msg, mPreviousPriority);
+	}
+
+	/**
+	 * Get the AvatarManager of this connection.
+	 * @return the AvatarManager or null if there is not
+	 */
+	public AvatarManager getAvatarManager() {
+		return mAvatarManager;
+	}
+
+	/**
+	 * get the previous status.
+	 * @return previous status.
+	 */
+	public String getPreviousStatus() {
+		return mPreviousStatus;
+	}
+
+	/**
+	 * get the previous mode.
+	 * @return previous mode.
+	 */
+	public int getPreviousMode() {
+		return mPreviousMode;
+	}
+
+	/**
+	 * Update the notification for the Beem status.
+	 * @param text the text to display.
+	 */
+	private void updateNotification(String text) {
+//		Notification mStatusNotification;
+//		mStatusNotification = new Notification(com.beem.project.beem.R.drawable.beem_status_icon, text, System
+//			.currentTimeMillis());
+//		mStatusNotification.defaults = Notification.DEFAULT_LIGHTS;
+//		mStatusNotification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
+//
+//		mStatusNotification.setLatestEventInfo(mService, "Beem Status", text, PendingIntent.getActivity(mService, 0,
+//			new Intent(mService, ChangeStatus.class), 0));
+//		// bypass the preferences for notification
+//		mService.getNotificationManager().notify(BeemService.NOTIFICATION_STATUS_ID, mStatusNotification);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean disconnect() {
+		if (mAdaptee != null && mAdaptee.isConnected())
+			mAdaptee.disconnect();
+		return true;
+	}
+
+	/**
+	 * Get the Smack XmppConnection.
+	 * @return Smack XmppConnection
+	 */
+	public XMPPConnection getAdaptee() {
+		return mAdaptee;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public IChatManager getChatManager() throws RemoteException {
+		return mChatManager;
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
-	public void connectionClosed() {
-	    Log.d(TAG, "closing connection");
-	    mRoster = null;
-	    Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED);
-	    intent.putExtra("message", mService.getString(R.string.BeemBroadcastReceiverDisconnect));
-	    intent.putExtra("normally", true);
-	    mService.sendBroadcast(intent);
-	    mService.stopSelf();
-	    mApplication.setConnected(false);
+	public IRoster getRoster() throws RemoteException {
+		if (mRoster != null)
+			return mRoster;
+		Roster adap = mAdaptee.getRoster();
+		if (adap == null)
+			return null;
+		mRoster = new RosterAdapter(adap, mService, mAvatarManager);
+		return mRoster;
+	}
+
+	/**
+	 * Returns true if currently authenticated by successfully calling the login method.
+	 * @return true when successfully authenticated
+	 */
+	public boolean isAuthentificated() {
+		return mAdaptee.isAuthenticated();
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
-	public void connectionClosedOnError(Exception exception) {
-	    Log.d(TAG, "connectionClosedOnError");
-	    mRoster = null;
-	    Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED);
-	    intent.putExtra("message", exception.getMessage());
-	    mService.sendBroadcast(intent);
-	    mService.stopSelf();
-	    mApplication.setConnected(false);
+	public void removeConnectionListener(IBeemConnectionListener listen) throws RemoteException {
+		if (listen != null)
+			mRemoteConnListeners.unregister(listen);
 	}
 
 	/**
-	 * Connection failed callback.
-	 * @param errorMsg smack failure message
+	 * PrivacyListManagerAdapter mutator.
+	 * @param privacyListManager the privacy list manager
 	 */
-	public void connectionFailed(String errorMsg) {
-	    Log.d(TAG, "Connection Failed");
-	    final int n = mRemoteConnListeners.beginBroadcast();
-
-	    for (int i = 0; i < n; i++) {
-		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
-		try {
-		    if (listener != null)
-			listener.connectionFailed(errorMsg);
-		} catch (RemoteException e) {
-		    // The RemoteCallbackList will take care of removing the
-		    // dead listeners.
-		    Log.w(TAG, "Error while triggering remote connection listeners", e);
-		}
-	    }
-	    mRemoteConnListeners.finishBroadcast();
-	    mService.stopSelf();
-	    mApplication.setConnected(false);
+	public void setPrivacyListManager(PrivacyListManagerAdapter privacyListManager) {
+		this.mPrivacyListManager = privacyListManager;
 	}
 
 	/**
-	 * {@inheritDoc}
+	 * PrivacyListManagerAdapter accessor.
+	 * @return the mPrivacyList
 	 */
-	@Override
-	public void reconnectingIn(int arg0) {
-	    Log.d(TAG, "reconnectingIn");
-	    final int n = mRemoteConnListeners.beginBroadcast();
-
-	    for (int i = 0; i < n; i++) {
-		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
-		try {
-		    if (listener != null)
-			listener.reconnectingIn(arg0);
-		} catch (RemoteException e) {
-		    // The RemoteCallbackList will take care of removing the
-		    // dead listeners.
-		    Log.w(TAG, "Error while triggering remote connection listeners", e);
-		}
-	    }
-	    mRemoteConnListeners.finishBroadcast();
+	public PrivacyListManagerAdapter getPrivacyListManager() {
+		return mPrivacyListManager;
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
-	public void reconnectionFailed(Exception arg0) {
-	    Log.d(TAG, "reconnectionFailed");
-	    final int r = mRemoteConnListeners.beginBroadcast();
+	public String getErrorMessage() {
+		return mErrorMsg;
+	}
+
+	public void handleMessage(android.os.Message msg) {
+		Log.e(TAG, "HANDLEMESSAGE");
+		Bundle b = (Bundle) msg.obj;
+		switch (msg.what) {
+
+			default:
+				Log.w(TAG, "Unknown message " + msg);
+		}
+	}
 
-	    for (int i = 0; i < r; i++) {
-		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
+	/**
+	 * Initialize the features provided by beem.
+	 */
+	private void initFeatures() {
+		ServiceDiscoveryManager.setIdentityName("Beem");
+		ServiceDiscoveryManager.setIdentityType("phone");
+		ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
+		if (sdm == null)
+			sdm = new ServiceDiscoveryManager(mAdaptee);
+
+		sdm.addFeature("http://jabber.org/protocol/disco#info");
+		//nikita: must be uncommented when the feature will be enabled
+		//sdm.addFeature("jabber:iq:privacy");
+		sdm.addFeature("http://jabber.org/protocol/caps");
+		sdm.addFeature("urn:xmpp:avatar:metadata");
+		sdm.addFeature("urn:xmpp:avatar:metadata+notify");
+		sdm.addFeature("urn:xmpp:avatar:data");
+		sdm.addFeature("http://jabber.org/protocol/nick");
+		sdm.addFeature("http://jabber.org/protocol/nick+notify");
+
+		mChatStateManager = ChatStateManager.getInstance(mAdaptee);
+		BeemCapsManager caps = new BeemCapsManager(sdm, mAdaptee, mService);
+		caps.setNode("http://www.beem-project.com");
+	}
+
+	/**
+	 * Discover the features provided by the server.
+	 */
+	private void discoverServerFeatures() {
 		try {
-		    if (listener != null)
-			listener.reconnectionFailed();
-		} catch (RemoteException e) {
-		    // The RemoteCallbackList will take care of removing the
-		    // dead listeners.
-		    Log.w(TAG, "Error while triggering remote connection listeners", e);
+			// jid et server
+			ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
+			DiscoverInfo info = sdm.discoverInfo(mAdaptee.getServiceName());
+			Iterator<DiscoverInfo.Identity> it = info.getIdentities();
+			while (it.hasNext()) {
+				DiscoverInfo.Identity identity = it.next();
+				if ("pubsub".equals(identity.getCategory()) && "pep".equals(identity.getType())) {
+					initPEP();
+				}
+			}
+		} catch (XMPPException e) {
+			// No Pep
 		}
-	    }
-	    mRemoteConnListeners.finishBroadcast();
+	}
+
+	/**
+	 * Initialize PEP.
+	 */
+	private void initPEP() {
+		// Enable pep sending
+		// API 8
+		// mService.getExternalCacheDir()
+		mPepManager = new PepSubManager(mAdaptee);
+		AvatarCache avatarCache = new BeemAvatarCache(mService);
+		mAvatarManager = new AvatarManager(mAdaptee, mPepManager, avatarCache, true);
 	}
 
 	/**
-	 * {@inheritDoc}
+	 * Listener for XMPP connection events. It will calls the remote listeners for connection events.
+	 * @author darisk
 	 */
-	@Override
-	public void reconnectionSuccessful() {
-	    Log.d(TAG, "reconnectionSuccessful");
-	    mApplication.setConnected(true);
-	    PacketFilter filter = new PacketFilter() {
+	private class ConnexionListenerAdapter implements ConnectionListener {
+
+		/**
+		 * Defaut constructor.
+		 */
+		public ConnexionListenerAdapter() {
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void connectionClosed() {
+			Log.d(TAG, "closing connection");
+			mRoster = null;
+			Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED);
+			intent.putExtra("message", mService.getString(R.string.BeemBroadcastReceiverDisconnect));
+			intent.putExtra("normally", true);
+			mService.sendBroadcast(intent);
+			mService.stopSelf();
+			mApplication.setConnected(false);
+		}
 
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void connectionClosedOnError(Exception exception) {
+			Log.d(TAG, "connectionClosedOnError");
+			mRoster = null;
+			Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED);
+			intent.putExtra("message", exception.getMessage());
+			mService.sendBroadcast(intent);
+			mService.stopSelf();
+			mApplication.setConnected(false);
+		}
+
+		/**
+		 * Connection failed callback.
+		 * @param errorMsg smack failure message
+		 */
+		public void connectionFailed(String errorMsg) {
+			Log.d(TAG, "Connection Failed");
+			final int n = mRemoteConnListeners.beginBroadcast();
+
+			for (int i = 0; i < n; i++) {
+				IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
+				try {
+					if (listener != null)
+						listener.connectionFailed(errorMsg);
+				} catch (RemoteException e) {
+					// The RemoteCallbackList will take care of removing the
+					// dead listeners.
+					Log.w(TAG, "Error while triggering remote connection listeners", e);
+				}
+			}
+			mRemoteConnListeners.finishBroadcast();
+			mService.stopSelf();
+			mApplication.setConnected(false);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
 		@Override
-		public boolean accept(Packet packet) {
-		    if (packet instanceof Presence) {
-			Presence pres = (Presence) packet;
-			if (pres.getType() == Presence.Type.subscribe)
-			    return true;
-		    }
-		    return false;
+		public void reconnectingIn(int arg0) {
+			Log.d(TAG, "reconnectingIn");
+			final int n = mRemoteConnListeners.beginBroadcast();
+
+			for (int i = 0; i < n; i++) {
+				IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
+				try {
+					if (listener != null)
+						listener.reconnectingIn(arg0);
+				} catch (RemoteException e) {
+					// The RemoteCallbackList will take care of removing the
+					// dead listeners.
+					Log.w(TAG, "Error while triggering remote connection listeners", e);
+				}
+			}
+			mRemoteConnListeners.finishBroadcast();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void reconnectionFailed(Exception arg0) {
+			Log.d(TAG, "reconnectionFailed");
+			final int r = mRemoteConnListeners.beginBroadcast();
+
+			for (int i = 0; i < r; i++) {
+				IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
+				try {
+					if (listener != null)
+						listener.reconnectionFailed();
+				} catch (RemoteException e) {
+					// The RemoteCallbackList will take care of removing the
+					// dead listeners.
+					Log.w(TAG, "Error while triggering remote connection listeners", e);
+				}
+			}
+			mRemoteConnListeners.finishBroadcast();
 		}
-	    };
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void reconnectionSuccessful() {
+			Log.d(TAG, "reconnectionSuccessful");
+			mApplication.setConnected(true);
+			PacketFilter filter = new PacketFilter() {
+
+				@Override
+				public boolean accept(Packet packet) {
+					if (packet instanceof Presence) {
+						Presence pres = (Presence) packet;
+						if (pres.getType() == Presence.Type.subscribe)
+							return true;
+					}
+					return false;
+				}
+			};
+
+			mAdaptee.addPacketListener(new PacketListener() {
 
-	    mAdaptee.addPacketListener(new PacketListener() {
+				@Override
+				public void processPacket(Packet packet) {
+					String from = packet.getFrom();
+					Notification notif = new Notification(android.R.drawable.stat_notify_more, mService.getString(
+						R.string.AcceptContactRequest, from), System.currentTimeMillis());
+					notif.flags = Notification.FLAG_AUTO_CANCEL;
+					Intent intent = new Intent(mService, Subscription.class);
+					intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("from", from);
+					notif.setLatestEventInfo(mService, from, mService
+						.getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0,
+						intent, PendingIntent.FLAG_ONE_SHOT));
+					int id = packet.hashCode();
+					mService.sendNotification(id, notif);
+				}
+			}, filter);
+
+			final int n = mRemoteConnListeners.beginBroadcast();
+
+			for (int i = 0; i < n; i++) {
+				IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
+				try {
+					if (listener != null)
+						listener.reconnectionSuccessful();
+				} catch (RemoteException e) {
+					// The RemoteCallbackList will take care of removing the
+					// dead listeners.
+					Log.w(TAG, "Error while triggering remote connection listeners", e);
+				}
+			}
+			mRemoteConnListeners.finishBroadcast();
+		}
+	}
+
+	/**
+	 * This PacketListener will set a notification when you got a subscribtion request.
+	 * @author Da Risk <da_risk@elyzion.net>
+	 */
+	private class SubscribePacketListener implements PacketListener {
+
+		/**
+		 * Constructor.
+		 */
+		public SubscribePacketListener() {
+		}
 
 		@Override
 		public void processPacket(Packet packet) {
-		    String from = packet.getFrom();
-		    Notification notif = new Notification(android.R.drawable.stat_notify_more, mService.getString(
-			R.string.AcceptContactRequest, from), System.currentTimeMillis());
-		    notif.flags = Notification.FLAG_AUTO_CANCEL;
-		    Intent intent = new Intent(mService, Subscription.class);
-		    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("from", from);
-		    notif.setLatestEventInfo(mService, from, mService
-			.getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0,
-			intent, PendingIntent.FLAG_ONE_SHOT));
-		    int id = packet.hashCode();
-		    mService.sendNotification(id, notif);
+			if (!(packet instanceof Presence))
+				return;
+			Presence p = (Presence) packet;
+			if (p.getType() != Presence.Type.subscribe)
+				return;
+			String from = p.getFrom();
+			Notification notification = new Notification(android.R.drawable.stat_notify_more, mService.getString(
+				R.string.AcceptContactRequest, from), System.currentTimeMillis());
+			notification.flags = Notification.FLAG_AUTO_CANCEL;
+			Intent intent = new Intent(mService, Subscription.class);
+			intent.setData(Contact.makeXmppUri(from));
+			notification.setLatestEventInfo(mService, from,
+				mService.getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0,
+					intent, PendingIntent.FLAG_ONE_SHOT));
+			int id = p.hashCode();
+			mService.sendNotification(id, notification);
 		}
-	    }, filter);
-
-	    final int n = mRemoteConnListeners.beginBroadcast();
-
-	    for (int i = 0; i < n; i++) {
-		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
-		try {
-		    if (listener != null)
-			listener.reconnectionSuccessful();
-		} catch (RemoteException e) {
-		    // The RemoteCallbackList will take care of removing the
-		    // dead listeners.
-		    Log.w(TAG, "Error while triggering remote connection listeners", e);
-		}
-	    }
-	    mRemoteConnListeners.finishBroadcast();
-	}
-    }
-
-    /**
-     * This PacketListener will set a notification when you got a subscribtion request.
-     * @author Da Risk <da_risk@elyzion.net>
-     */
-    private class SubscribePacketListener implements PacketListener {
-
-	/**
-	 * Constructor.
-	 */
-	public SubscribePacketListener() {
 	}
 
-	@Override
-	public void processPacket(Packet packet) {
-	    if (!(packet instanceof Presence))
-		return;
-	    Presence p = (Presence) packet;
-	    if (p.getType() != Presence.Type.subscribe)
-		return;
-	    String from = p.getFrom();
-	    Notification notification = new Notification(android.R.drawable.stat_notify_more, mService.getString(
-		R.string.AcceptContactRequest, from), System.currentTimeMillis());
-	    notification.flags = Notification.FLAG_AUTO_CANCEL;
-	    Intent intent = new Intent(mService, Subscription.class);
-	    intent.setData(Contact.makeXmppUri(from));
-	    notification.setLatestEventInfo(mService, from,
-		mService.getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0,
-		    intent, PendingIntent.FLAG_ONE_SHOT));
-	    int id = p.hashCode();
-	    mService.sendNotification(id, notification);
-	}
-    }
-
 }
--- a/src/com/beem/project/beem/ui/Chat.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/ui/Chat.java	Fri Oct 14 18:57:07 2011 +0200
@@ -43,930 +43,80 @@
  */
 package com.beem.project.beem.ui;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.jivesoftware.smack.packet.Presence.Mode;
-import org.jivesoftware.smack.util.StringUtils;
-
 import android.app.Activity;
-import android.app.Dialog;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
 import android.content.SharedPreferences;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
 import android.preference.PreferenceManager;
-import android.provider.Contacts;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.RawContacts.Entity;
-import android.text.util.Linkify;
 import android.util.Log;
 import android.view.KeyEvent;
-import android.view.LayoutInflater;
-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.ListView;
 import android.widget.TextView;
 
 import com.beem.project.beem.R;
-import com.beem.project.beem.providers.AvatarProvider;
-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.ui.dialogs.builders.ChatList;
-import com.beem.project.beem.utils.BeemBroadcastReceiver;
-import com.beem.project.beem.utils.Status;
 
 /**
- * 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>
+ * The chat activity for communication with 1 contact.
+ * 
+ * @author Vincent V. <marseille@beem-project.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 = new Handler();
-
-    private IRoster mRoster;
-    private Contact mContact;
-
-    private TextView mContactNameTextView;
-    private TextView mContactStatusMsgTextView;
-    private TextView mContactChatState;
-    private ImageView mContactStatusIcon;
-    private LayerDrawable mAvatarStatusDrawable;
-    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 final IMessageListener mMessageListener = new OnMessageListener();
-    private final IChatManagerListener mChatManagerListener = new ChatManagerListener();
-    private MessagesListAdapter mMessagesListAdapter = new MessagesListAdapter();
-
-    private final ServiceConnection mConn = new BeemServiceConnection();
-    private final BeemBroadcastReceiver mBroadcastReceiver = new BeemBroadcastReceiver();
-    private final BeemRosterListener mBeemRosterListener = new BeemRosterListener();
-    private IXmppFacade mXmppFacade;
-    private String mCurrentAvatarId;
-    private boolean mBinded;
-    private boolean mCompact;
-
-    /**
-     * Constructor.
-     */
-    public Chat() {
-	super();
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    @Override
-    protected void onCreate(Bundle savedBundle) {
-	super.onCreate(savedBundle);
-	this.registerReceiver(mBroadcastReceiver, new IntentFilter(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED));
-	SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
-	mCompact = settings.getBoolean("settings_chat_compact_key", false);
-	// UI
-	if (!mCompact) {
-	    setContentView(R.layout.chat);
-	    mContactNameTextView = (TextView) findViewById(R.id.chat_contact_name);
-	    mContactStatusMsgTextView = (TextView) findViewById(R.id.chat_contact_status_msg);
-	    mContactChatState = (TextView) findViewById(R.id.chat_contact_chat_state);
-	    mContactStatusIcon = (ImageView) findViewById(R.id.chat_contact_status_icon);
-	    mAvatarStatusDrawable = (LayerDrawable) mContactStatusIcon.getDrawable();
-	    mAvatarStatusDrawable.setLayerInset(1, 36, 36, 0, 0);
-	} else {
-	    setContentView(R.layout.chat_compact);
-	}
-	mMessagesListView = (ListView) findViewById(R.id.chat_messages);
-	mMessagesListView.setAdapter(mMessagesListAdapter);
-	mInputField = (EditText) findViewById(R.id.chat_input);
-	mInputField.setOnKeyListener(this);
-	mInputField.requestFocus();
-	mSendButton = (Button) findViewById(R.id.chat_send_message);
-	mSendButton.setOnClickListener(new OnClickListener() {
-	    @Override
-	    public void onClick(View v) {
-		sendMessage();
-	    }
-	});
-	prepareIconsStatus();
-    }
-
-    @Override
-    protected void onResume() {
-	super.onResume();
-	// When coming from account contact
-	//TODO : get account from jid
-	//TODO : if multi account propose select
-	Uri contactURI = getIntent().getData();
-	String jid = contactURI.getPathSegments().get(0);
-	mContact = new Contact(jid);
-	if (!mBinded) {
-	    bindService(SERVICE_INTENT, mConn, BIND_AUTO_CREATE);
-	    mBinded = true;
-	}
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    @Override
-    protected void onDestroy() {
-	super.onDestroy();
-	this.unregisterReceiver(mBroadcastReceiver);
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    @Override
-    protected void onPause() {
-	super.onPause();
-	try {
-	    if (mChat != null) {
-		mChat.setOpen(false);
-		mChat.removeMessageListener(mMessageListener);
-	    }
-	    if (mRoster != null)
-		mRoster.removeRosterListener(mBeemRosterListener);
-	    if (mChatManager != null)
-		mChatManager.removeChatCreationListener(mChatManagerListener);
-	} catch (RemoteException e) {
-	    Log.e(TAG, e.getMessage());
-	}
-	if (mBinded) {
-	    unbindService(mConn);
-	    mBinded = false;
-	}
-	mXmppFacade = null;
-	mRoster = null;
-	mChat = null;
-	mChatManager = null;
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    @Override
-    protected void onNewIntent(Intent intent) {
-	super.onNewIntent(intent);
-	setIntent(intent);
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    @Override
-    protected void onSaveInstanceState(Bundle savedInstanceState) {
-	super.onSaveInstanceState(savedInstanceState);
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    @Override
-    protected void onRestoreInstanceState(Bundle savedInstanceState) {
-	super.onRestoreInstanceState(savedInstanceState);
-    }
-
-    /**
-     * {@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);
-		break;
-	    case R.id.chat_menu_change_chat:
-		try {
-		    final List<Contact> openedChats = mChatManager.getOpenedChatList();
-		    Log.d(TAG, "opened chats = " + openedChats);
-		    Dialog chatList = new ChatList(Chat.this, openedChats).create();
-		    chatList.show();
-		} catch (RemoteException e) {
-		    Log.e(TAG, e.getMessage());
-		}
-		break;
-	    case R.id.chat_menu_close_chat:
-		try {
-		    mChatManager.destroyChat(mChat);
-		} catch (RemoteException e) {
-		    Log.e(TAG, e.getMessage());
-		}
-		this.finish();
-		break;
-	    default:
-		return false;
-	}
-	return true;
-    }
-
-    /**
-     * 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 {
-	if (mChat != null) {
-	    mChat.setOpen(false);
-	    mChat.removeMessageListener(mMessageListener);
-	}
-	mChat = mChatManager.getChat(contact);
-	if (mChat != null) {
-	    mChat.setOpen(true);
-	    mChat.addMessageListener(mMessageListener);
-	    mChatManager.deleteChatNotification(mChat);
-	}
-	mContact = mRoster.getContact(contact.getJID());
-	String res = contact.getSelectedRes();
-	if (mContact == null)
-	    mContact = contact;
-	if (!"".equals(res)) {
-	    mContact.setSelectedRes(res);
-	}
-	updateContactInformations();
-	updateContactStatusIcon();
-
-	playRegisteredTranscript();
-    }
-
-    /**
-     * 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 {
-	mListMessages.clear();
-	if (mChat != null) {
-	    List<MessageText> msgList = convertMessagesList(mChat.getMessages());
-	    mListMessages.addAll(msgList);
-	    mMessagesListAdapter.notifyDataSetChanged();
-	}
-    }
-
-    /**
-     * Convert a list of Message coming from the service to a list of MessageText that can be displayed in UI.
-     * @param chatMessages the list of Message
-     * @return a list of message that can be displayed.
-     */
-    private List<MessageText> convertMessagesList(List<Message> chatMessages) {
-	List<MessageText> result = new ArrayList<MessageText>(chatMessages.size());
-	String remoteName = mContact.getName();
-	String localName = getString(R.string.chat_self);
-	MessageText lastMessage = null;
-
-	for (Message m : chatMessages) {
-	    String name = remoteName;
-	    String fromBareJid = StringUtils.parseBareAddress(m.getFrom());
-	    if (m.getType() == Message.MSG_TYPE_ERROR) {
-		lastMessage = null;
-		result.add(new MessageText(fromBareJid, name, m.getBody(), true, m.getTimestamp()));
-	    } else if (m.getType() == Message.MSG_TYPE_CHAT) {
-		if (fromBareJid == null) { //nofrom or from == yours
-		    name = localName;
-		    fromBareJid = "";
-		}
-
-		if (m.getBody() != null) {
-		    if (lastMessage == null || !fromBareJid.equals(lastMessage.getBareJid())) {
-			lastMessage = new MessageText(fromBareJid, name, m.getBody(), false, m.getTimestamp());
-			result.add(lastMessage);
-		    } else {
-			lastMessage.setMessage(lastMessage.getMessage().concat("\n" + m.getBody()));
-		    }
-		}
-	    }
-	}
-	return result;
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    private final class BeemServiceConnection implements ServiceConnection {
+	private static final String TAG = "Chat";
+	private String mjid;
 
 	/**
 	 * Constructor.
 	 */
-	public BeemServiceConnection() {
-	}
-
-	/**
-	 * {@inheritDoc}.
-	 */
-	@Override
-	public void onServiceConnected(ComponentName name, IBinder service) {
-	    mXmppFacade = IXmppFacade.Stub.asInterface(service);
-	    try {
-		mRoster = mXmppFacade.getRoster();
-		if (mRoster != null)
-		    mRoster.addRosterListener(mBeemRosterListener);
-		mChatManager = mXmppFacade.getChatManager();
-		if (mChatManager != null) {
-		    mChatManager.addChatCreationListener(mChatManagerListener);
-		    changeCurrentChat(mContact);
-		}
-	    } catch (RemoteException e) {
-		Log.e(TAG, e.getMessage());
-	    }
-	}
-
-	/**
-	 * {@inheritDoc}.
-	 */
-	@Override
-	public void onServiceDisconnected(ComponentName name) {
-	    mXmppFacade = null;
-	    try {
-		mRoster.removeRosterListener(mBeemRosterListener);
-		mChatManager.removeChatCreationListener(mChatManagerListener);
-	    } catch (RemoteException e) {
-		Log.e(TAG, e.getMessage());
-	    }
-	}
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    private class BeemRosterListener extends IBeemRosterListener.Stub {
-
-	/**
-	 * Constructor.
-	 */
-	public BeemRosterListener() {
-	}
-
-	/**
-	 * {@inheritDoc}.
-	 */
-	@Override
-	public void onEntriesAdded(List<String> addresses) throws RemoteException {
-	}
-
-	/**
-	 * {@inheritDoc}.
-	 */
-	@Override
-	public void onEntriesDeleted(List<String> addresses) throws RemoteException {
-	}
-
-	/**
-	 * {@inheritDoc}.
-	 */
-	@Override
-	public void onEntriesUpdated(List<String> addresses) throws RemoteException {
+	public Chat() {
+		super();
 	}
 
 	/**
 	 * {@inheritDoc}.
 	 */
 	@Override
-	public void onPresenceChanged(final PresenceAdapter presence) throws RemoteException {
-	    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();
-		    }
-		});
-	    }
-	}
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    private class OnMessageListener extends IMessageListener.Stub {
-
-	/**
-	 * Constructor.
-	 */
-	public OnMessageListener() {
-	}
-
-	/**
-	 * {@inheritDoc}.
-	 */
-	@Override
-	public void processMessage(IChat chat, final Message msg) throws RemoteException {
-	    final String fromBareJid = StringUtils.parseBareAddress(msg.getFrom());
-
-	    if (mContact.getJID().equals(fromBareJid)) {
-		mHandler.post(new Runnable() {
-
-		    @Override
-		    public void run() {
-			if (msg.getType() == Message.MSG_TYPE_ERROR) {
-			    mListMessages.add(new MessageText(fromBareJid, mContact.getName(), msg.getBody(), true, msg
-				.getTimestamp()));
-			    mMessagesListAdapter.notifyDataSetChanged();
-			} else if (msg.getBody() != null) {
-			    MessageText lastMessage = null;
-			    if (mListMessages.size() != 0)
-				lastMessage = mListMessages.get(mListMessages.size() - 1);
-
-			    if (lastMessage != null && lastMessage.getBareJid().equals(fromBareJid)) {
-				lastMessage.setMessage(lastMessage.getMessage().concat("\n" + msg.getBody()));
-				lastMessage.setTimestamp(msg.getTimestamp());
-				mListMessages.set(mListMessages.size() - 1, lastMessage);
-			    } else if (msg.getBody() != null)
-				mListMessages.add(new MessageText(fromBareJid, mContact.getName(), msg.getBody(),
-				    false, msg.getTimestamp()));
-			    mMessagesListAdapter.notifyDataSetChanged();
-			}
-		    }
-		});
-	    }
-	}
-
-	/**
-	 * {@inheritDoc}.
-	 */
-	@Override
-	public void stateChanged(IChat chat) throws RemoteException {
-	    final String state = chat.getState();
-	    mHandler.post(new Runnable() {
-		@Override
-		public void run() {
-		    String text = null;
-		    if ("active".equals(state)) {
-			text = Chat.this.getString(R.string.chat_state_active);
-		    } else if ("composing".equals(state)) {
-			text = Chat.this.getString(R.string.chat_state_composing);
-		    } else if ("gone".equals(state)) {
-			text = Chat.this.getString(R.string.chat_state_gone);
-		    } else if ("inactive".equals(state)) {
-			text = Chat.this.getString(R.string.chat_state_inactive);
-		    } else if ("paused".equals(state)) {
-			text = Chat.this.getString(R.string.chat_state_active);
-		    }
-		    if (!mCompact)
-			mContactChatState.setText(text);
+	protected void onCreate(Bundle savedBundle) {
+		super.onCreate(savedBundle);
+		// TODO : get account from jid. if multi account propose select
+		// Intent { act=android.intent.action.SENDTO dat=imto://jabber/jid
+		// cmp=com.beem.project.beem/.ui.Chat }
+		Uri contactURI = getIntent().getData();		
+		mjid = contactURI.getPathSegments().get(0);
+		
+		SharedPreferences settings = PreferenceManager
+				.getDefaultSharedPreferences(this);
+		boolean isCompact = settings.getBoolean("settings_chat_compact_key",
+				false);
+		// UI
+		if (!isCompact) {
+			setNormalView();
+		} else {
+			setContentView(R.layout.chat_compact);
 		}
-	    });
-
-	}
-    }
 
-    /**
-     * Update the contact informations.
-     */
-    private void updateContactInformations() {
-	// Check for a contact name update
-	String name = mContact.getName();
-	String res = mContact.getSelectedRes();
-	if (!"".equals(res))
-	    name += "(" + res + ")";
-	if (!mCompact) {
-	    if (!(mContactNameTextView.getText().toString().equals(name)))
-		mContactNameTextView.setText(name);
-	    //Check for a contact status message update
-	    if (!(mContactStatusMsgTextView.getText().toString().equals(mContact.getMsgState()))) {
-		mContactStatusMsgTextView.setText(mContact.getMsgState());
-		Linkify.addLinks(mContactStatusMsgTextView, Linkify.WEB_URLS);
-	    }
-	} else {
-	    Mode m = Status.getPresenceModeFromStatus(mContact.getStatus());
-	    if (m == null)
-		setTitle(getString(R.string.chat_name) + " " + name + " ("
-		    + getString(R.string.contact_status_msg_offline) + ")");
-	    else
-		setTitle(getString(R.string.chat_name) + " " + name + " (" + m.name() + ")");
-	}
-    }
-
-    /**
-     * Update the contact status icon.
-     */
-    private void updateContactStatusIcon() {
-	if (mCompact)
-	    return;
-	String id = mContact.getAvatarId();
-	if (id == null)
-	    id = "";
-	Log.d(TAG, "update contact icon  : " + id);
-	if (!id.equals(mCurrentAvatarId)) {
-	    Drawable avatar = getAvatarDrawable(mContact.getAvatarId());
-	    mAvatarStatusDrawable.setDrawableByLayerId(R.id.avatar, avatar);
-	    mCurrentAvatarId = id;
-	}
-	mContactStatusIcon.setImageLevel(mContact.getStatus());
-    }
-
-    /**
-     * Get a Drawable containing the avatar icon.
-     * @param avatarId the avatar id to retrieve or null to get default
-     * @return a Drawable
-     */
-    private Drawable getAvatarDrawable(String avatarId) {
-	Drawable avatarDrawable = null;
-	if (avatarId != null) {
-	    Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(avatarId).build();
-	    InputStream in = null;
-	    try {
-		try {
-		    in = getContentResolver().openInputStream(uri);
-		    avatarDrawable = Drawable.createFromStream(in, avatarId);
-		} finally {
-		    if (in != null)
-			in.close();
-		}
-	    } catch (IOException e) {
-		Log.w(TAG, "Error while setting the avatar", e);
-	    }
-	}
-	if (avatarDrawable == null)
-	    avatarDrawable = getResources().getDrawable(R.drawable.beem_launcher_icon_silver);
-	return avatarDrawable;
-    }
-
-    /**
-     * Prepare the status icons map.
-     */
-    private void prepareIconsStatus() {
-	mStatusIconsMap.put(Status.CONTACT_STATUS_AVAILABLE, BitmapFactory.decodeResource(getResources(),
-	    android.R.drawable.presence_online));
-	mStatusIconsMap.put(Status.CONTACT_STATUS_AVAILABLE_FOR_CHAT, BitmapFactory.decodeResource(getResources(),
-	    android.R.drawable.presence_online));
-	mStatusIconsMap.put(Status.CONTACT_STATUS_AWAY, BitmapFactory.decodeResource(getResources(),
-	    android.R.drawable.presence_away));
-	mStatusIconsMap.put(Status.CONTACT_STATUS_BUSY, BitmapFactory.decodeResource(getResources(),
-	    android.R.drawable.presence_busy));
-	mStatusIconsMap.put(Status.CONTACT_STATUS_DISCONNECT, BitmapFactory.decodeResource(getResources(),
-	    android.R.drawable.presence_offline));
-	mStatusIconsMap.put(Status.CONTACT_STATUS_UNAVAILABLE, BitmapFactory.decodeResource(getResources(),
-	    R.drawable.status_requested));
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    private class MessagesListAdapter extends BaseAdapter {
-
-	/**
-	 * Constructor.
-	 */
-	public MessagesListAdapter() {
-	}
-
-	/**
-	 * Returns the number of messages contained in the messages list.
-	 * @return The number of messages contained in the messages list.
-	 */
-	@Override
-	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.
-	 */
-	@Override
-	public Object getItem(int position) {
-	    return mListMessages.get(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.
-	 */
-	@Override
-	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) {
-	    View sv;
-	    if (convertView == null) {
-		LayoutInflater inflater = Chat.this.getLayoutInflater();
-		sv = inflater.inflate(R.layout.chat_msg_row, null);
-	    } else {
-		sv = convertView;
-	    }
-	    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);
-	    MessageText msg = mListMessages.get(position);
-	    TextView msgName = (TextView) sv.findViewById(R.id.chatmessagename);
-	    msgName.setText(msg.getName());
-	    msgName.setTextColor(Color.WHITE);
-	    msgName.setError(null);
-	    TextView msgText = (TextView) sv.findViewById(R.id.chatmessagetext);
-	    msgText.setText(msg.getMessage());
-	    registerForContextMenu(msgText);
-	    TextView msgDate = (TextView) sv.findViewById(R.id.chatmessagedate);
-	    String date = df.format(msg.getTimestamp());
-	    msgDate.setText(date);
-	    if (msg.isError()) {
-		String err = getString(R.string.chat_error);
-		msgName.setText(err);
-		msgName.setTextColor(Color.RED);
-		msgName.setError(err);
-	    }
-	    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;
-	private boolean mIsError;
-	private Date mTimestamp;
-
-	/**
-	 * 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;
-	    mIsError = false;
-	}
-
-	/**
-	 * 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.
-	 * @param isError if the message is an error message.
-	 */
-	public MessageText(final String bareJid, final String name, final String message, final boolean isError) {
-	    mBareJid = bareJid;
-	    mName = name;
-	    mMessage = message;
-	    mIsError = isError;
-	}
-
-	/**
-	 * 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.
-	 * @param isError if the message is an error message.
-	 * @param date the time of the message.
-	 */
-	public MessageText(final String bareJid, final String name, final String message, final boolean isError,
-	    Date date) {
-	    mBareJid = bareJid;
-	    mName = name;
-	    mMessage = message;
-	    mIsError = isError;
-	    mTimestamp = date;
-	}
-
-	/**
-	 * 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;
-	}
+	private void setNormalView() {
+		Log.d(TAG, "Jid : " + mjid);
+		setContentView(R.layout.chat);
+		TextView ContactNameTextView = (TextView) findViewById(R.id.chat_contact_name);
+		ContactNameTextView.setText(mjid);
+		TextView ContactStatusMsgTextView = (TextView) findViewById(R.id.chat_contact_status_msg);
+		TextView ContactChatStateTextView = (TextView) findViewById(R.id.chat_contact_chat_state);
+		ImageView ContactStatusIcon = (ImageView) findViewById(R.id.chat_contact_status_icon);
+		LayerDrawable AvatarStatusDrawable = (LayerDrawable) ContactStatusIcon
+				.getDrawable();
+		AvatarStatusDrawable.setLayerInset(1, 36, 36, 0, 0);
 
-	/**
-	 * 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;
-	}
-
-	/**
-	 * Get the message type.
-	 * @return true if the message is an error message.
-	 */
-	public boolean isError() {
-	    return mIsError;
-	}
-
-	/**
-	 * Set the Date of the message.
-	 * @param date date of the message.
-	 */
-	public void setTimestamp(Date date) {
-	    mTimestamp = date;
-	}
-
-	/**
-	 * Get the Date of the message.
-	 * @return if it is a delayed message get the date the message was sended.
-	 */
-	public Date getTimestamp() {
-	    return mTimestamp;
-	}
-
-    }
-
-    /**
-     * {@inheritDoc}.
-     */
-    @Override
-    public boolean onKey(View v, int keyCode, KeyEvent event) {
-	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();
-
-	if (!"".equals(inputContent)) {
-	    Message msgToSend = new Message(mContact.getJIDWithRes(), Message.MSG_TYPE_CHAT);
-	    msgToSend.setBody(inputContent);
-
-	    try {
-		if (mChat == null) {
-		    mChat = mChatManager.createChat(mContact, mMessageListener);
-		    mChat.setOpen(true);
-		}
-		mChat.sendMessage(msgToSend);
-	    } catch (RemoteException e) {
-		Log.e(TAG, e.getMessage());
-	    }
-
-	    final String self = getString(R.string.chat_self);
-	    MessageText lastMessage = null;
-	    if (mListMessages.size() != 0)
-		lastMessage = mListMessages.get(mListMessages.size() - 1);
-
-	    if (lastMessage != null && lastMessage.getName().equals(self)) {
-		lastMessage.setMessage(lastMessage.getMessage().concat("\n" + inputContent));
-		lastMessage.setTimestamp(new Date());
-	    } else
-		mListMessages.add(new MessageText(self, self, inputContent, false, new Date()));
-	    mMessagesListAdapter.notifyDataSetChanged();
-	    mInputField.setText(null);
-	}
-    }
-
-    /**
-     * This class is in charge of getting the new chat in the activity if someone talk to you.
-     */
-    private class ChatManagerListener extends IChatManagerListener.Stub {
-
-	/**
-	 * Constructor.
-	 */
-	public ChatManagerListener() {
 	}
 
 	@Override
-	public void chatCreated(IChat chat, boolean locally) {
-	    if (locally)
-		return;
-	    try {
-		String contactJid = mContact.getJIDWithRes();
-		String chatJid = chat.getParticipant().getJIDWithRes();
-		if (chatJid.equals(contactJid)) {
-		    // This should not be happened but to be sure
-		    if (mChat != null) {
-			mChat.setOpen(false);
-			mChat.removeMessageListener(mMessageListener);
-		    }
-		    mChat = chat;
-		    mChat.setOpen(true);
-		    mChat.addMessageListener(mMessageListener);
-		    mChatManager.deleteChatNotification(mChat);
-		}
-	    } catch (RemoteException ex) {
-		Log.e(TAG, "A remote exception occurs during the creation of a chat", ex);
-	    }
+	public boolean onKey(View v, int keyCode, KeyEvent event) {
+		return false;
 	}
-    }
-
-    public class MyReceiver extends BroadcastReceiver {
-
-	@Override
-	public void onReceive(Context context, Intent intent) {
-	    Context c = getApplicationContext();
-	    Intent sendIntent = new Intent();
-	    if (intent.getAction().equals(Intent.ACTION_SENDTO)) {
-		sendIntent.setClass(c, Chat.class);
-		context.startActivity(sendIntent);
-	    }
-	}
-    }
 
 }
--- a/src/com/beem/project/beem/ui/ContactList.java	Mon Aug 22 22:43:19 2011 +0200
+++ b/src/com/beem/project/beem/ui/ContactList.java	Fri Oct 14 18:57:07 2011 +0200
@@ -42,11 +42,9 @@
  */
 package com.beem.project.beem.ui;
 
-import java.util.ArrayList;
+import java.net.URI;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import android.app.Activity;
 import android.app.Dialog;
@@ -55,8 +53,8 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.database.Cursor;
+import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.RemoteException;
 import android.preference.PreferenceManager;
 import android.provider.ContactsContract;
@@ -89,455 +87,492 @@
 import com.beem.project.beem.ui.dialogs.builders.ChatList;
 import com.beem.project.beem.ui.dialogs.builders.DeleteContact;
 import com.beem.project.beem.ui.dialogs.builders.ResendSubscription;
-import com.beem.project.beem.utils.BeemBroadcastReceiver;
 
 /**
  * The contact list activity displays the roster of the user.
+ * 
+ * @author Vincent V. <marseille@beem-project.com>
  */
 public class ContactList extends Activity {
 
-    private static final Intent SERVICE_INTENT = new Intent();
-    static {
-	SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
-    }
-
-    private static final String SETTINGS_HIDDEN_CONTACT = "settings_key_hidden_contact";
-    private static final String TAG = "ContactList";
-
-    /**
-     * Map containing a list of the different contacts of a given group. Each list is a @{link SortedList} so there is
-     * no need to sort it again.
-     */
-
-    private final BeemContactListOnClick mOnContactClick = new BeemContactListOnClick();
-
-    private final ComparatorContactListByStatusAndName<Contact> mComparator = new ComparatorContactListByStatusAndName<Contact>();
-    private List<Contact> mListContact;
-    private String mSelectedGroup;
-    private IRoster mRoster;
-    private Contact mSelectedContact;
-    private IXmppFacade mXmppFacade;
-    private IChatManager mChatManager;
-    private SharedPreferences mSettings;
-    private LayoutInflater mInflater;
-    private BeemBanner mAdapterBanner;
-    private BeemContactList mAdapterContactList;
-    private boolean mBinded;
-
-    private String mAccountName;
-
-    /**
-     * Constructor.
-     */
-    public ContactList() {
-    }
-
-    @Override
-    protected void onCreate(Bundle saveBundle) {
-	super.onCreate(saveBundle);
-	mSettings = PreferenceManager.getDefaultSharedPreferences(this);
-	setContentView(R.layout.contactlist);
-
-	mInflater = getLayoutInflater();
-	mAccountName = getIntent().getExtras().getString(BeemIntent.EXTRA_ACCOUNT);
-
-	//Get Groups list 
-	final Cursor cursorGroup = getContentResolver().query(ContactsContract.Groups.CONTENT_URI,
-	    new String[] { ContactsContract.Groups._ID, ContactsContract.Groups.TITLE }, ContactsContract.Groups.ACCOUNT_NAME + "=?", new String[] {mAccountName}, null);
-	mAdapterBanner = new BeemBanner(this, R.layout.contactlist_group, cursorGroup,
-	    new String[] { ContactsContract.Groups.TITLE }, new int[] { R.id.contactlist_group });
-
-	//Get Contacts list
-	//TODO: Get contact list by account
-	final Cursor cursorContact = getContentResolver().query(
-	    ContactsContract.Contacts.CONTENT_URI,
-	    new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME,
-		ContactsContract.Contacts.CONTACT_STATUS }, null, null, null);
-	//TODO: GetAvatar + Presence
-	mAdapterContactList = new BeemContactList(this, R.layout.contactlistcontact, cursorContact, new String[] {
-	    ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME,
-	    ContactsContract.Contacts.CONTACT_STATUS }, new int[] { R.id.avatar, R.id.contactlistpseudo,
-	    R.id.contactlistmsgperso });
-
-	ListView listView = (ListView) findViewById(R.id.contactlist);
-	listView.setOnItemClickListener(mOnContactClick);
-	registerForContextMenu(listView);
-	listView.setAdapter(mAdapterContactList);
-	Log.e(TAG, "ONCREATE");
-    }
-
-    @Override
-    protected void onResume() {
-	super.onResume();
-	if (!mSettings.getBoolean("settings_key_hide_groups", false))
-	    showGroups();
-	else
-	    hideGroups();
-    }
-
-    @Override
-    public final boolean onCreateOptionsMenu(Menu menu) {
-	super.onCreateOptionsMenu(menu);
-	MenuInflater inflater = getMenuInflater();
-	inflater.inflate(R.menu.contact_list, menu);
-	return true;
-    }
-
-    @Override
-    public final boolean onOptionsItemSelected(MenuItem item) {
-	switch (item.getItemId()) {
-	    case R.id.contact_list_menu_settings:
-		Intent i = new Intent(this, Settings.class);
-		i.putExtra("account_name", mAccountName);
-		startActivity(i);
-		return true;
-	    case R.id.contact_list_menu_add_contact:
-		startActivity(new Intent(ContactList.this, AddContact.class));
-		return true;
-	    case R.id.menu_change_status:
-		startActivity(new Intent(ContactList.this, ChangeStatus.class));
-		return true;
-	    case R.id.contact_list_menu_chatlist:
-		List<Contact> openedChats;
-		try {
-		    openedChats = mChatManager.getOpenedChatList();
-		    Log.d(TAG, "opened chats = " + openedChats);
-		    Dialog chatList = new ChatList(ContactList.this, openedChats).create();
-		    chatList.show();
-		} catch (RemoteException e) {
-		    e.printStackTrace();
-		}
-		return true;
-	    case R.id.menu_disconnect:
-		stopService(SERVICE_INTENT);
-		finish();
-	    default:
-		return false;
-	}
-    }
-
-    @Override
-    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
-	super.onCreateContextMenu(menu, v, menuInfo);
-	MenuInflater inflater = getMenuInflater();
-	inflater.inflate(R.menu.contactlist_context, menu);
-	AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
-	Contact c = mListContact.get(info.position);
-	try {
-	    mSelectedContact = mRoster.getContact(c.getJID());
-	} catch (RemoteException e) {
-	    e.printStackTrace();
-	}
-	menu.setHeaderTitle(mSelectedContact.getJID());
-    }
-
-    @Override
-    public boolean onContextItemSelected(MenuItem item) {
-	Intent in;
-	boolean result;
-	if (mSelectedContact != null) {
-	    switch (item.getItemId()) {
-		case R.id.contact_list_context_menu_chat_item:
-		    List<String> res = mSelectedContact.getMRes();
-		    if (res.isEmpty()) {
-			result = false;
-			break;
-		    }
-		    for (String resv : res) {
-			in = new Intent(this, Chat.class);
-			in.setData(mSelectedContact.toUri(resv));
-			item.getSubMenu().add(resv).setIntent(in);
-		    }
-		    result = true;
-		    break;
-		case R.id.contact_list_context_menu_call_item:
-		    try {
-			mXmppFacade.call(mSelectedContact.getJID() + "/psi");
-			result = true;
-		    } catch (RemoteException e) {
-			e.printStackTrace();
-		    }
-		    result = true;
-		    break;
-		case R.id.contact_list_context_menu_user_info:
-		    item.getSubMenu().setHeaderTitle(mSelectedContact.getJID());
-		    result = true;
-		    break;
-		case R.id.contact_list_context_menu_userinfo_alias:
-		    Dialog alias = new Alias(ContactList.this, mRoster, mSelectedContact).create();
-		    alias.show();
-		    result = true;
-		    break;
-		case R.id.contact_list_context_menu_userinfo_group:
-		    in = new Intent(this, GroupList.class);
-		    in.putExtra("contact", mSelectedContact);
-		    startActivity(in);
-		    result = true;
-		    break;
-		case R.id.contact_list_context_menu_userinfo_subscription:
-		    Dialog subscription = new ResendSubscription(ContactList.this, mXmppFacade, mSelectedContact)
-			.create();
-		    subscription.show();
-		    result = true;
-		    break;
-		case R.id.contact_list_context_menu_userinfo_block:
-		    result = true;
-		    break;
-		case R.id.contact_list_context_menu_userinfo_delete:
-		    Dialog delete = new DeleteContact(ContactList.this, mRoster, mSelectedContact).create();
-		    delete.show();
-		    result = true;
-		    break;
-		default:
-		    result = super.onContextItemSelected(item);
-		    break;
-	    }
-	    return result;
-	}
-	return super.onContextItemSelected(item);
-    }
-
-    /**
-     * Build and display the contact list.
-     * @param group name of the contact list.
-     */
-    private void buildContactList(String group) {
-
-    }
-
-    /**
-     * Show the groups view.
-     */
-    private void showGroups() {
-
-	ViewStub stub = (ViewStub) findViewById(R.id.contactlist_stub);
-	if (stub != null) {
-	    View v = stub.inflate();
-	    Gallery g = (Gallery) v.findViewById(R.id.contactlist_banner);
-	    g.setOnItemClickListener(new OnItemClickGroupName());
-	    g.setAdapter(mAdapterBanner);
-	    g.setSelection(0);
-	} else {
-	    ((LinearLayout) findViewById(R.id.contactlist_groupstub)).setVisibility(View.VISIBLE);
-	    Gallery g = (Gallery) findViewById(R.id.contactlist_banner);
-	    g.setSelection(0);
-	}
-    }
-
-    /**
-     * Hide the groups view.
-     */
-    private void hideGroups() {
-	View v = findViewById(R.id.contactlist_groupstub);
-	if (v != null)
-	    v.setVisibility(View.GONE);
-    }
-
-    /**
-     * Adapter contact list.
-     */
-    private static class BeemContactList extends SimpleCursorAdapter implements Filterable {
-
-	private Context mContext;
-	private int mLayout;
-
-	public BeemContactList(Context context, int layout, Cursor c, String[] from, int[] to) {
-	    super(context, layout, c, from, to);
-	    mContext = context;
-	    mLayout = layout;
+	private static final Intent SERVICE_INTENT = new Intent();
+	static {
+		SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem",
+				"com.beem.project.beem.BeemService"));
 	}
 
-	@Override
-	public View newView(Context context, Cursor cursor, ViewGroup parent) {
-	    final LayoutInflater inflater = LayoutInflater.from(mContext);
-	    return inflater.inflate(mLayout, parent, false);
-	}
-
-	@Override
-	public void bindView(View view, Context context, Cursor cursor) {
-	    String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
-	    TextView nameText = (TextView) view.findViewById(R.id.contactlistpseudo);
-	    if (nameText != null) {
-		nameText.setText(name);
-	    }
-
-	    String msgStatus = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.CONTACT_STATUS));
-	    TextView msgStatusText = (TextView) view.findViewById(R.id.contactlistmsgperso);
-	    if (msgStatusText != null) {
-		msgStatusText.setText(msgStatus);
-	    }
-
-	    //		ImageView img = (ImageView) view.findViewById(R.id.avatar);
-	    //		String avatarId = curContact.getAvatarId();
-	    //		int contactStatus = curContact.getStatus();
-	    //		Drawable avatar = getAvatarStatusDrawable(avatarId);
-	    //		img.setImageDrawable(avatar);
-	    //		img.setImageLevel(contactStatus);
-	}
-
-	//	@Override
-	//	public Filter getFilter() {
-	//	    return mFilter;
-	//	}
-
-	/**
-	 * Get a LayerDrawable containing the avatar and the status icon. The status icon will change with the level of
-	 * the drawable.
-	 * @param avatarId the avatar id to retrieve or null to get default
-	 * @return a LayerDrawable
-	 */
-	//	private Drawable getAvatarStatusDrawable(String avatarId) {
-	//	    Drawable avatarDrawable = null;
-	//	    if (avatarId != null) {
-	//		Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(avatarId).build();
-	//		InputStream in = null;
-	//		try {
-	//		    try {
-	//			in = getContentResolver().openInputStream(uri);
-	//			avatarDrawable = Drawable.createFromStream(in, avatarId);
-	//		    } finally {
-	//			if (in != null)
-	//			    in.close();
-	//		    }
-	//		} catch (IOException e) {
-	//		    Log.w(TAG, "Error while setting the avatar", e);
-	//		}
-	//	    }
-	//	    if (avatarDrawable == null)
-	//		avatarDrawable = getResources().getDrawable(R.drawable.beem_launcher_icon_silver);
-	//	    LayerDrawable ld = (LayerDrawable) getResources().getDrawable(R.drawable.avatar_status);
-	//	    ld.setLayerInset(1, 36, 36, 0, 0);
-	//	    ld.setDrawableByLayerId(R.id.avatar, avatarDrawable);
-	//	    return ld;
-	//	}
+	private static final String SETTINGS_HIDDEN_CONTACT = "settings_key_hidden_contact";
+	private static final String TAG = "ContactList";
 
 	/**
-	 * A Filter which select Contact to display by searching in ther Jid.
+	 * Map containing a list of the different contacts of a given group. Each
+	 * list is a @{link SortedList} so there is no need to sort it again.
 	 */
-	//	private class ContactFilter extends Filter {
-	//
-	//	    /**
-	//	     * Create a ContactFilter.
-	//	     */
-	//	    public ContactFilter() {
-	//	    }
-	//
-	//	    @Override
-	//	    protected Filter.FilterResults performFiltering(CharSequence constraint) {
-	//		Log.d(TAG, "performFiltering");
-	//		List<Contact> result = mListContact;
-	//		if (constraint.length() > 0) {
-	//		    result = new LinkedList<Contact>();
-	//		    for (Contact c : mContactOnGroup.get(mSelectedGroup)) {
-	//			if (c.getJID().contains(constraint))
-	//			    result.add(c);
-	//		    }
-	//		}
-	//		Filter.FilterResults fr = new Filter.FilterResults();
-	//		fr.values = result;
-	//		fr.count = result.size();
-	//		return fr;
-	//	    }
-	//
-	//	    @Override
-	//	    protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
-	//		Log.d(TAG, "publishResults");
-	//		List<Contact> contacts = (List<Contact>) results.values;
-	//		mListContact = contacts;
-	//		notifyDataSetChanged();
-	//	    }
-	//	}
-    }
 
-    /**
-     * Adapter banner group list.
-     */
-    private static class BeemBanner extends SimpleCursorAdapter {
-
-	private Context mContext;
-	private int mLayout;
-
-	public BeemBanner(Context context, int layout, Cursor c, String[] from, int[] to) {
-	    super(context, layout, c, from, to);
-	    mContext = context;
-	    mLayout = layout;
-	}
-
-	@Override
-	public View newView(Context context, Cursor cursor, ViewGroup parent) {
-	    final LayoutInflater inflater = LayoutInflater.from(mContext);
-	    return inflater.inflate(mLayout, parent, false);
-	}
+	private final BeemContactListOnClick mOnContactClick = new BeemContactListOnClick();
 
-	@Override
-	public void bindView(View view, Context context, Cursor cursor) {
-	    String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Groups.TITLE));
-	    TextView nameText = (TextView) view.findViewById(R.id.contactlist_group);
-	    if (nameText != null) {
-		nameText.setText(name);
-	    }
-	}
-    }
-
-    /**
-     * Comparator Contact by status and name.
-     */
-    private static class ComparatorContactListByStatusAndName<T> implements Comparator<T> {
-	/**
-	 * Constructor.
-	 */
-	public ComparatorContactListByStatusAndName() {
-	}
+	private final ComparatorContactListByStatusAndName<Contact> mComparator = new ComparatorContactListByStatusAndName<Contact>();
+	private IRoster mRoster;
+	private Contact mSelectedContact;
+	private IXmppFacade mXmppFacade;
+	private IChatManager mChatManager;
+	private SharedPreferences mSettings;
+	private BeemBanner mAdapterBanner;
+	private BeemContactList mAdapterContactList;
 
-	@Override
-	public int compare(T c1, T c2) {
-	    if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) {
-		return 1;
-	    } else if (((Contact) c1).getStatus() > ((Contact) c2).getStatus()) {
-		return -1;
-	    } else
-		return ((Contact) c1).getName().compareToIgnoreCase(((Contact) c2).getName());
-	}
-    }
-
-    /**
-     * Event simple click on item of the contact list.
-     */
-    private class BeemContactListOnClick implements OnItemClickListener {
-	/**
-	 * Constructor.
-	 */
-	public BeemContactListOnClick() {
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public void onItemClick(AdapterView<?> arg0, View v, int pos, long lpos) {
-	    Contact c = mListContact.get(pos);
-	    Intent i = new Intent(ContactList.this, Chat.class);
-	    i.setData(c.toUri());
-	    startActivity(i);
-	}
-    }
-
-    /**
-     * Event simple click on middle group name.
-     */
-    private class OnItemClickGroupName implements OnItemClickListener {
+	private String mAccountName;
 
 	/**
 	 * Constructor.
 	 */
-	public OnItemClickGroupName() {
+	public ContactList() {
+	}
+
+	@Override
+	protected void onCreate(Bundle saveBundle) {
+		super.onCreate(saveBundle);
+		mSettings = PreferenceManager.getDefaultSharedPreferences(this);
+		setContentView(R.layout.contactlist);
+
+		mAccountName = getIntent().getExtras().getString(
+				BeemIntent.EXTRA_ACCOUNT);
+
+		// Get Groups list
+		final Cursor cursorGroup = getContentResolver().query(
+				ContactsContract.Groups.CONTENT_URI,
+				new String[] { ContactsContract.Groups._ID,
+						ContactsContract.Groups.TITLE },
+				ContactsContract.Groups.ACCOUNT_NAME + "=?",
+				new String[] { mAccountName }, null);
+		mAdapterBanner = new BeemBanner(this, R.layout.contactlist_group,
+				cursorGroup, new String[] { ContactsContract.Groups.TITLE },
+				new int[] { R.id.contactlist_group });
+
+		// Get Contacts list
+		// TODO: Get contact list by account
+		final Cursor cursorContact = getContentResolver().query(
+				ContactsContract.RawContacts.CONTENT_URI,
+				new String[] { ContactsContract.RawContacts._ID,
+						ContactsContract.RawContacts.SOURCE_ID },
+				ContactsContract.RawContacts.ACCOUNT_NAME + "=?",
+				new String[] { mAccountName }, null);
+		// TODO: GetAvatar + Presence
+		mAdapterContactList = new BeemContactList(this,
+				R.layout.contactlistcontact, cursorContact, new String[] {
+						ContactsContract.RawContacts._ID,
+						ContactsContract.RawContacts.SOURCE_ID }, new int[] {
+						R.id.avatar, R.id.contactlistpseudo,
+						R.id.contactlistmsgperso });
+
+		ListView listView = (ListView) findViewById(R.id.contactlist);
+		listView.setOnItemClickListener(mOnContactClick);
+		registerForContextMenu(listView);
+		listView.setAdapter(mAdapterContactList);
+		Log.e(TAG, "ONCREATE");
+	}
+
+	@Override
+	protected void onResume() {
+		super.onResume();
+		if (!mSettings.getBoolean("settings_key_hide_groups", false))
+			showGroups();
+		else
+			hideGroups();
+	}
+
+	@Override
+	public final boolean onCreateOptionsMenu(Menu menu) {
+		super.onCreateOptionsMenu(menu);
+		MenuInflater inflater = getMenuInflater();
+		inflater.inflate(R.menu.contact_list, menu);
+		return true;
+	}
+
+	@Override
+	public final boolean onOptionsItemSelected(MenuItem item) {
+		switch (item.getItemId()) {
+		case R.id.contact_list_menu_settings:
+			Intent i = new Intent(this, Settings.class);
+			i.putExtra("account_name", mAccountName);
+			startActivity(i);
+			return true;
+		case R.id.contact_list_menu_add_contact:
+			startActivity(new Intent(ContactList.this, AddContact.class));
+			return true;
+		case R.id.menu_change_status:
+			startActivity(new Intent(ContactList.this, ChangeStatus.class));
+			return true;
+		case R.id.contact_list_menu_chatlist:
+			List<Contact> openedChats;
+			try {
+				openedChats = mChatManager.getOpenedChatList();
+				Log.d(TAG, "opened chats = " + openedChats);
+				Dialog chatList = new ChatList(ContactList.this, openedChats)
+						.create();
+				chatList.show();
+			} catch (RemoteException e) {
+				e.printStackTrace();
+			}
+			return true;
+		case R.id.menu_disconnect:
+			stopService(SERVICE_INTENT);
+			finish();
+		default:
+			return false;
+		}
+	}
+
+	@Override
+	public void onCreateContextMenu(ContextMenu menu, View v,
+			ContextMenu.ContextMenuInfo menuInfo) {
+		super.onCreateContextMenu(menu, v, menuInfo);
+		MenuInflater inflater = getMenuInflater();
+		inflater.inflate(R.menu.contactlist_context, menu);
+		AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+		// Contact c = new Contact();
+		// try {
+		// mSelectedContact = mRoster.getContact(c.getJID());
+		// } catch (RemoteException e) {
+		// e.printStackTrace();
+		// }
+		// menu.setHeaderTitle(mSelectedContact.getJID());
 	}
 
 	@Override
-	public void onItemClick(AdapterView<?> arg0, View v, int i, long l) {
-	    //	    String group = mListGroup.get(i);
-	    //	    buildContactList(group);
+	public boolean onContextItemSelected(MenuItem item) {
+		Intent in;
+		boolean result;
+		if (mSelectedContact != null) {
+			switch (item.getItemId()) {
+			case R.id.contact_list_context_menu_chat_item:
+				List<String> res = mSelectedContact.getMRes();
+				if (res.isEmpty()) {
+					result = false;
+					break;
+				}
+				for (String resv : res) {
+					in = new Intent(this, Chat.class);
+					in.setData(mSelectedContact.toUri(resv));
+					item.getSubMenu().add(resv).setIntent(in);
+				}
+				result = true;
+				break;
+			case R.id.contact_list_context_menu_call_item:
+				try {
+					mXmppFacade.call(mSelectedContact.getJID() + "/psi");
+					result = true;
+				} catch (RemoteException e) {
+					e.printStackTrace();
+				}
+				result = true;
+				break;
+			case R.id.contact_list_context_menu_user_info:
+				item.getSubMenu().setHeaderTitle(mSelectedContact.getJID());
+				result = true;
+				break;
+			case R.id.contact_list_context_menu_userinfo_alias:
+				Dialog alias = new Alias(ContactList.this, mRoster,
+						mSelectedContact).create();
+				alias.show();
+				result = true;
+				break;
+			case R.id.contact_list_context_menu_userinfo_group:
+				in = new Intent(this, GroupList.class);
+				in.putExtra("contact", mSelectedContact);
+				startActivity(in);
+				result = true;
+				break;
+			case R.id.contact_list_context_menu_userinfo_subscription:
+				Dialog subscription = new ResendSubscription(ContactList.this,
+						mXmppFacade, mSelectedContact).create();
+				subscription.show();
+				result = true;
+				break;
+			case R.id.contact_list_context_menu_userinfo_block:
+				result = true;
+				break;
+			case R.id.contact_list_context_menu_userinfo_delete:
+				Dialog delete = new DeleteContact(ContactList.this, mRoster,
+						mSelectedContact).create();
+				delete.show();
+				result = true;
+				break;
+			default:
+				result = super.onContextItemSelected(item);
+				break;
+			}
+			return result;
+		}
+		return super.onContextItemSelected(item);
+	}
+
+	/**
+	 * Build and display the contact list.
+	 * 
+	 * @param group
+	 *            name of the contact list.
+	 */
+	private void buildContactList(String group) {
+
+	}
+
+	/**
+	 * Show the groups view.
+	 */
+	private void showGroups() {
+
+		ViewStub stub = (ViewStub) findViewById(R.id.contactlist_stub);
+		if (stub != null) {
+			View v = stub.inflate();
+			Gallery g = (Gallery) v.findViewById(R.id.contactlist_banner);
+			g.setOnItemClickListener(new OnItemClickGroupName());
+			g.setAdapter(mAdapterBanner);
+			g.setSelection(0);
+		} else {
+			((LinearLayout) findViewById(R.id.contactlist_groupstub))
+					.setVisibility(View.VISIBLE);
+			Gallery g = (Gallery) findViewById(R.id.contactlist_banner);
+			g.setSelection(0);
+		}
+	}
+
+	/**
+	 * Hide the groups view.
+	 */
+	private void hideGroups() {
+		View v = findViewById(R.id.contactlist_groupstub);
+		if (v != null)
+			v.setVisibility(View.GONE);
 	}
-    }
+
+	/**
+	 * Adapter contact list.
+	 */
+	private static class BeemContactList extends SimpleCursorAdapter implements
+			Filterable {
+
+		private Context mContext;
+		private int mLayout;
+
+		public BeemContactList(Context context, int layout, Cursor c,
+				String[] from, int[] to) {
+			super(context, layout, c, from, to);
+			mContext = context;
+			mLayout = layout;
+		}
+
+		@Override
+		public View newView(Context context, Cursor cursor, ViewGroup parent) {
+			final LayoutInflater inflater = LayoutInflater.from(mContext);
+			return inflater.inflate(mLayout, parent, false);
+		}
+
+		@Override
+		public void bindView(View view, Context context, Cursor cursor) {
+			String name = cursor.getString(cursor
+					.getColumnIndex(ContactsContract.RawContacts.SOURCE_ID));
+			String jid = cursor.getString(cursor
+					.getColumnIndex(ContactsContract.RawContacts.SOURCE_ID));
+			TextView nameText = (TextView) view
+					.findViewById(R.id.contactlistpseudo);
+			if (nameText != null) {
+				nameText.setText(name);
+			}
+
+			// String msgStatus = cursor.getString(cursor
+			// .getColumnIndex(ContactsContract.Contacts.CONTACT_STATUS));
+			// TextView msgStatusText = (TextView) view
+			// .findViewById(R.id.contactlistmsgperso);
+			// if (msgStatusText != null) {
+			// msgStatusText.setText(msgStatus);
+			// }
+
+			view.setTag(jid);
+
+			// ImageView img = (ImageView) view.findViewById(R.id.avatar);
+			// String avatarId = curContact.getAvatarId();
+			// int contactStatus = curContact.getStatus();
+			// Drawable avatar = getAvatarStatusDrawable(avatarId);
+			// img.setImageDrawable(avatar);
+			// img.setImageLevel(contactStatus);
+		}
+
+		// @Override
+		// public Filter getFilter() {
+		// return mFilter;
+		// }
+
+		/**
+		 * Get a LayerDrawable containing the avatar and the status icon. The
+		 * status icon will change with the level of the drawable.
+		 * 
+		 * @param avatarId
+		 *            the avatar id to retrieve or null to get default
+		 * @return a LayerDrawable
+		 */
+		// private Drawable getAvatarStatusDrawable(String avatarId) {
+		// Drawable avatarDrawable = null;
+		// if (avatarId != null) {
+		// Uri uri =
+		// AvatarProvider.CONTENT_URI.buildUpon().appendPath(avatarId).build();
+		// InputStream in = null;
+		// try {
+		// try {
+		// in = getContentResolver().openInputStream(uri);
+		// avatarDrawable = Drawable.createFromStream(in, avatarId);
+		// } finally {
+		// if (in != null)
+		// in.close();
+		// }
+		// } catch (IOException e) {
+		// Log.w(TAG, "Error while setting the avatar", e);
+		// }
+		// }
+		// if (avatarDrawable == null)
+		// avatarDrawable =
+		// getResources().getDrawable(R.drawable.beem_launcher_icon_silver);
+		// LayerDrawable ld = (LayerDrawable)
+		// getResources().getDrawable(R.drawable.avatar_status);
+		// ld.setLayerInset(1, 36, 36, 0, 0);
+		// ld.setDrawableByLayerId(R.id.avatar, avatarDrawable);
+		// return ld;
+		// }
+
+		/**
+		 * A Filter which select Contact to display by searching in ther Jid.
+		 */
+		// private class ContactFilter extends Filter {
+		//
+		// /**
+		// * Create a ContactFilter.
+		// */
+		// public ContactFilter() {
+		// }
+		//
+		// @Override
+		// protected Filter.FilterResults performFiltering(CharSequence
+		// constraint) {
+		// Log.d(TAG, "performFiltering");
+		// List<Contact> result = mListContact;
+		// if (constraint.length() > 0) {
+		// result = new LinkedList<Contact>();
+		// for (Contact c : mContactOnGroup.get(mSelectedGroup)) {
+		// if (c.getJID().contains(constraint))
+		// result.add(c);
+		// }
+		// }
+		// Filter.FilterResults fr = new Filter.FilterResults();
+		// fr.values = result;
+		// fr.count = result.size();
+		// return fr;
+		// }
+		//
+		// @Override
+		// protected void publishResults(CharSequence constraint,
+		// Filter.FilterResults results) {
+		// Log.d(TAG, "publishResults");
+		// List<Contact> contacts = (List<Contact>) results.values;
+		// mListContact = contacts;
+		// notifyDataSetChanged();
+		// }
+		// }
+	}
+
+	/**
+	 * Adapter banner group list.
+	 */
+	private static class BeemBanner extends SimpleCursorAdapter {
+
+		private Context mContext;
+		private int mLayout;
+
+		public BeemBanner(Context context, int layout, Cursor c, String[] from,
+				int[] to) {
+			super(context, layout, c, from, to);
+			mContext = context;
+			mLayout = layout;
+		}
+
+		@Override
+		public View newView(Context context, Cursor cursor, ViewGroup parent) {
+			final LayoutInflater inflater = LayoutInflater.from(mContext);
+			return inflater.inflate(mLayout, parent, false);
+		}
+
+		@Override
+		public void bindView(View view, Context context, Cursor cursor) {
+			String name = cursor.getString(cursor
+					.getColumnIndex(ContactsContract.Groups.TITLE));
+			TextView nameText = (TextView) view
+					.findViewById(R.id.contactlist_group);
+			if (nameText != null) {
+				nameText.setText(name);
+			}
+		}
+	}
+
+	/**
+	 * Comparator Contact by status and name.
+	 */
+	private static class ComparatorContactListByStatusAndName<T> implements
+			Comparator<T> {
+		/**
+		 * Constructor.
+		 */
+		public ComparatorContactListByStatusAndName() {
+		}
+
+		@Override
+		public int compare(T c1, T c2) {
+			if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) {
+				return 1;
+			} else if (((Contact) c1).getStatus() > ((Contact) c2).getStatus()) {
+				return -1;
+			} else
+				return ((Contact) c1).getName().compareToIgnoreCase(
+						((Contact) c2).getName());
+		}
+	}
+
+	/**
+	 * Event simple click on item of the contact list.
+	 */
+	private class BeemContactListOnClick implements OnItemClickListener {
+		/**
+		 * Constructor.
+		 */
+		public BeemContactListOnClick() {
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void onItemClick(AdapterView<?> arg0, View v, int pos, long lpos) {
+			String jid = (String) v.getTag();
+			Log.i(TAG, "OnClick Jid :" + jid);
+			Intent i = new Intent(ContactList.this, Chat.class);
+			i.setData(Uri.parse("imto://jabber/" + jid));
+			startActivity(i);
+		}
+	}
+
+	/**
+	 * Event simple click on middle group name.
+	 */
+	private class OnItemClickGroupName implements OnItemClickListener {
+
+		/**
+		 * Constructor.
+		 */
+		public OnItemClickGroupName() {
+		}
+
+		@Override
+		public void onItemClick(AdapterView<?> arg0, View v, int i, long l) {
+			// String group = mListGroup.get(i);
+			// buildContactList(group);
+		}
+	}
 
 }