# HG changeset patch # User "Vincent Veronis" # Date 1302727904 -7200 # Node ID 4e23720db26d952888318f19053f77ff07ab9184 # Parent 5cf109742815939cafe5a6911d8bb881a47d7f05 Finaly SyncAdapter works on Add and Update. diff -r 5cf109742815 -r 4e23720db26d src/com/beem/project/beem/account/SyncAdapterService.java --- a/src/com/beem/project/beem/account/SyncAdapterService.java Thu Mar 31 21:49:28 2011 +0200 +++ b/src/com/beem/project/beem/account/SyncAdapterService.java Wed Apr 13 22:51:44 2011 +0200 @@ -9,7 +9,6 @@ import org.jivesoftware.smack.RosterEntry; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.util.StringUtils; import android.accounts.Account; import android.accounts.OperationCanceledException; @@ -17,15 +16,18 @@ 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.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.provider.ContactsContract.Data; -import android.provider.ContactsContract.RawContacts; -import android.provider.ContactsContract.CommonDataKinds.Im; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.util.Log; @@ -72,56 +74,94 @@ BeemConnection beemco = new BeemConnection(mContext.getSharedPreferences(account.name, MODE_PRIVATE), null); beemco.setNoPresence(); XMPPConnection con = new XMPPConnection(beemco.getConnectionConfiguration()); + Roster roster = null; try { con.connect(); con.login(beemco.getLogin(), beemco.getPassword(), "BEEM_SYNC_ADAPTER"); + roster = con.getRoster(); - Roster roster = con.getRoster(); - if (roster != null) { - for (RosterEntry entry : roster.getEntries()) { - if (entry != null) { - addEntry(account, entry); - } - } - } - } catch (XMPPException e) { + } catch (XMPPException e) { Log.e(TAG, "Error while connecting with syncAdapter", e); + } catch (IllegalStateException e) { + Log.e(TAG, "Not connected to server", e); + } + if (roster != null) { + manageRoster(roster, account); } con.disconnect(); } - private static void addEntry(Account account, RosterEntry entry) { + private static void executeOperation(ArrayList ops) { + try { + mContentResolver.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); + } + } + + private static void manageRoster(final Roster r, final Account a) { ArrayList ops = new ArrayList(); - int rawContactInsertIndex = ops.size(); + for (RosterEntry entry : r.getEntries()) { + if (entry != null) { + manageEntry(ops, a, entry); + } + if (ops.size() > 100) + executeOperation(ops); + } + if (ops.size() > 0) + executeOperation(ops); + } - ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI); - builder.withValue(RawContacts.ACCOUNT_NAME, account.name); - builder.withValue(RawContacts.ACCOUNT_TYPE, account.type); - builder.withValue(RawContacts.SYNC1, entry.getUser()); - ops.add(builder.build()); + private static void manageEntry(ArrayList ops, Account account, RosterEntry entry) { - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex); - builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); - builder.withValue(StructuredName.DISPLAY_NAME, entry.getUser()); - ops.add(builder.build()); - - builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); - builder.withValueBackReference(Data.RAW_CONTACT_ID, 0); - builder.withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE); - builder.withValue(Im.DATA, entry.getUser()); - builder.withValue(Im.PROTOCOL, Im.PROTOCOL_JABBER); - ops.add(builder.build()); - - try { - mContentResolver.applyBatch(ContactsContract.AUTHORITY, ops); - Log.i(TAG, "added contact " + entry.getUser()); - } catch (Exception e) { - Log.d(TAG, "Error during add of contact", e); + long rawContactID = getRawContactID(account.name, entry.getUser()); + 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 = mContentResolver.insert(ContactsContract.RawContacts.CONTENT_URI, values); + rawContactID = ContentUris.parseId(rawContactUri); + values.clear(); + ContentProviderOperation.Builder builder = buildStructuredName(ContentProviderOperation + .newInsert(ContactsContract.Data.CONTENT_URI), entry, rawContactID); + ops.add(builder.build()); + } else { // Found, update + // if newUpdate instead of newInster ... fail update : all rows = 1 row + ContentProviderOperation.Builder builder = buildStructuredName(ContentProviderOperation + .newInsert(ContactsContract.Data.CONTENT_URI), entry, rawContactID); + ops.add(builder.build()); } } + private static ContentProviderOperation.Builder buildStructuredName(ContentProviderOperation.Builder builder, + RosterEntry entry, long rawContactID) { + String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); + builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); + builder.withValue(ContactsContract.Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); + builder.withValue(StructuredName.DISPLAY_NAME, displayName); + return builder; + } + + private static long getRawContactID(String account, String jid) { + long authorId = -1; + final Cursor c = mContentResolver.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; + } + }