1
0
mirror of https://github.com/etesync/android synced 2024-11-22 07:58:09 +00:00
This commit is contained in:
Tom Hacohen 2019-01-06 12:54:04 +00:00
parent b90d2714a9
commit 467701047f
4 changed files with 23 additions and 38 deletions

View File

@ -133,7 +133,7 @@ class LocalGroup : AndroidGroup, LocalAddress {
constructor(addressBook: AndroidAddressBook<out AndroidContact, LocalGroup>, values: ContentValues) constructor(addressBook: AndroidAddressBook<out AndroidContact, LocalGroup>, values: ContentValues)
: super(addressBook, values) {} : super(addressBook, values) {}
constructor(addressBook: AndroidAddressBook<out AndroidContact, LocalGroup>, contact: Contact, fileName: String?, eTag: String?, flags: Int) constructor(addressBook: AndroidAddressBook<out AndroidContact, LocalGroup>, contact: Contact, fileName: String?, eTag: String?)
: super(addressBook, contact, fileName, eTag) {} : super(addressBook, contact, fileName, eTag) {}
override fun contentValues(): ContentValues { override fun contentValues(): ContentValues {

View File

@ -227,7 +227,7 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
val startDate = event.dtStart?.date val startDate = event.dtStart?.date
val endDate = event.getEndDate(true)!!.date val endDate = event.getEndDate(true)!!.date
val tzName = timezone.getDisplayName(timezone?.inDaylightTime(startDate)!!, TimeZone.SHORT) val tzName = timezone?.getDisplayName(timezone?.inDaylightTime(startDate)!!, TimeZone.SHORT)
val cal1 = Calendar.getInstance() val cal1 = Calendar.getInstance()
val cal2 = Calendar.getInstance() val cal2 = Calendar.getInstance()

View File

@ -17,6 +17,7 @@ import android.content.SyncResult
import android.database.sqlite.SQLiteException import android.database.sqlite.SQLiteException
import android.os.Bundle import android.os.Bundle
import android.provider.CalendarContract import android.provider.CalendarContract
import at.bitfire.ical4android.AndroidCalendar
import com.etesync.syncadapter.AccountSettings import com.etesync.syncadapter.AccountSettings
import com.etesync.syncadapter.App import com.etesync.syncadapter.App
@ -67,7 +68,7 @@ class CalendarsSyncAdapterService : SyncAdapterService() {
val principal = HttpUrl.get(settings.uri!!)!! val principal = HttpUrl.get(settings.uri!!)!!
for (calendar in LocalCalendar.find(account, provider, LocalCalendar.Factory.INSTANCE, CalendarContract.Calendars.SYNC_EVENTS + "!=0", null) as Array<LocalCalendar>) { for (calendar in AndroidCalendar.find(account, provider, LocalCalendar.Factory, CalendarContract.Calendars.SYNC_EVENTS + "!=0", null) as Array<LocalCalendar>) {
App.log.info("Synchronizing calendar #" + calendar.id + ", URL: " + calendar.name) App.log.info("Synchronizing calendar #" + calendar.id + ", URL: " + calendar.name)
val syncManager = CalendarSyncManager(context, account, settings, extras, authority, syncResult, calendar, principal) val syncManager = CalendarSyncManager(context, account, settings, extras, authority, syncResult, calendar, principal)
syncManager.performSync() syncManager.performSync()
@ -95,10 +96,6 @@ class CalendarsSyncAdapterService : SyncAdapterService() {
notificationManager.notify(title, context.getString(syncPhase)) notificationManager.notify(title, context.getString(syncPhase))
} catch (e: OutOfMemoryError) { } catch (e: OutOfMemoryError) {
if (e is CalendarStorageException || e is SQLiteException) {
App.log.log(Level.SEVERE, "Couldn't prepare local calendars", e)
syncResult.databaseError = true
}
val syncPhase = R.string.sync_phase_journals val syncPhase = R.string.sync_phase_journals
val title = context.getString(R.string.sync_error_calendar, account.name) val title = context.getString(R.string.sync_error_calendar, account.name)
notificationManager.setThrowable(e) notificationManager.setThrowable(e)
@ -121,7 +118,7 @@ class CalendarsSyncAdapterService : SyncAdapterService() {
remote[journalEntity.uid] = journalEntity remote[journalEntity.uid] = journalEntity
} }
val local = LocalCalendar.find(account, provider, LocalCalendar.Factory.INSTANCE, null, null) as Array<LocalCalendar> val local = AndroidCalendar.find(account, provider, LocalCalendar.Factory, null, null) as Array<LocalCalendar>
val updateColors = settings.manageCalendarColors val updateColors = settings.manageCalendarColors

View File

@ -29,14 +29,9 @@ import com.etesync.syncadapter.journalmanager.Exceptions
import com.etesync.syncadapter.journalmanager.JournalEntryManager import com.etesync.syncadapter.journalmanager.JournalEntryManager
import com.etesync.syncadapter.model.CollectionInfo import com.etesync.syncadapter.model.CollectionInfo
import com.etesync.syncadapter.model.SyncEntry import com.etesync.syncadapter.model.SyncEntry
import com.etesync.syncadapter.resource.LocalAddressBook
import com.etesync.syncadapter.resource.LocalContact
import com.etesync.syncadapter.resource.LocalGroup
import com.etesync.syncadapter.resource.LocalResource
import org.apache.commons.codec.Charsets import org.apache.commons.codec.Charsets
import org.apache.commons.collections4.SetUtils import org.apache.commons.collections4.SetUtils
import org.apache.commons.io.IOUtils
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.FileNotFoundException import java.io.FileNotFoundException
@ -47,15 +42,17 @@ import at.bitfire.ical4android.CalendarStorageException
import at.bitfire.vcard4android.BatchOperation import at.bitfire.vcard4android.BatchOperation
import at.bitfire.vcard4android.Contact import at.bitfire.vcard4android.Contact
import at.bitfire.vcard4android.ContactsStorageException import at.bitfire.vcard4android.ContactsStorageException
import com.etesync.syncadapter.resource.*
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.Request import okhttp3.Request
import java.io.StringReader
/** /**
* *
* Synchronization manager for CardDAV collections; handles contacts and groups. * Synchronization manager for CardDAV collections; handles contacts and groups.
*/ */
class ContactsSyncManager @Throws(Exceptions.IntegrityException::class, Exceptions.GenericCryptoException::class, ContactsStorageException::class) class ContactsSyncManager @Throws(Exceptions.IntegrityException::class, Exceptions.GenericCryptoException::class, ContactsStorageException::class)
constructor(context: Context, account: Account, settings: AccountSettings, extras: Bundle, authority: String, private val provider: ContentProviderClient, result: SyncResult, localAddressBook: LocalAddressBook, private val remote: HttpUrl) : SyncManager(context, account, settings, extras, authority, result, localAddressBook.url!!, CollectionInfo.Type.ADDRESS_BOOK, localAddressBook.mainAccount.name) { constructor(context: Context, account: Account, settings: AccountSettings, extras: Bundle, authority: String, private val provider: ContentProviderClient, result: SyncResult, localAddressBook: LocalAddressBook, private val remote: HttpUrl) : SyncManager<LocalAddress>(context, account, settings, extras, authority, result, localAddressBook.url!!, CollectionInfo.Type.ADDRESS_BOOK, localAddressBook.mainAccount.name) {
protected override val syncErrorTitle: String protected override val syncErrorTitle: String
get() = context.getString(R.string.sync_error_contacts, account.name) get() = context.getString(R.string.sync_error_contacts, account.name)
@ -81,7 +78,7 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// workaround for Android 7 which sets DIRTY flag when only meta-data is changed // workaround for Android 7 which sets DIRTY flag when only meta-data is changed
val reallyDirty = localAddressBook.verifyDirty() val reallyDirty = localAddressBook.verifyDirty()
val deleted = localAddressBook.deleted.size val deleted = localAddressBook.findDeleted().size
if (extras.containsKey(ContentResolver.SYNC_EXTRAS_UPLOAD) && reallyDirty == 0 && deleted == 0) { if (extras.containsKey(ContentResolver.SYNC_EXTRAS_UPLOAD) && reallyDirty == 0 && deleted == 0) {
App.log.info("This sync was called to up-sync dirty/deleted contacts, but no contacts have been changed") App.log.info("This sync was called to up-sync dirty/deleted contacts, but no contacts have been changed")
return false return false
@ -92,7 +89,7 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
val values = ContentValues(2) val values = ContentValues(2)
values.put(ContactsContract.Settings.SHOULD_SYNC, 1) values.put(ContactsContract.Settings.SHOULD_SYNC, 1)
values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1) values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1)
localAddressBook.updateSettings(values) localAddressBook.settings.putAll(values)
journal = JournalEntryManager(httpClient, remote, localAddressBook.url!!) journal = JournalEntryManager(httpClient, remote, localAddressBook.url!!)
@ -110,8 +107,8 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
/* groups as separate VCards: there are group contacts and individual contacts */ /* groups as separate VCards: there are group contacts and individual contacts */
// mark groups with changed members as dirty // mark groups with changed members as dirty
val batch = BatchOperation(addressBook.provider) val batch = BatchOperation(addressBook.provider!!)
for (contact in addressBook.dirtyContacts) { for (contact in addressBook.findDirtyContacts()) {
try { try {
App.log.fine("Looking for changed group memberships of contact " + contact.fileName) App.log.fine("Looking for changed group memberships of contact " + contact.fileName)
val cachedGroups = contact.cachedGroupMemberships val cachedGroups = contact.cachedGroupMemberships
@ -148,10 +145,10 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
@Throws(IOException::class, ContactsStorageException::class, CalendarStorageException::class) @Throws(IOException::class, ContactsStorageException::class, CalendarStorageException::class)
override fun processSyncEntry(cEntry: SyncEntry) { override fun processSyncEntry(cEntry: SyncEntry) {
val `is` = ByteArrayInputStream(cEntry.content.toByteArray(Charsets.UTF_8)) val inputReader = StringReader(cEntry.content)
val downloader = ResourceDownloader(context) val downloader = ResourceDownloader(context)
val contacts = Contact.fromStream(`is`, Charsets.UTF_8, downloader) val contacts = Contact.fromReader(inputReader, downloader)
if (contacts.size == 0) { if (contacts.size == 0) {
App.log.warning("Received VCard without data, ignoring") App.log.warning("Received VCard without data, ignoring")
return return
@ -159,14 +156,13 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
App.log.warning("Received multiple VCards, using first one") App.log.warning("Received multiple VCards, using first one")
val contact = contacts[0] val contact = contacts[0]
val local = localCollection!!.findByUid(contact.uid) as LocalResource? val local = localCollection!!.findByUid(contact.uid!!)
if (cEntry.isAction(SyncEntry.Actions.ADD) || cEntry.isAction(SyncEntry.Actions.CHANGE)) { if (cEntry.isAction(SyncEntry.Actions.ADD) || cEntry.isAction(SyncEntry.Actions.CHANGE)) {
processContact(contact, local) processContact(contact, local)
} else { } else {
if (local != null) { if (local != null) {
App.log.info("Removing local record #" + local.id + " which has been deleted on the server") App.log.info("Removing local record which has been deleted on the server")
local.delete() local.delete()
} else { } else {
App.log.warning("Tried deleting a non-existent record: " + contact.uid) App.log.warning("Tried deleting a non-existent record: " + contact.uid)
@ -175,7 +171,7 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
} }
@Throws(IOException::class, ContactsStorageException::class) @Throws(IOException::class, ContactsStorageException::class)
private fun processContact(newData: Contact, local: LocalResource?): LocalResource { private fun processContact(newData: Contact, local: LocalAddress?): LocalAddress {
var local = local var local = local
val uuid = newData.uid val uuid = newData.uid
// update local contact, if it exists // update local contact, if it exists
@ -184,14 +180,14 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
if (local is LocalGroup && newData.group) { if (local is LocalGroup && newData.group) {
// update group // update group
val group = local as LocalGroup? val group: LocalGroup = local
group!!.eTag = uuid group!!.eTag = uuid
group.updateFromServer(newData) group.update(newData)
syncResult.stats.numUpdates++ syncResult.stats.numUpdates++
} else if (local is LocalContact && !newData.group) { } else if (local is LocalContact && !newData.group) {
// update contact // update contact
val contact = local as LocalContact? val contact: LocalContact = local
contact!!.eTag = uuid contact!!.eTag = uuid
contact.update(newData) contact.update(newData)
syncResult.stats.numUpdates++ syncResult.stats.numUpdates++
@ -212,13 +208,13 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
if (newData.group) { if (newData.group) {
App.log.log(Level.INFO, "Creating local group", newData.uid) App.log.log(Level.INFO, "Creating local group", newData.uid)
val group = LocalGroup(localAddressBook(), newData, uuid, uuid) val group = LocalGroup(localAddressBook(), newData, uuid, uuid)
group.create() group.add()
local = group local = group
} else { } else {
App.log.log(Level.INFO, "Creating local contact", newData.uid) App.log.log(Level.INFO, "Creating local contact", newData.uid)
val contact = LocalContact(localAddressBook(), newData, uuid, uuid) val contact = LocalContact(localAddressBook(), newData, uuid, uuid)
contact.create() contact.add()
local = contact local = contact
} }
@ -268,15 +264,7 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
val body = response.body() val body = response.body()
if (body != null) { if (body != null) {
val stream = body.byteStream() return body.bytes()
try {
if (response.isSuccessful && stream != null) {
return IOUtils.toByteArray(stream)
} else
App.log.severe("Couldn't download external resource")
} finally {
stream?.close()
}
} }
} catch (e: IOException) { } catch (e: IOException) {
App.log.log(Level.SEVERE, "Couldn't download external resource", e) App.log.log(Level.SEVERE, "Couldn't download external resource", e)