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 10:50:56 +00:00
parent 521cda35f5
commit 7209d634a5
7 changed files with 196 additions and 268 deletions

View File

@ -12,6 +12,7 @@ import android.accounts.AccountManager
import android.accounts.AccountManagerCallback import android.accounts.AccountManagerCallback
import android.accounts.AccountManagerFuture import android.accounts.AccountManagerFuture
import android.accounts.AuthenticatorException import android.accounts.AuthenticatorException
import android.annotation.TargetApi
import android.content.ContentProviderClient import android.content.ContentProviderClient
import android.content.ContentResolver import android.content.ContentResolver
import android.content.ContentUris import android.content.ContentUris
@ -47,8 +48,78 @@ import at.bitfire.vcard4android.CachedGroupMembership
import at.bitfire.vcard4android.ContactsStorageException import at.bitfire.vcard4android.ContactsStorageException
class LocalAddressBook(protected val context: Context, account: Account, provider: ContentProviderClient?) : AndroidAddressBook(account, provider, LocalGroup.Factory.INSTANCE, LocalContact.Factory.INSTANCE), LocalCollection<LocalResource> { class LocalAddressBook(
private val syncState = Bundle() private val context: Context,
account: Account,
provider: ContentProviderClient?
): AndroidAddressBook<LocalContact, LocalGroup>(account, provider, LocalContact.Factory, LocalGroup.Factory), LocalCollection<LocalAddress> {
companion object {
val USER_DATA_MAIN_ACCOUNT_TYPE = "real_account_type"
val USER_DATA_MAIN_ACCOUNT_NAME = "real_account_name"
val USER_DATA_URL = "url"
const val USER_DATA_READ_ONLY = "read_only"
fun create(context: Context, provider: ContentProviderClient, mainAccount: Account, journalEntity: JournalEntity): LocalAddressBook {
val info = journalEntity.info
val accountManager = AccountManager.get(context)
val account = Account(accountName(mainAccount, info), App.addressBookAccountType)
if (!accountManager.addAccountExplicitly(account, null, initialUserData(mainAccount, info.url.toString())))
throw ContactsStorageException("Couldn't create address book account")
val addressBook = LocalAddressBook(context, account, provider)
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true)
val values = ContentValues(2)
values.put(ContactsContract.Settings.SHOULD_SYNC, 1)
values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1)
addressBook.settings = values
return addressBook
}
fun find(context: Context, provider: ContentProviderClient?, mainAccount: Account?) = AccountManager.get(context)
.getAccountsByType(App.addressBookAccountType)
.map { LocalAddressBook(context, it, provider) }
.filter { mainAccount == null || it.mainAccount == mainAccount }
.toList()
fun findByUid(context: Context, provider: ContentProviderClient, mainAccount: Account?, uid: String): LocalAddressBook? {
val accountManager = AccountManager.get(context)
for (account in accountManager.getAccountsByType(App.addressBookAccountType)) {
val addressBook = LocalAddressBook(context, account, provider)
if (addressBook.url == uid && (mainAccount == null || addressBook.mainAccount == mainAccount))
return addressBook
}
return null
}
// HELPERS
fun accountName(mainAccount: Account, info: CollectionInfo): String {
val displayName = if (info.displayName != null) info.displayName else info.uid
val sb = StringBuilder(displayName)
sb.append(" (")
.append(mainAccount.name)
.append(" ")
.append(info.uid!!.substring(0, 4))
.append(")")
return sb.toString()
}
fun initialUserData(mainAccount: Account, url: String): Bundle {
val bundle = Bundle(3)
bundle.putString(USER_DATA_MAIN_ACCOUNT_NAME, mainAccount.name)
bundle.putString(USER_DATA_MAIN_ACCOUNT_TYPE, mainAccount.type)
bundle.putString(USER_DATA_URL, url)
return bundle
}
}
/** /**
* Whether contact groups (LocalGroup resources) are included in query results for * Whether contact groups (LocalGroup resources) are included in query results for
@ -57,100 +128,44 @@ class LocalAddressBook(protected val context: Context, account: Account, provide
*/ */
var includeGroups = true var includeGroups = true
/** private var _mainAccount: Account? = null
* Returns an array of local contacts/groups which have been deleted locally. (DELETED != 0).
*/
override val deleted: Array<LocalResource>
@Throws(ContactsStorageException::class)
get() {
val deleted = LinkedList<LocalResource>()
Collections.addAll(deleted, *deletedContacts)
if (includeGroups)
Collections.addAll(deleted, *deletedGroups)
return deleted.toTypedArray()
}
/**
* Returns an array of local contacts/groups which have been changed locally (DIRTY != 0).
*/
override val dirty: Array<LocalResource>
@Throws(ContactsStorageException::class)
get() {
val dirty = LinkedList<LocalResource>()
Collections.addAll(dirty, *dirtyContacts)
if (includeGroups)
Collections.addAll(dirty, *dirtyGroups)
return dirty.toTypedArray()
}
/**
* Returns an array of local contacts which don't have a file name yet.
*/
override val withoutFileName: Array<LocalResource>
@Throws(ContactsStorageException::class)
get() {
val nameless = LinkedList<LocalResource>()
Collections.addAll(nameless, *queryContacts(AndroidContact.COLUMN_FILENAME + " IS NULL", null) as Array<LocalContact>)
if (includeGroups)
Collections.addAll(nameless, *queryGroups(AndroidGroup.COLUMN_FILENAME + " IS NULL", null) as Array<LocalGroup>)
return nameless.toTypedArray()
}
val deletedContacts: Array<LocalContact>
@Throws(ContactsStorageException::class)
get() = queryContacts(RawContacts.DELETED + "!= 0", null) as Array<LocalContact>
val dirtyContacts: Array<LocalContact>
@Throws(ContactsStorageException::class)
get() = queryContacts(RawContacts.DIRTY + "!= 0 AND " + RawContacts.DELETED + "== 0", null) as Array<LocalContact>
val all: Array<LocalContact>
@Throws(ContactsStorageException::class)
get() = queryContacts(RawContacts.DELETED + "== 0", null) as Array<LocalContact>
val deletedGroups: Array<LocalGroup>
@Throws(ContactsStorageException::class)
get() = queryGroups(Groups.DELETED + "!= 0", null) as Array<LocalGroup>
val dirtyGroups: Array<LocalGroup>
@Throws(ContactsStorageException::class)
get() = queryGroups(Groups.DIRTY + "!= 0 AND " + Groups.DELETED + "== 0", null) as Array<LocalGroup>
var mainAccount: Account var mainAccount: Account
@Throws(ContactsStorageException::class)
get() { get() {
val accountManager = AccountManager.get(context) _mainAccount?.let { return it }
val name = accountManager.getUserData(account, USER_DATA_MAIN_ACCOUNT_NAME)
val type = accountManager.getUserData(account, USER_DATA_MAIN_ACCOUNT_TYPE) AccountManager.get(context).let { accountManager ->
return if (name != null && type != null) val name = accountManager.getUserData(account, USER_DATA_MAIN_ACCOUNT_NAME)
Account(name, type) val type = accountManager.getUserData(account, USER_DATA_MAIN_ACCOUNT_TYPE)
else if (name != null && type != null)
throw ContactsStorageException("Address book doesn't exist anymore") return Account(name, type)
else
throw IllegalStateException("Address book doesn't exist anymore")
}
} }
@Throws(ContactsStorageException::class) set(newMainAccount) {
set(mainAccount) { AccountManager.get(context).let { accountManager ->
val accountManager = AccountManager.get(context) accountManager.setUserData(account, USER_DATA_MAIN_ACCOUNT_NAME, newMainAccount.name)
accountManager.setUserData(account, USER_DATA_MAIN_ACCOUNT_NAME, mainAccount.name) accountManager.setUserData(account, USER_DATA_MAIN_ACCOUNT_TYPE, newMainAccount.type)
accountManager.setUserData(account, USER_DATA_MAIN_ACCOUNT_TYPE, mainAccount.type) }
_mainAccount = newMainAccount
} }
var url: String? var url: String
@Throws(ContactsStorageException::class) get() = AccountManager.get(context).getUserData(account, USER_DATA_URL)
get() { ?: throw IllegalStateException("Address book has no URL")
val accountManager = AccountManager.get(context) set(url) = AccountManager.get(context).setUserData(account, USER_DATA_URL, url)
return accountManager.getUserData(account, USER_DATA_URL)
} var readOnly: Boolean
@Throws(ContactsStorageException::class) get() = AccountManager.get(context).getUserData(account, USER_DATA_READ_ONLY) != null
set(url) { set(readOnly) = AccountManager.get(context).setUserData(account, USER_DATA_READ_ONLY, if (readOnly) "1" else null)
val accountManager = AccountManager.get(context)
accountManager.setUserData(account, USER_DATA_URL, url)
}
@Throws(AuthenticatorException::class, OperationCanceledException::class, IOException::class, ContactsStorageException::class, android.accounts.OperationCanceledException::class)
fun update(journalEntity: JournalEntity) { fun update(journalEntity: JournalEntity) {
val info = journalEntity.info val info = journalEntity.info
val newAccountName = accountName(mainAccount, info) val newAccountName = accountName(mainAccount, info)
if (account.name != newAccountName && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
if (account.name != newAccountName && Build.VERSION.SDK_INT >= 21) {
val accountManager = AccountManager.get(context) val accountManager = AccountManager.get(context)
val future = accountManager.renameAccount(account, newAccountName, { val future = accountManager.renameAccount(account, newAccountName, {
try { try {
@ -168,22 +183,61 @@ class LocalAddressBook(protected val context: Context, account: Account, provide
account = future.result account = future.result
} }
App.log.info("Address book write permission? = ${journalEntity.isReadOnly}")
readOnly = journalEntity.isReadOnly
// make sure it will still be synchronized when contacts are updated // make sure it will still be synchronized when contacts are updated
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true) ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true)
} }
fun delete() { fun delete() {
val accountManager = AccountManager.get(context) val accountManager = AccountManager.get(context)
AndroidCompat.removeAccount(accountManager, account) @Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= 22)
accountManager.removeAccount(account, null, null, null)
else
accountManager.removeAccount(account, null, null)
} }
@Throws(ContactsStorageException::class, FileNotFoundException::class) fun findAll(): List<LocalAddress> = queryContacts(RawContacts.DELETED + "== 0", null)
fun findContactByUID(uid: String): LocalContact {
val contacts = queryContacts(LocalContact.COLUMN_UID + "=?", arrayOf(uid)) as Array<LocalContact> /**
if (contacts.size == 0) * Returns an array of local contacts/groups which have been deleted locally. (DELETED != 0).
throw FileNotFoundException() * @throws RemoteException on content provider errors
return contacts[0] */
} override fun findDeleted() =
if (includeGroups)
findDeletedContacts() + findDeletedGroups()
else
findDeletedContacts()
fun findDeletedContacts() = queryContacts("${RawContacts.DELETED}!=0", null)
fun findDeletedGroups() = queryGroups("${Groups.DELETED}!=0", null)
/**
* Returns an array of local contacts/groups which have been changed locally (DIRTY != 0).
* @throws RemoteException on content provider errors
*/
override fun findDirty() =
if (includeGroups)
findDirtyContacts() + findDirtyGroups()
else
findDirtyContacts()
fun findDirtyContacts() = queryContacts("${RawContacts.DIRTY}!=0", null)
fun findDirtyGroups() = queryGroups("${Groups.DIRTY}!=0", null)
/**
* Returns an array of local contacts which don't have a file name yet.
*/
override fun findWithoutFileName() =
if (includeGroups)
findWithoutFileNameContacts() + findWithoutFileNameGroups()
else
findWithoutFileNameContacts()
fun findWithoutFileNameContacts() = queryContacts("${AndroidContact.COLUMN_FILENAME} IS NULL", null)
fun findWithoutFileNameGroups() = queryGroups("${AndroidGroup.COLUMN_FILENAME} IS NULL", null)
/** /**
* Queries all contacts with DIRTY flag and checks whether their data checksum has changed, i.e. * Queries all contacts with DIRTY flag and checks whether their data checksum has changed, i.e.
@ -192,52 +246,39 @@ class LocalAddressBook(protected val context: Context, account: Account, provide
* whose contact data checksum has not changed. * whose contact data checksum has not changed.
* @return number of "really dirty" contacts * @return number of "really dirty" contacts
*/ */
@Throws(ContactsStorageException::class)
fun verifyDirty(): Int { fun verifyDirty(): Int {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
App.log.severe("verifyDirty() should not be called on Android <7") throw IllegalStateException("verifyDirty() should not be called on Android != 7")
var reallyDirty = 0 var reallyDirty = 0
for (contact in dirtyContacts) { for (contact in findDirtyContacts()) {
try { val lastHash = contact.getLastHashCode()
val lastHash = contact.lastHashCode val currentHash = contact.dataHashCode()
val currentHash = contact.dataHashCode() if (lastHash == currentHash) {
if (lastHash == currentHash) { // hash is code still the same, contact is not "really dirty" (only metadata been have changed)
// hash is code still the same, contact is not "really dirty" (only metadata been have changed) App.log.log(Level.FINE, "Contact data hash has not changed, resetting dirty flag", contact)
App.log.log(Level.FINE, "Contact data hash has not changed, resetting dirty flag", contact) contact.resetDirty()
contact.resetDirty() } else {
} else { App.log.log(Level.FINE, "Contact data has changed from hash $lastHash to $currentHash", contact)
App.log.log(Level.FINE, "Contact data has changed from hash $lastHash to $currentHash", contact) reallyDirty++
reallyDirty++
}
} catch (e: FileNotFoundException) {
throw ContactsStorageException("Couldn't calculate hash code", e)
} }
} }
if (includeGroups) if (includeGroups)
reallyDirty += dirtyGroups.size reallyDirty += findDirtyGroups().size
return reallyDirty return reallyDirty
} }
@Throws(ContactsStorageException::class) override fun findByUid(uid: String): LocalAddress? = findContactByUID(uid)
override fun getByUid(uid: String): LocalResource? {
val ret = queryContacts(AndroidContact.COLUMN_FILENAME + " =? ", arrayOf(uid)) as Array<LocalContact>
return if (ret != null && ret.size > 0) {
ret[0]
} else null
}
@Throws(ContactsStorageException::class)
override fun count(): Long { override fun count(): Long {
try { try {
val cursor = provider.query(syncAdapterURI(RawContacts.CONTENT_URI), null, null, null, null) val cursor = provider?.query(syncAdapterURI(RawContacts.CONTENT_URI), null, null, null, null)
try { try {
return cursor.count.toLong() return cursor?.count.toLong()
} finally { } finally {
cursor.close() cursor?.close()
} }
} catch (e: RemoteException) { } catch (e: RemoteException) {
throw ContactsStorageException("Couldn't query contacts", e) throw ContactsStorageException("Couldn't query contacts", e)
@ -245,7 +286,6 @@ class LocalAddressBook(protected val context: Context, account: Account, provide
} }
@Throws(ContactsStorageException::class)
internal fun getByGroupMembership(groupID: Long): Array<LocalContact> { internal fun getByGroupMembership(groupID: Long): Array<LocalContact> {
try { try {
val cursor = provider.query(syncAdapterURI(ContactsContract.Data.CONTENT_URI), val cursor = provider.query(syncAdapterURI(ContactsContract.Data.CONTENT_URI),
@ -271,11 +311,10 @@ class LocalAddressBook(protected val context: Context, account: Account, provide
} }
@Throws(ContactsStorageException::class)
fun deleteAll() { fun deleteAll() {
try { try {
provider.delete(syncAdapterURI(RawContacts.CONTENT_URI), null, null) provider?.delete(syncAdapterURI(RawContacts.CONTENT_URI), null, null)
provider.delete(syncAdapterURI(Groups.CONTENT_URI), null, null) provider?.delete(syncAdapterURI(Groups.CONTENT_URI), null, null)
} catch (e: RemoteException) { } catch (e: RemoteException) {
throw ContactsStorageException("Couldn't delete all local contacts and groups", e) throw ContactsStorageException("Couldn't delete all local contacts and groups", e)
} }
@ -283,57 +322,38 @@ class LocalAddressBook(protected val context: Context, account: Account, provide
} }
/* special group operations */
/** /**
* Finds the first group with the given title. If there is no group with this * Finds the first group with the given title. If there is no group with this
* title, a new group is created. * title, a new group is created.
* @param title title of the group to look for * @param title title of the group to look for
* @return id of the group with given title * @return id of the group with given title
* @throws ContactsStorageException on contact provider errors * @throws RemoteException on content provider errors
*/ */
@Throws(ContactsStorageException::class)
fun findOrCreateGroup(title: String): Long { fun findOrCreateGroup(title: String): Long {
try { provider!!.query(syncAdapterURI(Groups.CONTENT_URI), arrayOf(Groups._ID),
val cursor = provider.query(syncAdapterURI(Groups.CONTENT_URI), "${Groups.TITLE}=?", arrayOf(title), null)?.use { cursor ->
arrayOf(Groups._ID), if (cursor.moveToNext())
Groups.TITLE + "=?", arrayOf(title), null) return cursor.getLong(0)
try {
if (cursor != null && cursor.moveToNext())
return cursor.getLong(0)
} finally {
cursor!!.close()
}
val values = ContentValues()
values.put(Groups.TITLE, title)
val uri = provider.insert(syncAdapterURI(Groups.CONTENT_URI), values)
return ContentUris.parseId(uri)
} catch (e: RemoteException) {
throw ContactsStorageException("Couldn't find local contact group", e)
} }
val values = ContentValues(1)
values.put(Groups.TITLE, title)
val uri = provider.insert(syncAdapterURI(Groups.CONTENT_URI), values)
return ContentUris.parseId(uri)
} }
@Throws(ContactsStorageException::class)
fun removeEmptyGroups() { fun removeEmptyGroups() {
// find groups without members // find groups without members
/** should be done using [Groups.SUMMARY_COUNT], but it's not implemented in Android yet */ /** should be done using {@link Groups.SUMMARY_COUNT}, but it's not implemented in Android yet */
for (group in queryGroups(null, null) as Array<LocalGroup>) queryGroups(null, null).filter { it.getMembers().isEmpty() }.forEach { group ->
if (group.members.size == 0) { App.log.log(Level.FINE, "Deleting group", group)
App.log.log(Level.FINE, "Deleting group", group) group.delete()
group.delete()
}
}
@Throws(ContactsStorageException::class)
fun removeGroups() {
try {
provider.delete(syncAdapterURI(Groups.CONTENT_URI), null, null)
} catch (e: RemoteException) {
throw ContactsStorageException("Couldn't remove all groups", e)
} }
} }
/** Fix all of the etags of all of the non-dirty contacts to be non-null. /** Fix all of the etags of all of the non-dirty contacts to be non-null.
* Currently set to all ones. */ * Currently set to all ones. */
@Throws(ContactsStorageException::class) @Throws(ContactsStorageException::class)
@ -352,81 +372,4 @@ class LocalAddressBook(protected val context: Context, account: Account, provide
} }
} }
companion object {
protected val USER_DATA_MAIN_ACCOUNT_TYPE = "real_account_type"
protected val USER_DATA_MAIN_ACCOUNT_NAME = "real_account_name"
protected val USER_DATA_URL = "url"
@Throws(ContactsStorageException::class)
fun find(context: Context, provider: ContentProviderClient, mainAccount: Account?): Array<LocalAddressBook> {
val accountManager = AccountManager.get(context)
val result = LinkedList<LocalAddressBook>()
for (account in accountManager.getAccountsByType(App.addressBookAccountType)) {
val addressBook = LocalAddressBook(context, account, provider)
if (mainAccount == null || addressBook.mainAccount == mainAccount)
result.add(addressBook)
}
return result.toTypedArray()
}
@Throws(ContactsStorageException::class)
fun findByUid(context: Context, provider: ContentProviderClient, mainAccount: Account?, uid: String): LocalAddressBook? {
val accountManager = AccountManager.get(context)
for (account in accountManager.getAccountsByType(App.addressBookAccountType)) {
val addressBook = LocalAddressBook(context, account, provider)
if (addressBook.url == uid && (mainAccount == null || addressBook.mainAccount == mainAccount))
return addressBook
}
return null
}
@Throws(ContactsStorageException::class)
fun create(context: Context, provider: ContentProviderClient, mainAccount: Account, journalEntity: JournalEntity): LocalAddressBook {
val info = journalEntity.info
val accountManager = AccountManager.get(context)
val account = Account(accountName(mainAccount, info), App.addressBookAccountType)
if (!accountManager.addAccountExplicitly(account, null, null))
throw ContactsStorageException("Couldn't create address book account")
setUserData(accountManager, account, mainAccount, info.uid!!)
val addressBook = LocalAddressBook(context, account, provider)
addressBook.mainAccount = mainAccount
addressBook.url = info.uid
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true)
return addressBook
}
// SETTINGS
// XXX: Workaround a bug in Android where passing a bundle to addAccountExplicitly doesn't work.
fun setUserData(accountManager: AccountManager, account: Account, mainAccount: Account, url: String) {
accountManager.setUserData(account, USER_DATA_MAIN_ACCOUNT_NAME, mainAccount.name)
accountManager.setUserData(account, USER_DATA_MAIN_ACCOUNT_TYPE, mainAccount.type)
accountManager.setUserData(account, USER_DATA_URL, url)
}
// HELPERS
fun accountName(mainAccount: Account, info: CollectionInfo): String {
val displayName = if (info.displayName != null) info.displayName else info.uid
val sb = StringBuilder(displayName)
sb.append(" (")
.append(mainAccount.name)
.append(" ")
.append(info.uid!!.substring(0, 4))
.append(")")
return sb.toString()
}
}
} }

View File

@ -81,7 +81,7 @@ class LocalCalendar protected constructor(account: Account, provider: ContentPro
} }
@Throws(CalendarStorageException::class) @Throws(CalendarStorageException::class)
override fun getByUid(uid: String): LocalEvent? { override fun findByUid(uid: String): LocalEvent? {
val ret = queryEvents(Events._SYNC_ID + " =? ", arrayOf(uid)) as Array<LocalEvent> val ret = queryEvents(Events._SYNC_ID + " =? ", arrayOf(uid)) as Array<LocalEvent>
return if (ret != null && ret.size > 0) { return if (ret != null && ret.size > 0) {
ret[0] ret[0]

View File

@ -8,21 +8,13 @@
package com.etesync.syncadapter.resource package com.etesync.syncadapter.resource
import java.io.FileNotFoundException interface LocalCollection<out T: LocalResource<*>> {
fun findDeleted(): List<T>
fun findDirty(): List<T>
fun findWithoutFileName(): List<T>
import at.bitfire.ical4android.CalendarStorageException fun findByUid(uid: String): T?
import at.bitfire.vcard4android.ContactsStorageException
interface LocalCollection<T> {
val deleted: Array<T>
val withoutFileName: Array<T>
/** Dirty *non-deleted* entries */
val dirty: Array<T>
@Throws(CalendarStorageException::class, ContactsStorageException::class)
fun getByUid(uid: String): T?
@Throws(CalendarStorageException::class, ContactsStorageException::class)
fun count(): Long fun count(): Long
} }

View File

@ -199,7 +199,7 @@ class LocalGroup : AndroidGroup, LocalAddress {
* Marks all members of the current group as dirty. * Marks all members of the current group as dirty.
*/ */
fun markMembersDirty() { fun markMembersDirty() {
] val batch = BatchOperation(addressBook.provider!!) val batch = BatchOperation(addressBook.provider!!)
for (member in getMembers()) for (member in getMembers())
batch.enqueue(BatchOperation.Operation( batch.enqueue(BatchOperation.Operation(

View File

@ -65,7 +65,7 @@ class LocalTaskList protected constructor(account: Account, provider: TaskProvid
} }
@Throws(CalendarStorageException::class) @Throws(CalendarStorageException::class)
override fun getByUid(uid: String): LocalTask? { override fun findByUid(uid: String): LocalTask? {
val ret = queryTasks(Tasks._SYNC_ID + " =? ", arrayOf(uid)) as Array<LocalTask> val ret = queryTasks(Tasks._SYNC_ID + " =? ", arrayOf(uid)) as Array<LocalTask>
return if (ret != null && ret.size > 0) { return if (ret != null && ret.size > 0) {
ret[0] ret[0]

View File

@ -38,12 +38,9 @@ import org.apache.commons.codec.Charsets
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.io.InputStream
import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.ArrayList import java.util.ArrayList
import java.util.Calendar import java.util.Calendar
import java.util.Date
import java.util.Locale import java.util.Locale
import java.util.TimeZone import java.util.TimeZone
@ -112,7 +109,7 @@ constructor(context: Context, account: Account, settings: AccountSettings, extra
} }
val event = events[0] val event = events[0]
val local = localCollection!!.getByUid(event.uid) as LocalEvent? val local = localCollection!!.findByUid(event.uid) as LocalEvent?
if (cEntry.isAction(SyncEntry.Actions.ADD) || cEntry.isAction(SyncEntry.Actions.CHANGE)) { if (cEntry.isAction(SyncEntry.Actions.ADD) || cEntry.isAction(SyncEntry.Actions.CHANGE)) {
processEvent(event, local) processEvent(event, local)

View File

@ -41,7 +41,6 @@ import org.apache.commons.io.IOUtils
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.IOException import java.io.IOException
import java.io.InputStream
import java.util.logging.Level import java.util.logging.Level
import at.bitfire.ical4android.CalendarStorageException import at.bitfire.ical4android.CalendarStorageException
@ -49,10 +48,7 @@ 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 okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody
/** /**
* *
@ -163,7 +159,7 @@ 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!!.getByUid(contact.uid) as LocalResource? val local = localCollection!!.findByUid(contact.uid) as LocalResource?
if (cEntry.isAction(SyncEntry.Actions.ADD) || cEntry.isAction(SyncEntry.Actions.CHANGE)) { if (cEntry.isAction(SyncEntry.Actions.ADD) || cEntry.isAction(SyncEntry.Actions.CHANGE)) {