diff --git a/app/build.gradle b/app/build.gradle index 401a6ea4..f5e66b50 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -138,6 +138,7 @@ dependencies { compile group: 'com.madgag.spongycastle', name: 'prov', version: '1.54.0.0' compile group: 'com.google.code.gson', name: 'gson', version: '1.7.2' compile 'com.squareup.okhttp3:logging-interceptor:3.8.0' + compile 'org.apache.commons:commons-collections4:4.1' provided 'org.projectlombok:lombok:1.16.16' // for tests diff --git a/app/src/main/java/com/etesync/syncadapter/resource/LocalGroup.java b/app/src/main/java/com/etesync/syncadapter/resource/LocalGroup.java index 5918ba00..5dd00b21 100644 --- a/app/src/main/java/com/etesync/syncadapter/resource/LocalGroup.java +++ b/app/src/main/java/com/etesync/syncadapter/resource/LocalGroup.java @@ -25,6 +25,7 @@ import com.etesync.syncadapter.App; import org.apache.commons.lang3.ArrayUtils; +import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashSet; @@ -41,10 +42,13 @@ import at.bitfire.vcard4android.BatchOperation; import at.bitfire.vcard4android.CachedGroupMembership; import at.bitfire.vcard4android.Contact; import at.bitfire.vcard4android.ContactsStorageException; +import ezvcard.VCardVersion; import lombok.Cleanup; import lombok.Getter; import lombok.ToString; +import static at.bitfire.vcard4android.GroupMethod.GROUP_VCARDS; + @ToString(callSuper=true) public class LocalGroup extends AndroidGroup implements LocalResource { @Getter @@ -62,7 +66,15 @@ public class LocalGroup extends AndroidGroup implements LocalResource { @Override public String getContent() throws IOException, ContactsStorageException { - return null; + final Contact contact; + contact = getContact(); + + App.log.log(Level.FINE, "Preparing upload of VCard " + getUuid(), contact); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + contact.write(VCardVersion.V4_0, GROUP_VCARDS, os); + + return os.toString(); } @Override @@ -107,7 +119,7 @@ public class LocalGroup extends AndroidGroup implements LocalResource { @Override public void prepareForUpload() throws ContactsStorageException { final String uid = UUID.randomUUID().toString(); - final String newFileName = uid + ".vcf"; + final String newFileName = uid; ContentValues values = new ContentValues(2); values.put(COLUMN_FILENAME, newFileName); diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/ContactsSyncManager.java b/app/src/main/java/com/etesync/syncadapter/syncadapter/ContactsSyncManager.java index 98b57c34..e49c36cf 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/ContactsSyncManager.java +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/ContactsSyncManager.java @@ -10,7 +10,9 @@ package com.etesync.syncadapter.syncadapter; import android.accounts.Account; 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.SyncResult; @@ -33,14 +35,18 @@ import com.etesync.syncadapter.resource.LocalGroup; import com.etesync.syncadapter.resource.LocalResource; import org.apache.commons.codec.Charsets; +import org.apache.commons.collections4.SetUtils; import org.apache.commons.io.IOUtils; import java.io.ByteArrayInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.Set; import java.util.logging.Level; import at.bitfire.ical4android.CalendarStorageException; +import at.bitfire.vcard4android.BatchOperation; import at.bitfire.vcard4android.Contact; import at.bitfire.vcard4android.ContactsStorageException; import lombok.Cleanup; @@ -100,6 +106,8 @@ public class ContactsSyncManager extends SyncManager { journal = new JournalEntryManager(httpClient, remote, localAddressBook.getURL()); + localAddressBook.includeGroups = true; + return true; } @@ -109,12 +117,27 @@ public class ContactsSyncManager extends SyncManager { LocalAddressBook addressBook = localAddressBook(); - /* groups as separate VCards: thtere are group contacts and individual contacts */ + /* groups as separate VCards: there are group contacts and individual contacts */ // mark groups with changed members as dirty - - // FIXME: add back - + BatchOperation batch = new BatchOperation(addressBook.provider); + for (LocalContact contact : addressBook.getDirtyContacts()) { + try { + App.log.fine("Looking for changed group memberships of contact " + contact.getFileName()); + Set cachedGroups = contact.getCachedGroupMemberships(), + currentGroups = contact.getGroupMemberships(); + for (Long groupID : SetUtils.disjunction(cachedGroups, currentGroups)) { + App.log.fine("Marking group as dirty: " + groupID); + batch.enqueue(new BatchOperation.Operation( + ContentProviderOperation.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(ContactsContract.Groups.CONTENT_URI, groupID))) + .withValue(ContactsContract.Groups.DIRTY, 1) + .withYieldAllowed(true) + )); + } + } catch (FileNotFoundException ignored) { + } + } + batch.commit(); } @Override