--- 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();
+ }
+ }
+ }
+
+ }
}