You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
etesync-android/app/src/main/java/com/etesync/syncadapter/syncadapter/TasksSyncAdapterService.kt

121 lines
5.1 KiB

/*
* Copyright © Ricki Hirner (bitfire web engineering).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package com.etesync.syncadapter.syncadapter
import android.accounts.Account
import android.accounts.AccountManager
import android.content.ContentProviderClient
import android.content.ContentResolver
import android.content.Context
import android.content.SyncResult
import android.os.Build
import android.os.Bundle
import at.bitfire.ical4android.AndroidTaskList
import at.bitfire.ical4android.TaskProvider
import at.bitfire.ical4android.TaskProvider.ProviderName
import com.etesync.syncadapter.AccountSettings
import com.etesync.syncadapter.App
import com.etesync.syncadapter.Constants
import com.etesync.syncadapter.R
import com.etesync.syncadapter.log.Logger
import com.etesync.syncadapter.model.CollectionInfo
import com.etesync.syncadapter.model.JournalEntity
import com.etesync.syncadapter.model.JournalModel
import com.etesync.syncadapter.resource.LocalTaskList
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import org.dmfs.tasks.contract.TaskContract
import java.util.*
/**
* Synchronization manager for CalDAV collections; handles tasks ({@code VTODO}).
*/
class TasksSyncAdapterService: SyncAdapterService() {
override fun syncAdapter() = TasksSyncAdapter(this, ProviderName.OpenTasks)
class TasksSyncAdapter(
context: Context,
private val name: ProviderName
): SyncAdapter(context) {
override val syncErrorTitle = R.string.sync_error_tasks
override val notificationManager = SyncNotification(context, "journals-tasks", Constants.NOTIFICATION_TASK_SYNC)
override fun onPerformSyncDo(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
val taskProvider = TaskProvider.fromProviderClient(context, provider, name)
// make sure account can be seen by OpenTasks
if (Build.VERSION.SDK_INT >= 26)
AccountManager.get(context).setAccountVisibility(account, taskProvider.name.packageName, AccountManager.VISIBILITY_VISIBLE)
val accountSettings = AccountSettings(context, 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(accountSettings))
return
RefreshCollections(account, CollectionInfo.Type.TASKS).run()
updateLocalTaskLists(taskProvider, account, accountSettings)
val principal = accountSettings.uri?.toHttpUrlOrNull()!!
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, accountSettings, extras, authority, syncResult, taskList, principal).use {
it.performSync()
}
}
Logger.log.info("Task sync complete")
}
private fun updateLocalTaskLists(provider: TaskProvider, account: Account, settings: AccountSettings) {
val data = (context.applicationContext as App).data
var service = JournalModel.Service.fetchOrCreate(data, account.name, CollectionInfo.Type.TASKS)
val remote = HashMap<String, JournalEntity>()
val remoteJournals = JournalEntity.getJournals(data, service)
for (journalEntity in remoteJournals) {
remote[journalEntity.uid] = journalEntity
}
val local = AndroidTaskList.find(account, provider, LocalTaskList.Factory, null, null)
val updateColors = settings.manageCalendarColors
// delete obsolete local TaskList
for (taskList in local) {
val url = taskList.url
val journalEntity = remote[url]
if (journalEntity == null) {
Logger.log.fine("Deleting obsolete local task list $url")
taskList.delete()
} else {
// remote CollectionInfo found for this local collection, update data
Logger.log.fine("Updating local task list $url with $journalEntity")
taskList.update(journalEntity, updateColors)
// we already have a local tasks for this remote collection, don't take into consideration anymore
remote.remove(url)
}
}
// create new local taskss
for (url in remote.keys) {
val journalEntity = remote[url]!!
Logger.log.info("Adding local task list $journalEntity")
LocalTaskList.create(account, provider, journalEntity)
}
}
}
}