Code format
author"Vincent Veronis"
Fri, 12 Aug 2011 11:13:15 +0200
changeset 899 43e0206f1135
parent 898 965a9876c37a
child 900 6e537de6b190
Code format
src/com/beem/project/beem/BeemService.java
src/com/beem/project/beem/BeemSync.java
src/com/beem/project/beem/account/Authenticator.java
src/com/beem/project/beem/account/AuthenticatorService.java
src/com/beem/project/beem/account/SyncAdapter.java
src/com/beem/project/beem/account/SyncAdapterService.java
src/com/beem/project/beem/ui/Login.java
--- a/src/com/beem/project/beem/BeemService.java	Sat Jul 23 01:28:07 2011 +0200
+++ b/src/com/beem/project/beem/BeemService.java	Fri Aug 12 11:13:15 2011 +0200
@@ -43,20 +43,13 @@
  */
 package com.beem.project.beem;
 
-import java.io.IOException;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.jivesoftware.smack.ConnectionConfiguration;
 import org.jivesoftware.smack.Roster;
-import org.jivesoftware.smack.RosterEntry;
-import org.jivesoftware.smack.RosterGroup;
 import org.jivesoftware.smack.XMPPConnection;
 import org.jivesoftware.smack.Roster.SubscriptionMode;
-import org.jivesoftware.smack.packet.Presence;
 import org.jivesoftware.smack.provider.ProviderManager;
-import org.jivesoftware.smack.util.StringUtils;
 import org.jivesoftware.smackx.packet.ChatStateExtension;
 import org.jivesoftware.smackx.provider.DelayInfoProvider;
 import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
@@ -67,23 +60,16 @@
 import org.jivesoftware.smackx.pubsub.provider.PubSubProvider;
 
 import android.accounts.Account;
-import android.accounts.AccountManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.Service;
 import android.content.BroadcastReceiver;
-import android.content.ContentProviderOperation;
-import android.content.ContentUris;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.OperationApplicationException;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
-import android.database.Cursor;
 import android.net.ConnectivityManager;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -91,14 +77,10 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.provider.ContactsContract;
 import android.util.Log;
 
-import com.beem.project.beem.service.BeemAvatarCache;
-import com.beem.project.beem.service.RosterAdapter;
 import com.beem.project.beem.service.XmppConnectionAdapter;
 import com.beem.project.beem.service.XmppFacade;
-import com.beem.project.beem.service.aidl.IRoster;
 import com.beem.project.beem.service.aidl.IXmppFacade;
 import com.beem.project.beem.smack.avatar.AvatarMetadataProvider;
 import com.beem.project.beem.smack.avatar.AvatarProvider;
@@ -119,9 +101,9 @@
 
     private static final String TAG = "BeemService";
     private static final int MESSAGE_CONNECT = 0x1;
-    private static final int MESSAGE_SEND_MSG = 0x2;
-    private static final int MESSAGE_SYNC = 0x3;
-    private static final int NB_DB_OPERATION = 50;
+    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>();
@@ -293,7 +275,6 @@
      */
     public IXmppFacade getBind() {
 	//TODO: Prendre le bon mbind dans le tableau
-	Log.e(TAG, "GETBIND");
 	return mBind.get(0);
     }
 
@@ -469,6 +450,8 @@
 	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)) {
@@ -493,6 +476,9 @@
 		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);
@@ -500,14 +486,17 @@
 			con.handleMessage(msg);
 		    }
 		    break;
-		case MESSAGE_SYNC:		 
+		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) {
-		        manageRoster(co.getAdaptee().getRoster(), a);
+			BeemSync sync = new BeemSync(getBaseContext());
+			if (co.getAdaptee() != null)
+			    sync.manageRoster(co.getAdaptee().getRoster(), a);
 		    }
 		    break;
 		default:
@@ -518,305 +507,54 @@
 
     private void handleConnect(Bundle b) {
 	Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED);
-	
+
 	String account = null;
 	if (b != null) {
-	    Log.e("VIEW", "ID"+b.getInt("VIEW"));	    	   
 	    account = b.getString(BeemIntent.EXTRA_ACCOUNT);
 	    res.putExtra(BeemIntent.EXTRA_ACCOUNT, account);
 	}
-	if (account == null) //TODO temporary
-	    account = "dummy";
-	if (account == null) {
-	    //connect all
+	if (mConnection.containsKey(account)) {
+	    res.setAction(BeemIntent.ACTION_CONNECTED);
 	} 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);
+	    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));
 		}
