Commit d0e0b5d9 authored by Ricki Hirner's avatar Ricki Hirner

Raise API level, compatibility, make sync work again

* raise API level to 19 (required by ical4j)
* make HttpClient use Settings to get sync working again
* don't use vector graphics for notification icons (crashes on Android 4.x)
* various fixes and improvements
* library and build tools updates
parent b2475d2b
......@@ -12,7 +12,7 @@ apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 27
buildToolsVersion '27.0.0'
buildToolsVersion '27.0.1'
defaultConfig {
applicationId "at.bitfire.davdroid"
......@@ -21,9 +21,10 @@ android {
buildConfigField "long", "buildTime", System.currentTimeMillis() + "L"
buildConfigField "boolean", "customCerts", "true"
minSdkVersion 16
minSdkVersion 19 // Android 4.4
targetSdkVersion 25
// when using this, make sure that notification icons are real bitmaps
vectorDrawables.useSupportLibrary = true
}
......
......@@ -241,9 +241,9 @@ class DavService: Service() {
try {
Logger.log.info("Refreshing $serviceType collections of service #$service")
Settings.getInstance(this).use { settings ->
Settings.getInstance(this)?.use { settings ->
// create authenticating OkHttpClient (credentials taken from account settings)
HttpClient.Builder(this, settings, account)
HttpClient.Builder(this, settings, AccountSettings(this, settings, account))
.setForeground(true)
.build().use { client ->
val httpClient = client.okHttpClient
......@@ -366,13 +366,13 @@ class DavService: Service() {
debugIntent.putExtra(DebugInfoActivity.KEY_THROWABLE, e)
debugIntent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account)
val nm = NotificationManagerCompat.from(this@DavService)
val notify = NotificationCompat.Builder(this@DavService)
.setSmallIcon(R.drawable.ic_error_light)
.setLargeIcon(App.getLauncherBitmap(this@DavService))
val nm = NotificationManagerCompat.from(this)
val notify = NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_sync_error_notification)
.setLargeIcon(App.getLauncherBitmap(this))
.setContentTitle(getString(R.string.dav_service_refresh_failed))
.setContentText(getString(R.string.dav_service_refresh_couldnt_refresh))
.setContentIntent(PendingIntent.getActivity(this@DavService, 0, debugIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.setContentIntent(PendingIntent.getActivity(this, 0, debugIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.build()
nm.notify(Constants.NOTIFICATION_REFRESH_COLLECTIONS, notify)
} finally {
......
......@@ -8,7 +8,6 @@
package at.bitfire.davdroid;
import android.accounts.Account
import android.content.Context
import android.os.Build
import at.bitfire.cert4android.CustomCertManager
......@@ -16,7 +15,6 @@ import at.bitfire.dav4android.BasicDigestAuthHandler
import at.bitfire.dav4android.UrlUtils
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.settings.ISettings
import at.bitfire.davdroid.settings.Settings
import okhttp3.Cache
import okhttp3.Interceptor
import okhttp3.OkHttpClient
......@@ -44,7 +42,6 @@ class HttpClient private constructor(
class Builder @JvmOverloads constructor(
val context: Context? = null,
val settings: ISettings? = null,
account: Account? = null,
accountSettings: AccountSettings? = null,
logger: java.util.logging.Logger = Logger.log
) {
......@@ -97,7 +94,6 @@ class HttpClient private constructor(
customCertManager(CustomCertManager(context, BuildConfig.customCertsUI, !settings.getBoolean(App.DISTRUST_SYSTEM_CERTIFICATES, false)))
// use account settings for authentication
val accountSettings = accountSettings ?: account?.let { AccountSettings(context, settings, account) }
accountSettings?.let {
val userName = accountSettings.username()
val password = accountSettings.password()
......
......@@ -20,7 +20,9 @@ import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
class SSLSocketFactoryCompat(trustManager: X509TrustManager): SSLSocketFactory() {
class SSLSocketFactoryCompat(
trustManager: X509TrustManager
): SSLSocketFactory() {
private var delegate: SSLSocketFactory
......@@ -40,9 +42,8 @@ class SSLSocketFactoryCompat(trustManager: X509TrustManager): SSLSocketFactory()
cipherSuites = null
Logger.log.fine("Using device default TLS protocols/ciphers")
} else {
val socket = SSLSocketFactory.getDefault().createSocket() as SSLSocket?
try {
socket?.let {
(SSLSocketFactory.getDefault().createSocket() as? SSLSocket)?.use { socket ->
try {
/* set reasonable protocol versions */
// - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0)
// - remove all SSL versions (especially SSLv3) because they're insecure now
......@@ -53,7 +54,7 @@ class SSLSocketFactoryCompat(trustManager: X509TrustManager): SSLSocketFactory()
protocols = _protocols.toTypedArray()
/* set up reasonable cipher suites */
val knownCiphers = arrayOf<String>(
val knownCiphers = arrayOf<String>(
// TLS 1.2
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
......@@ -92,11 +93,9 @@ class SSLSocketFactoryCompat(trustManager: X509TrustManager): SSLSocketFactory()
Logger.log.info("Enabling (only) these TLS ciphers: " + _cipherSuites.joinToString(", "))
cipherSuites = _cipherSuites.toTypedArray()
} catch (e: IOException) {
Logger.log.severe("Couldn't determine default TLS settings")
}
} catch(e: IOException) {
Logger.log.severe("Couldn't determine default TLS settings")
} finally {
socket?.close() // doesn't implement Closeable on all supported Android versions
}
}
}
......
......@@ -66,7 +66,7 @@ object Logger {
// log to external file according to preferences
if (logToFile) {
val builder = NotificationCompat.Builder(context)
builder .setSmallIcon(R.drawable.ic_sd_storage_light)
builder .setSmallIcon(R.drawable.ic_sd_storage_notification)
.setLargeIcon(App.getLauncherBitmap(context))
.setContentTitle(context.getString(R.string.logging_davdroid_file_logging))
.setLocalOnly(true)
......
......@@ -10,7 +10,6 @@ package at.bitfire.davdroid.resource
import android.content.ContentProviderOperation
import android.content.ContentValues
import android.os.Build
import android.provider.CalendarContract
import android.provider.CalendarContract.Events
import at.bitfire.davdroid.BuildConfig
......@@ -27,7 +26,6 @@ class LocalEvent: AndroidEvent, LocalResource {
}
val COLUMN_ETAG = CalendarContract.Events.SYNC_DATA1
val COLUMN_UID = if (Build.VERSION.SDK_INT >= 17) Events.UID_2445 else Events.SYNC_DATA2
val COLUMN_SEQUENCE = CalendarContract.Events.SYNC_DATA3
}
......@@ -59,16 +57,11 @@ class LocalEvent: AndroidEvent, LocalResource {
fileName = row.getAsString(Events._SYNC_ID)
eTag = row.getAsString(COLUMN_ETAG)
event.uid = row.getAsString(COLUMN_UID)
event.uid = row.getAsString(Events.UID_2445)
event.sequence = row.getAsInteger(COLUMN_SEQUENCE)
if (Build.VERSION.SDK_INT >= 17) {
val isOrganizer = row.getAsInteger(Events.IS_ORGANIZER)
weAreOrganizer = isOrganizer != null && isOrganizer != 0
} else {
val organizer = row.getAsString(Events.ORGANIZER)
weAreOrganizer = organizer == null || organizer == calendar.account.name
}
val isOrganizer = row.getAsInteger(Events.IS_ORGANIZER)
weAreOrganizer = isOrganizer != null && isOrganizer != 0
}
@Throws(FileNotFoundException::class, CalendarStorageException::class)
......@@ -79,7 +72,7 @@ class LocalEvent: AndroidEvent, LocalResource {
val buildException = recurrence != null
val eventToBuild = recurrence ?: event
builder .withValue(COLUMN_UID, event.uid)
builder .withValue(Events.UID_2445, event.uid)
.withValue(COLUMN_SEQUENCE, eventToBuild.sequence)
.withValue(CalendarContract.Events.DIRTY, 0)
.withValue(CalendarContract.Events.DELETED, 0)
......@@ -98,7 +91,7 @@ class LocalEvent: AndroidEvent, LocalResource {
override fun prepareForUpload() {
try {
var uid: String? = null
calendar.provider.query(eventSyncURI(), arrayOf(COLUMN_UID), null, null, null)?.use { cursor ->
calendar.provider.query(eventSyncURI(), arrayOf(Events.UID_2445), null, null, null)?.use { cursor ->
if (cursor.moveToNext())
uid = cursor.getString(0)
}
......@@ -109,7 +102,7 @@ class LocalEvent: AndroidEvent, LocalResource {
val values = ContentValues(2)
values.put(Events._SYNC_ID, newFileName)
values.put(COLUMN_UID, uid)
values.put(Events.UID_2445, uid)
calendar.provider.update(eventSyncURI(), values, null, null)
fileName = newFileName
......@@ -126,7 +119,7 @@ class LocalEvent: AndroidEvent, LocalResource {
val values = ContentValues(2)
values.put(CalendarContract.Events.DIRTY, 0)
values.put(COLUMN_ETAG, eTag)
values.put(COLUMN_SEQUENCE, event!!.sequence);
values.put(COLUMN_SEQUENCE, event!!.sequence)
calendar.provider.update(eventSyncURI(), values, null, null)
this.eTag = eTag
......
......@@ -14,7 +14,6 @@ import android.content.Context
import android.content.SyncResult
import android.os.Bundle
import at.bitfire.dav4android.DavCalendar
import at.bitfire.dav4android.DavResource
import at.bitfire.dav4android.exception.DavException
import at.bitfire.dav4android.property.CalendarData
import at.bitfire.dav4android.property.GetCTag
......@@ -26,6 +25,7 @@ import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.resource.LocalCalendar
import at.bitfire.davdroid.resource.LocalEvent
import at.bitfire.davdroid.resource.LocalResource
import at.bitfire.davdroid.settings.ISettings
import at.bitfire.ical4android.Event
import at.bitfire.ical4android.InvalidCalendarException
import okhttp3.HttpUrl
......@@ -42,14 +42,15 @@ import java.util.logging.Level
*/
class CalendarSyncManager(
context: Context,
settings: ISettings,
account: Account,
settings: AccountSettings,
accountSettings: AccountSettings,
extras: Bundle,
authority: String,
syncResult: SyncResult,
val provider: ContentProviderClient,
val localCalendar: LocalCalendar
): SyncManager(context, account, settings, extras, authority, syncResult, "calendar/${localCalendar.id}") {
): SyncManager(context, settings, account, accountSettings, extras, authority, syncResult, "calendar/${localCalendar.id}") {
val MAX_MULTIGET = 20
......@@ -96,7 +97,7 @@ class CalendarSyncManager(
override fun listRemote() {
// calculate time range limits
var limitStart: Date? = null
settings.getTimeRangePastDays()?.let { pastDays ->
accountSettings.getTimeRangePastDays()?.let { pastDays ->
val calendar = Calendar.getInstance()
calendar.add(Calendar.DAY_OF_MONTH, -pastDays)
limitStart = calendar.time
......@@ -107,7 +108,7 @@ class CalendarSyncManager(
currentDavResource = calendar
calendar.calendarQuery("VEVENT", limitStart, null)
remoteResources = HashMap<String, DavResource>(davCollection.members.size)
remoteResources = HashMap(davCollection.members.size)
for (iCal in davCollection.members) {
val fileName = iCal.fileName()
Logger.log.fine("Found remote VEVENT: $fileName")
......
......@@ -24,12 +24,12 @@ import java.util.logging.Level
class CalendarsSyncAdapterService: SyncAdapterService() {
override fun syncAdapter() = SyncAdapter(this)
override fun syncAdapter() = CalendarsSyncAdapter(this)
protected class SyncAdapter(
class CalendarsSyncAdapter(
context: Context
): SyncAdapterService.SyncAdapter(context) {
): SyncAdapter(context) {
override fun sync(settings: ISettings, account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
try {
......@@ -51,7 +51,7 @@ class CalendarsSyncAdapterService: SyncAdapterService() {
for (calendar in AndroidCalendar.find(account, provider, LocalCalendar.Factory, "${CalendarContract.Calendars.SYNC_EVENTS}!=0", null)) {
Logger.log.info("Synchronizing calendar #${calendar.id}, URL: ${calendar.name}")
CalendarSyncManager(context, account, accountSettings, extras, authority, syncResult, provider, calendar).use {
CalendarSyncManager(context, settings, account, accountSettings, extras, authority, syncResult, provider, calendar).use {
it.performSync()
}
}
......
......@@ -30,7 +30,7 @@ class ContactsSyncAdapterService: SyncAdapterService() {
override fun syncAdapter() = ContactsSyncAdapter(this)
protected class ContactsSyncAdapter(
class ContactsSyncAdapter(
context: Context
): SyncAdapter(context) {
......@@ -61,7 +61,7 @@ class ContactsSyncAdapterService: SyncAdapterService() {
Logger.log.info("Synchronizing address book: ${addressBook.getURL()}")
Logger.log.info("Taking settings from: ${addressBook.getMainAccount()}")
ContactsSyncManager(context, account, accountSettings, extras, authority, syncResult, provider, addressBook).use {
ContactsSyncManager(context, settings, account, accountSettings, extras, authority, syncResult, provider, addressBook).use {
it.performSync()
}
} catch(e: Exception) {
......
......@@ -18,7 +18,6 @@ import android.provider.ContactsContract.Groups
import android.support.v4.app.NotificationCompat
import android.support.v4.app.NotificationManagerCompat
import at.bitfire.dav4android.DavAddressBook
import at.bitfire.dav4android.DavResource
import at.bitfire.dav4android.exception.DavException
import at.bitfire.dav4android.property.*
import at.bitfire.davdroid.*
......@@ -27,6 +26,7 @@ import at.bitfire.davdroid.resource.LocalAddressBook
import at.bitfire.davdroid.resource.LocalContact
import at.bitfire.davdroid.resource.LocalGroup
import at.bitfire.davdroid.resource.LocalResource
import at.bitfire.davdroid.settings.ISettings
import at.bitfire.vcard4android.BatchOperation
import at.bitfire.vcard4android.Contact
import at.bitfire.vcard4android.ContactsStorageException
......@@ -77,14 +77,15 @@ import java.util.logging.Level
*/
class ContactsSyncManager(
context: Context,
settings: ISettings,
account: Account,
settings: AccountSettings,
accountSettings: AccountSettings,
extras: Bundle,
authority: String,
syncResult: SyncResult,
val provider: ContentProviderClient,
private val localAddressBook: LocalAddressBook
): SyncManager(context, account, settings, extras, authority, syncResult, "addressBook") {
): SyncManager(context, settings, account, accountSettings, extras, authority, syncResult, "addressBook") {
companion object {
private val MAX_MULTIGET = 10
......@@ -94,7 +95,7 @@ class ContactsSyncManager(
private var numDiscarded = 0
private var hasVCard4 = false
private val groupMethod = settings.getGroupMethod()
private val groupMethod = accountSettings.getGroupMethod()
init {
......@@ -228,7 +229,7 @@ class ContactsSyncManager(
private fun notifyDiscardedChange() {
val notification = NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_delete_light)
.setSmallIcon(R.drawable.ic_delete_notification)
.setLargeIcon(App.getLauncherBitmap(context))
.setContentTitle(context.getString(R.string.sync_contacts_read_only_address_book))
.setContentText(context.resources.getQuantityString(R.plurals.sync_contacts_local_contact_changes_discarded, numDiscarded, numDiscarded))
......@@ -288,7 +289,7 @@ class ContactsSyncManager(
// fetch list of remote VCards and build hash table to index file name
addressBook.propfind(1, ResourceType.NAME, GetETag.NAME)
remoteResources = HashMap<String, DavResource>(davCollection.members.size)
remoteResources = HashMap(davCollection.members.size)
for (vCard in davCollection.members) {
// ignore member collections
val type = vCard.properties[ResourceType.NAME] as ResourceType?
......@@ -482,8 +483,8 @@ class ContactsSyncManager(
}
// authenticate only against a certain host, and only upon request
val username = settings.username()
val password = settings.password()
val username = accountSettings.username()
val password = accountSettings.password()
val builder = if (username != null && password != null)
HttpClient.Builder(context, baseUrl.host(), username, password)
else
......
......@@ -83,7 +83,7 @@ abstract class SyncAdapterService: Service() {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val notify = NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_error_light)
.setSmallIcon(R.drawable.ic_sync_error_notification)
.setLargeIcon(App.getLauncherBitmap(context))
.setContentTitle(context.getString(R.string.sync_error_permissions))
.setContentText(context.getString(R.string.sync_error_permissions_text))
......
......@@ -28,6 +28,7 @@ import at.bitfire.davdroid.R
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.resource.LocalCollection
import at.bitfire.davdroid.resource.LocalResource
import at.bitfire.davdroid.settings.ISettings
import at.bitfire.davdroid.ui.AccountSettingsActivity
import at.bitfire.davdroid.ui.DebugInfoActivity
import at.bitfire.ical4android.CalendarStorageException
......@@ -41,32 +42,39 @@ import java.util.logging.Level
abstract class SyncManager(
val context: Context,
val settings: ISettings,
val account: Account,
val settings: AccountSettings,
val accountSettings: AccountSettings,
val extras: Bundle,
val authority: String,
val syncResult: SyncResult,
val uniqueCollectionId: String
): Closeable {
val SYNC_PHASE_PREPARE = 0
val SYNC_PHASE_QUERY_CAPABILITIES = 1
val SYNC_PHASE_PROCESS_LOCALLY_DELETED = 2
val SYNC_PHASE_PREPARE_DIRTY = 3
val SYNC_PHASE_UPLOAD_DIRTY = 4
val SYNC_PHASE_CHECK_SYNC_STATE = 5
val SYNC_PHASE_LIST_LOCAL = 6
val SYNC_PHASE_LIST_REMOTE = 7
val SYNC_PHASE_COMPARE_LOCAL_REMOTE = 8
val SYNC_PHASE_DOWNLOAD_REMOTE = 9
val SYNC_PHASE_POST_PROCESSING = 10
val SYNC_PHASE_SAVE_SYNC_STATE = 11
companion object {
val SYNC_PHASE_PREPARE = 0
val SYNC_PHASE_QUERY_CAPABILITIES = 1
val SYNC_PHASE_PROCESS_LOCALLY_DELETED = 2
val SYNC_PHASE_PREPARE_DIRTY = 3
val SYNC_PHASE_UPLOAD_DIRTY = 4
val SYNC_PHASE_CHECK_SYNC_STATE = 5
val SYNC_PHASE_LIST_LOCAL = 6
val SYNC_PHASE_LIST_REMOTE = 7
val SYNC_PHASE_COMPARE_LOCAL_REMOTE = 8
val SYNC_PHASE_DOWNLOAD_REMOTE = 9
val SYNC_PHASE_POST_PROCESSING = 10
val SYNC_PHASE_SAVE_SYNC_STATE = 11
infix fun <T> Set<T>.disjunct(other: Set<T>) = (this - other) union (other - this)
}
protected val notificationManager = NotificationManagerCompat.from(context)!!
protected lateinit var localCollection: LocalCollection<*>
protected val httpClient = HttpClient.Builder(context, accountSettings = settings).build()
protected val httpClient = HttpClient.Builder(context, settings, accountSettings).build()
protected lateinit var collectionURL: HttpUrl
protected lateinit var davCollection: DavResource
......@@ -91,14 +99,10 @@ abstract class SyncManager(
protected val toDownload = mutableSetOf<DavResource>()
companion object {
infix fun <T> Set<T>.disjunct(other: Set<T>) = (this - other) union (other - this)
}
protected abstract fun notificationId(): Int
protected abstract fun getSyncErrorTitle(): String
@Suppress("UNUSED_VALUE")
fun performSync() {
// dismiss previous error notifications
notificationManager.cancel(uniqueCollectionId, notificationId())
......@@ -218,7 +222,7 @@ abstract class SyncManager(
detailsIntent.data = Uri.parse("uri://${javaClass.name}/$uniqueCollectionId")
val builder = NotificationCompat.Builder(context)
builder .setSmallIcon(R.drawable.ic_error_light)
builder .setSmallIcon(R.drawable.ic_sync_error_notification)
.setLargeIcon(App.getLauncherBitmap(context))
.setContentTitle(getSyncErrorTitle())
.setContentIntent(PendingIntent.getActivity(context, 0, detailsIntent, PendingIntent.FLAG_CANCEL_CURRENT))
......@@ -302,7 +306,7 @@ abstract class SyncManager(
* Uploads dirty records to the server, using a PUT request for each record.
* Checks Thread.interrupted() before each request to allow quick sync cancellation.
*/
protected fun uploadDirty() {
protected open fun uploadDirty() {
// upload dirty contacts
for (local in localCollection.getDirty()) {
if (Thread.interrupted())
......@@ -356,7 +360,7 @@ abstract class SyncManager(
* <li><code>false</code> if the remote collection hasn't changed</li>
* </ul>
*/
protected fun checkSyncState(): Boolean {
protected open fun checkSyncState(): Boolean {
// check CTag (ignore on manual sync)
(davCollection.properties[GetCTag.NAME] as GetCTag?)?.let { remoteCTag = it.cTag }
......@@ -376,7 +380,7 @@ abstract class SyncManager(
/**
* Lists all local resources which should be taken into account for synchronization into {@link #localResources}.
*/
protected fun listLocal() {
protected open fun listLocal() {
// fetch list of local contacts and build hash table to index file name
val localList = localCollection.getAll()
val resources = HashMap<String, LocalResource>(localList.size)
......@@ -400,7 +404,7 @@ abstract class SyncManager(
* <li>Resources whose remote ETag has changed will be added into {@link #toDownload}</li>
* </ul>
*/
protected fun compareLocalRemote() {
protected open fun compareLocalRemote() {
/* check which contacts
1. are not present anymore remotely -> delete immediately on local side
2. updated remotely -> add to downloadNames
......@@ -418,11 +422,9 @@ abstract class SyncManager(
syncResult.stats.numDeletes++
} else {
// contact is still on server, check whether it has been updated remotely
val getETag = remote.properties[GetETag.NAME] as GetETag?
if (getETag == null || getETag.eTag == null)
throw DavException("Server didn't provide ETag")
val localETag = local.eTag
val remoteETag = getETag.eTag
val getETag = remote.properties[GetETag.NAME] as GetETag?
val remoteETag = getETag?.eTag ?: throw DavException("Server didn't provide ETag")
if (remoteETag == localETag) {
Logger.log.fine("$name has not been changed on server (ETag still $remoteETag)")
syncResult.stats.numSkippedEntries++
......@@ -457,7 +459,7 @@ abstract class SyncManager(
*/
protected open fun postProcess() {}
protected fun saveSyncState() {
protected open fun saveSyncState() {
/* Save sync state (CTag). It doesn't matter if it has changed during the sync process
(for instance, because another client has uploaded changes), because this will simply
cause all remote entries to be listed at the next sync. */
......
......@@ -29,29 +29,29 @@ import java.util.logging.Level
*/
class TasksSyncAdapterService: SyncAdapterService() {
override fun syncAdapter() = SyncAdapter(this)
override fun syncAdapter() = TasksSyncAdapter(this)
protected class SyncAdapter(
class TasksSyncAdapter(
context: Context
): SyncAdapterService.SyncAdapter(context) {
): SyncAdapter(context) {
override fun sync(settings: ISettings, account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
try {
val taskProvider = TaskProvider.fromProviderClient(provider)
val settings = AccountSettings(context, settings, account)
val accountSettings = AccountSettings(context, settings, account)
/* don't run sync if
- sync conditions (e.g. "sync only in WiFi") are not met AND
- this is is an automatic sync (i.e. manual syncs are run regardless of sync conditions)
*/
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(settings))
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(accountSettings))
return
updateLocalTaskLists(taskProvider, account, settings)
updateLocalTaskLists(taskProvider, account, accountSettings)
for (taskList in AndroidTaskList.find(account, taskProvider, LocalTaskList.Factory, "${TaskContract.TaskLists.SYNC_ENABLED}!=0", null)) {
Logger.log.info("Synchronizing task list #${taskList.id} [${taskList.syncId}]")
TasksSyncManager(context, account, settings, extras, authority, syncResult, taskProvider, taskList).use {
TasksSyncManager(context, settings, account, accountSettings, extras, authority, syncResult, taskProvider, taskList).use {
it.performSync()
}
}
......
......@@ -13,7 +13,6 @@ import android.content.Context
import android.content.SyncResult
import android.os.Bundle
import at.bitfire.dav4android.DavCalendar
import at.bitfire.dav4android.DavResource
import at.bitfire.dav4android.exception.DavException
import at.bitfire.dav4android.property.CalendarData
import at.bitfire.dav4android.property.GetCTag
......@@ -25,6 +24,7 @@ import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.resource.LocalResource
import at.bitfire.davdroid.resource.LocalTask
import at.bitfire.davdroid.resource.LocalTaskList
import at.bitfire.davdroid.settings.ISettings
import at.bitfire.ical4android.InvalidCalendarException
import at.bitfire.ical4android.Task
import at.bitfire.ical4android.TaskProvider
......@@ -39,14 +39,15 @@ import java.util.logging.Level
class TasksSyncManager(
context: Context,
settings: ISettings,
account: Account,
settings: AccountSettings,
accountSettings: AccountSettings,
extras: Bundle,
authority: String,
syncResult: SyncResult,
val provider: TaskProvider,
val localTaskList: LocalTaskList
): SyncManager(context, account, settings, extras, authority, syncResult, "taskList/${localTaskList.id}") {
): SyncManager(context, settings, account, accountSettings, extras, authority, syncResult, "taskList/${localTaskList.id}") {
val MAX_MULTIGET = 30
......@@ -92,7 +93,7 @@ class TasksSyncManager(
currentDavResource = calendar
calendar.calendarQuery("VTODO", null, null)
remoteResources = HashMap<String, DavResource>(davCollection.members.size)
remoteResources = HashMap(davCollection.members.size)
for (vCard in davCollection.members) {
val fileName = vCard.fileName()
Logger.log.fine("Found remote VTODO: $fileName")
......
......@@ -19,6 +19,7 @@ import android.support.v4.content.AsyncTaskLoader
import android.support.v4.content.Loader
import at.bitfire.dav4android.DavResource
import at.bitfire.dav4android.XmlUtils
import at.bitfire.davdroid.AccountSettings
import at.bitfire.davdroid.DavUtils
import at.bitfire.davdroid.HttpClient
import at.bitfire.davdroid.R
......@@ -183,8 +184,8 @@ class CreateCollectionFragment: DialogFragment(), LoaderManager.LoaderCallbacks<
Logger.log.log(Level.SEVERE, "Couldn't assemble Extended MKCOL request", e)
}
Settings.getInstance(context).use { settings ->
HttpClient.Builder(context, settings, account)
Settings.getInstance(context)?.use { settings ->
HttpClient.Builder(context, settings, AccountSettings(context, settings, account))
.setForeground(true)
.build().use { httpClient ->
try {
......
......@@ -19,6 +19,7 @@ import android.support.v4.content.AsyncTaskLoader
import android.support.v4.content.Loader
import android.support.v7.app.AlertDialog
import at.bitfire.dav4android.DavResource
import at.bitfire.davdroid.AccountSettings
import at.bitfire.davdroid.HttpClient
import at.bitfire.davdroid.R
import at.bitfire.davdroid.model.CollectionInfo
......@@ -83,8 +84,8 @@ class DeleteCollectionFragment: DialogFragment(), LoaderManager.LoaderCallbacks<
override fun onStartLoading() = forceLoad()
override fun loadInBackground(): Exception? {
Settings.getInstance(context).use { settings ->
HttpClient.Builder(context, settings, account)
Settings.getInstance(context)?.use { settings ->
HttpClient.Builder(context, settings, AccountSettings(context, settings, account))
.setForeground(true)
.build().use { httpClient ->
try {
......@@ -98,13 +99,12 @@ class DeleteCollectionFragment: DialogFragment(), LoaderManager.LoaderCallbacks<
val db = dbHelper.writableDatabase
db.delete(ServiceDB.Collections._TABLE, "${ServiceDB.Collections.ID}=?", arrayOf(collectionInfo.id.toString()))
}
return null
} catch(e: Exception) {
return e
}
}
}
return null
}
}
......
......@@ -17,6 +17,7 @@ import at.bitfire.davdroid.DavUtils
import at.bitfire.davdroid.HttpClient
import at.bitfire.davdroid.log.StringHandler
import at.bitfire.davdroid.model.CollectionInfo
import at.bitfire.davdroid.settings.Settings
import okhttp3.HttpUrl
import org.apache.commons.lang3.builder.ReflectionToStringBuilder
import org.apache.commons.lang3.builder.ToStringBuilder
......@@ -50,7 +51,8 @@ class DavResourceFinder(
log.addHandler(logBuffer)
}
private val httpClient: HttpClient = HttpClient.Builder(context, logger = log)
private val settings = Settings.getInstance(context)
private val httpClient: HttpClient = HttpClient.Builder(context, settings, logger = log)
.addAuthentication(null, credentials.userName, credentials.password)