-	    } catch (RemoteException e) {
-		Log.e(TAG, "Unable to connect " + account, e);
-	    }
-	    sendBroadcast(res);
-	}
-    }
-
-    /**
-     * Method to execute content provider operation.
-     * @param ops
-     */
-    private void executeOperation(final ArrayList<ContentProviderOperation> ops) {
-	try {
-	    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();
-    }
+		mBeemConnection.put(account, beemco);
+		XmppConnectionAdapter beemcoAdapter = new XmppConnectionAdapter(beemco.getConnectionConfiguration(),
+		    beemco.getJid(), beemco.getPassword(), this);
 
-    /**
-     * Roster sync method.
-     * @param r The roster to sync
-     * @param a The account related
-     */
-    private void manageRoster(final Roster r, final Account a) {
-	Log.e("OOO", "roster" + r + "account" + a);
-	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);
-    }
+		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);
+		    }
+		} catch (RemoteException e) {
+		    Log.e(TAG, "Unable to connect " + account, e);
+		}
 
-    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 = 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;
+	sendBroadcast(res);
     }
 
-    /**
-     * 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;
-    }
-
-    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(getBaseContext());
-	try {
-	    builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bac.get(entry.getUser()));
-	} catch (IOException e) {
-	    Log.e(TAG, "Error cache beem avatar", e);
-	}
-	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);
-	}
-	//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 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 = 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;
-    }
-
-    /**
-     * 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 = 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;
+    private void handleDisconnect(Bundle b) {
+	Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED);
+	String account = b.getString(BeemIntent.EXTRA_ACCOUNT);
+	mConnection.remove(account);
+	sendBroadcast(res);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/BeemSync.java	Fri Aug 12 11:13:15 2011 +0200
@@ -0,0 +1,345 @@
+/*
+    BEEM is a videoconference application on the Android Platform.
+
+    Copyright (C) 2009 by Frederic-Charles Barthelery,
+                          Jean-Manuel Da Silva,
+                          Nikita Kozlov,
+                          Philippe Lago,
+                          Jean Baptiste Vergely,
+                          Vincent Veronis.
+
+    This file is part of BEEM.
+
+    BEEM is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    BEEM is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.
+
+    Please send bug reports with examples or suggestions to
+    contact@beem-project.com or http://dev.beem-project.com/
+ */
+
+package com.beem.project.beem;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.jivesoftware.smack.Roster;
+import org.jivesoftware.smack.RosterEntry;
+import org.jivesoftware.smack.RosterGroup;
+import org.jivesoftware.smack.packet.Presence;
+
+import android.accounts.Account;
+import android.content.ContentProviderOperation;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.OperationApplicationException;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
+import android.util.Log;
+
+import com.beem.project.beem.service.BeemAvatarCache;
+import com.beem.project.beem.utils.Status;
+
+/**
+ * Roster synchronisation, informations in database.
+ * @author Vincent V. <marseille@beem-project.com>
+ */
+public class BeemSync {
+
+    private static final String TAG = "BeemSync";
+    private static final int NB_DB_OPERATION = 50;
+
+    private Context mContext;
+
+    /**
+     * 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);
+	}
+	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;
+	}
+	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());
+	}
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * 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());
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * 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;
+    }
+}
--- a/src/com/beem/project/beem/account/Authenticator.java	Sat Jul 23 01:28:07 2011 +0200
+++ b/src/com/beem/project/beem/account/Authenticator.java	Fri Aug 12 11:13:15 2011 +0200
@@ -25,21 +25,6 @@
 
     Please send bug reports with examples or suggestions to
     contact@beem-project.com or http://dev.beem-project.com/
-
-    Epitech, hereby disclaims all copyright interest in the program "Beem"
-    written by Frederic-Charles Barthelery,
-               Jean-Manuel Da Silva,
-               Nikita Kozlov,
-               Philippe Lago,
-               Jean Baptiste Vergely,
-               Vincent Veronis.
-
-    Nicolas Sadirac, November 26, 2009
-    President of Epitech.
-
-    Flavien Astraud, November 26, 2009
-    Head of the EIP Laboratory.
-
  */
 
 package com.beem.project.beem.account;
--- a/src/com/beem/project/beem/account/AuthenticatorService.java	Sat Jul 23 01:28:07 2011 +0200
+++ b/src/com/beem/project/beem/account/AuthenticatorService.java	Fri Aug 12 11:13:15 2011 +0200
@@ -25,21 +25,6 @@
 
     Please send bug reports with examples or suggestions to
     contact@beem-project.com or http://dev.beem-project.com/
-
-    Epitech, hereby disclaims all copyright interest in the program "Beem"
-    written by Frederic-Charles Barthelery,
-               Jean-Manuel Da Silva,
-               Nikita Kozlov,
-               Philippe Lago,
-               Jean Baptiste Vergely,
-               Vincent Veronis.
-
-    Nicolas Sadirac, November 26, 2009
-    President of Epitech.
-
-    Flavien Astraud, November 26, 2009
-    Head of the EIP Laboratory.
-
  */
 
 package com.beem.project.beem.account;
--- a/src/com/beem/project/beem/account/SyncAdapter.java	Sat Jul 23 01:28:07 2011 +0200
+++ b/src/com/beem/project/beem/account/SyncAdapter.java	Fri Aug 12 11:13:15 2011 +0200
@@ -25,21 +25,6 @@
 
     Please send bug reports with examples or suggestions to
     contact@beem-project.com or http://dev.beem-project.com/
-
-    Epitech, hereby disclaims all copyright interest in the program "Beem"
-    written by Frederic-Charles Barthelery,
-               Jean-Manuel Da Silva,
-               Nikita Kozlov,
-               Philippe Lago,
-               Jean Baptiste Vergely,
-               Vincent Veronis.
-
-    Nicolas Sadirac, November 26, 2009
-    President of Epitech.
-
-    Flavien Astraud, November 26, 2009
-    Head of the EIP Laboratory.
-
  */
 
 package com.beem.project.beem.account;
--- a/src/com/beem/project/beem/account/SyncAdapterService.java	Sat Jul 23 01:28:07 2011 +0200
+++ b/src/com/beem/project/beem/account/SyncAdapterService.java	Fri Aug 12 11:13:15 2011 +0200
@@ -25,61 +25,23 @@
 
     Please send bug reports with examples or suggestions to
     contact@beem-project.com or http://dev.beem-project.com/
-
-    Epitech, hereby disclaims all copyright interest in the program "Beem"
-    written by Frederic-Charles Barthelery,
-               Jean-Manuel Da Silva,
-               Nikita Kozlov,
-               Philippe Lago,
-               Jean Baptiste Vergely,
-               Vincent Veronis.
-
-    Nicolas Sadirac, November 26, 2009
-    President of Epitech.
-
-    Flavien Astraud, November 26, 2009
-    Head of the EIP Laboratory.
-
  */
 
 package com.beem.project.beem.account;
 
-import java.io.IOException;
-import java.util.ArrayList;
-
-import org.jivesoftware.smack.Roster;
-import org.jivesoftware.smack.RosterEntry;
-import org.jivesoftware.smack.RosterGroup;
-import org.jivesoftware.smack.XMPPConnection;
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smack.packet.Presence;
-
 import android.accounts.Account;
 import android.accounts.OperationCanceledException;
 import android.app.Service;
 import android.content.ContentProviderClient;
-import android.content.ContentProviderOperation;
 import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.OperationApplicationException;
 import android.content.SyncResult;
-import android.database.Cursor;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.RemoteException;
-import android.provider.ContactsContract;
 import android.util.Log;
 
-import com.beem.project.beem.BeemConnection;
 import com.beem.project.beem.BeemIntent;
-import com.beem.project.beem.R;
-import com.beem.project.beem.service.BeemAvatarCache;
-import com.beem.project.beem.utils.Status;
 
 /**
  * Class to integrate beem in android's account.
--- a/src/com/beem/project/beem/ui/Login.java	Sat Jul 23 01:28:07 2011 +0200
+++ b/src/com/beem/project/beem/ui/Login.java	Fri Aug 12 11:13:15 2011 +0200
@@ -81,10 +81,10 @@
  */
 public class Login extends Activity {
 
-    private BroadcastReceiver mReceiver;    
     private BeemAccountList mAdapterAccountList;
     private List<String> mListAccount = new ArrayList<String>();
     private final BeemAccountListOnClick mOnAccountClick = new BeemAccountListOnClick();
+    private final BroadcastReceiver mOnBroadcastReceiver = new BeemBroadcastReceiver();
 
     /**
      * Constructor.
@@ -101,34 +101,6 @@
 	listView.setClickable(true);
 	listView.setOnItemClickListener(mOnAccountClick);
 	listView.setAdapter(mAdapterAccountList);
-
-	mReceiver = new BroadcastReceiver() {
-	    public void onReceive(Context ctx, Intent intent) {
-		String action = intent.getAction();
-		String account = intent.getExtras().getString(BeemIntent.EXTRA_ACCOUNT);
-		int hash = account.hashCode();
-		if (hash < 0 ) hash = hash - 2 * hash;
-		
-		View v = findViewById(hash);
-		TextView text = (TextView) v.findViewById(R.id.accountstatus);
-		ImageButton logo = (ImageButton) v.findViewById(R.id.loginanim_logo_anim);
-
-		if (BeemIntent.ACTION_CONNECTED.equals(action)) {
-		    if (text != null) text.setText(R.string.contact_status_msg_available);
-		    if (logo != null) {
-			logo.setImageResource(R.drawable.beem_launcher_icon_color);
-			logo.clearAnimation();			
-		    }
-		} else if (BeemIntent.ACTION_DISCONNECTED.equals(action)) {
-		    if (text != null) text.setText(R.string.contact_status_msg_offline);
-		    if (logo != null) {
-			logo.setImageResource(R.drawable.beem_launcher_icon_silver);
-			logo.clearAnimation();
-		    }
-		}
-	    }
-	};
-
     }
 
     @Override
@@ -228,8 +200,9 @@
 	    logo.setOnClickListener(new BeemConnectionOnClick(v));
 	    TextView name = (TextView) v.findViewById(R.id.accountname);
 	    name.setText(mListAccount.get(position));
-	    int hash  = mListAccount.get(position).hashCode();
-	    if (hash < 0 ) hash = hash - 2 * hash;
+	    int hash = mListAccount.get(position).hashCode();
+	    if (hash < 0)
+		hash = hash - 2 * hash;
 	    v.setId(hash);
 	    return v;
 	}
@@ -237,16 +210,18 @@
     }
 
     /**
-     * Event simple click on item of the bitton of account list.
+     * Event simple click on item of the button of account list.
      */
     private class BeemConnectionOnClick implements android.view.View.OnClickListener {
 	private View mView;
+
 	/**
 	 * Constructor.
 	 */
 	public BeemConnectionOnClick(View v) {
 	    mView = v;
 	}
+
 	@Override
 	public void onClick(View v) {
 	    //TODO: Check if already connected -> disconnect
@@ -261,7 +236,7 @@
 	    intent.putExtra(BeemIntent.EXTRA_ACCOUNT, accountName.getText());
 	    IntentFilter filter = new IntentFilter(BeemIntent.ACTION_CONNECTED);
 	    filter.addAction(BeemIntent.ACTION_DISCONNECTED);
-	    registerReceiver(mReceiver, filter);
+	    registerReceiver(mOnBroadcastReceiver, filter);
 	    startService(intent);
 	}
     }
@@ -282,9 +257,55 @@
 	@Override
 	public void onItemClick(AdapterView<?> arg0, View v, int pos, long lpos) {
 	    Intent i = new Intent(Login.this, ContactList.class);
-	    TextView accountName = (TextView)v.findViewById(R.id.accountname);
-	    i.putExtra(BeemIntent.EXTRA_ACCOUNT, accountName.getText());	    
+	    TextView accountName = (TextView) v.findViewById(R.id.accountname);
+	    i.putExtra(BeemIntent.EXTRA_ACCOUNT, accountName.getText());
 	    startActivity(i);
 	}
-    }   
+    }
+
+    /**
+     * Event receive from service.
+     */
+    private class BeemBroadcastReceiver extends BroadcastReceiver {
+
+	/**
+	 * Constructor.
+	 */
+	public BeemBroadcastReceiver() {
+
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void onReceive(Context context, Intent intent) {
+	    String action = intent.getAction();
+	    String account = intent.getExtras().getString(BeemIntent.EXTRA_ACCOUNT);
+	    int hash = account.hashCode();
+	    if (hash < 0)
+		hash = hash - 2 * hash;
+
+	    View v = findViewById(hash);
+	    TextView text = (TextView) v.findViewById(R.id.accountstatus);
+	    ImageButton logo = (ImageButton) v.findViewById(R.id.loginanim_logo_anim);
+
+	    if (BeemIntent.ACTION_CONNECTED.equals(action)) {
+		if (text != null)
+		    text.setText(R.string.contact_status_msg_available);
+		if (logo != null) {
+		    logo.setImageResource(R.drawable.beem_launcher_icon_color);
+		    logo.clearAnimation();
+		}
+	    } else if (BeemIntent.ACTION_DISCONNECTED.equals(action)) {
+		if (text != null)
+		    text.setText(R.string.contact_status_msg_offline);
+		if (logo != null) {
+		    logo.setImageResource(R.drawable.beem_launcher_icon_silver);
+		    logo.clearAnimation();
+		}
+	    }
+	}
+
+    }
 }