Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 4084dc36 authored by Patrick Lang's avatar Patrick Lang Committed by Ricki Hirner
Browse files

Updated queryCapabilities to use the same code as in TasksSyncManager, added...


Updated queryCapabilities to use the same code as in TasksSyncManager, added try-catch block for sync-method (#60)

* Updated queryCapabilities to use the same code as in TasksSyncManager
Might solve #59

* Added try-catch block for sync-method
updated min version for JtxBoard in TaskProvider.kt
Should solve #59

* removed syncResult.databaseError = true

* Changed wrong file before

* Created TasksSyncUtils to put notifyProviderTooOld method

* Cleaned up imports

* Added Version check in JtxSyncAdapterService.kt, required TaskProvider.checkVersion to be public

* Minor changes

Co-authored-by: default avatarRicki Hirner <hirner@bitfire.at>
parent 7534fe68
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ package at.bitfire.davdroid.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
@@ -27,16 +28,26 @@ class JtxSyncAdapterService: SyncAdapterService() {

    override fun syncAdapter() = JtxSyncAdapter(this)


    class JtxSyncAdapter(context: Context): SyncAdapter(context) {

        override fun sync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
            val accountSettings = AccountSettings(context, account)

            try {
                // check whether jtx Board is new enough
                TaskProvider.checkVersion(context, TaskProvider.ProviderName.JtxBoard)

                // make sure account can be seen by task provider
                if (Build.VERSION.SDK_INT >= 26)
                    AccountManager.get(context).setAccountVisibility(account, TaskProvider.ProviderName.JtxBoard.packageName, AccountManager.VISIBILITY_VISIBLE)

                /* 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)
                 */
                val accountSettings = AccountSettings(context, account)
                if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(accountSettings))
                    return

                //sync list of collections
                updateLocalCollections(account, provider)

@@ -48,6 +59,13 @@ class JtxSyncAdapterService: SyncAdapterService() {
                        it.performSync()
                    }
                }

            } catch (e: TaskProvider.ProviderTooOldException) {
                SyncUtils.notifyProviderTooOld(context, e)
            } catch (e: Exception) {
                Logger.log.log(Level.SEVERE, "Couldn't sync jtx collections", e)
            }
            Logger.log.info("jtx sync complete")
        }

        private fun updateLocalCollections(account: Account, client: ContentProviderClient) {
@@ -81,7 +99,6 @@ class JtxSyncAdapterService: SyncAdapterService() {
                LocalJtxCollection.create(account, client, info)
            }
        }

    }

}
 No newline at end of file
+3 −12
Original line number Diff line number Diff line
@@ -49,28 +49,20 @@ class JtxSyncManager(
        return true
    }

    override fun queryCapabilities(): SyncState? =
    override fun queryCapabilities() =
        remoteExceptionContext {
            var syncState: SyncState? = null
            it.propfind(0, SupportedReportSet.NAME, GetCTag.NAME, SyncToken.NAME) { response, relation ->
                if (relation == Response.HrefRelation.SELF) {
                    response[SupportedReportSet::class.java]?.let { supported ->
                        hasCollectionSync = supported.reports.contains(SupportedReportSet.SYNC_COLLECTION)
                    }
            it.propfind(0, GetCTag.NAME, SyncToken.NAME) { response, relation ->
                if (relation == Response.HrefRelation.SELF)
                    syncState = syncState(response)
            }
            }

            Logger.log.info("Server supports Collection Sync: $hasCollectionSync")
            syncState
        }

    override fun generateUpload(resource: LocalJtxICalObject): RequestBody = localExceptionContext(resource) {
        Logger.log.log(Level.FINE, "Preparing upload of icalobject ${resource.fileName}", resource)

        val os = ByteArrayOutputStream()
        resource.write(os)

        os.toByteArray().toRequestBody(DavCalendar.MIME_ICALENDAR_UTF8)
    }

@@ -112,7 +104,6 @@ class JtxSyncManager(
    override fun postProcess() {
        /* related-to entries must be updated. The linkedICalObjectId is set to 0 for synced entries as we cannot be sure that the linked entry is already
        there when the related-to entry is written. therefore we have to update it here in the postProcess() method.  */

        localCollection.updateRelatedTo()
    }

+62 −0
Original line number Diff line number Diff line
/***************************************************************************************************
 * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
 **************************************************************************************************/

package at.bitfire.davdroid.syncadapter

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import at.bitfire.davdroid.R
import at.bitfire.davdroid.ui.NotificationUtils
import at.bitfire.ical4android.TaskProvider

object SyncUtils {

    /**
     * Starts an Intent and redirects the user to the package in the market to update the app
     *
     * @param e   the TaskProvider.ProviderTooOldException to be shown
     */
    fun notifyProviderTooOld(context: Context, e: TaskProvider.ProviderTooOldException) {
        val nm = NotificationManagerCompat.from(context)
        val message = context.getString(R.string.sync_error_tasks_required_version, e.provider.minVersionName)

        val pm = context.packageManager
        val tasksAppInfo = pm.getPackageInfo(e.provider.packageName, 0)
        val tasksAppLabel = tasksAppInfo.applicationInfo.loadLabel(pm)

        val notify = NotificationUtils.newBuilder(context, NotificationUtils.CHANNEL_SYNC_ERRORS)
            .setSmallIcon(R.drawable.ic_sync_problem_notify)
            .setContentTitle(context.getString(R.string.sync_error_tasks_too_old, tasksAppLabel))
            .setContentText(message)
            .setSubText("$tasksAppLabel ${e.installedVersionName}")
            .setCategory(NotificationCompat.CATEGORY_ERROR)

        try {
            val icon = pm.getApplicationIcon(e.provider.packageName)
            if (icon is BitmapDrawable)
                notify.setLargeIcon(icon.bitmap)
        } catch (ignored: PackageManager.NameNotFoundException) {
            // couldn't get provider app icon
        }

        val intent = Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=${e.provider.packageName}"))

        var flags = PendingIntent.FLAG_UPDATE_CURRENT
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            flags = flags or PendingIntent.FLAG_IMMUTABLE

        if (intent.resolveActivity(pm) != null)
            notify.setContentIntent(PendingIntent.getActivity(context, 0, intent, flags))

        nm.notify(NotificationUtils.NOTIFY_TASKS_PROVIDER_TOO_OLD, notify.build())
    }

}
 No newline at end of file
+5 −34
Original line number Diff line number Diff line
@@ -5,23 +5,18 @@ package at.bitfire.davdroid.syncadapter

import android.accounts.Account
import android.accounts.AccountManager
import android.app.PendingIntent
import android.content.*
import android.content.pm.PackageManager
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
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 androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import at.bitfire.davdroid.R
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.model.AppDatabase
import at.bitfire.davdroid.model.Collection
import at.bitfire.davdroid.model.Service
import at.bitfire.davdroid.resource.LocalTaskList
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.ui.NotificationUtils
import at.bitfire.ical4android.AndroidTaskList
import at.bitfire.ical4android.TaskProvider
import okhttp3.HttpUrl
@@ -69,31 +64,7 @@ open class TasksSyncAdapterService: SyncAdapterService() {
                    }
                }
            } catch (e: TaskProvider.ProviderTooOldException) {
                val nm = NotificationManagerCompat.from(context)
                val message = context.getString(R.string.sync_error_tasks_required_version, e.provider.minVersionName)

                val pm = context.packageManager
                val tasksAppInfo = pm.getPackageInfo(e.provider.packageName, 0)
                val tasksAppLabel = tasksAppInfo.applicationInfo.loadLabel(pm)

                val notify = NotificationUtils.newBuilder(context, NotificationUtils.CHANNEL_SYNC_ERRORS)
                        .setSmallIcon(R.drawable.ic_sync_problem_notify)
                        .setContentTitle(context.getString(R.string.sync_error_tasks_too_old, tasksAppLabel))
                        .setContentText(message)
                        .setSubText("$tasksAppLabel ${e.installedVersionName}")
                        .setCategory(NotificationCompat.CATEGORY_ERROR)

                try {
                    val icon = pm.getApplicationIcon(e.provider.packageName)
                    if (icon is BitmapDrawable)
                        notify.setLargeIcon(icon.bitmap)
                } catch(ignored: PackageManager.NameNotFoundException) {}

                val intent = Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=${e.provider.packageName}"))
                if (intent.resolveActivity(pm) != null)
                    notify.setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))

                nm.notify(NotificationUtils.NOTIFY_OPENTASKS, notify.build())
                SyncUtils.notifyProviderTooOld(context, e)
                syncResult.databaseError = true
            } catch (e: Exception) {
                Logger.log.log(Level.SEVERE, "Couldn't sync task lists", e)
+1 −1
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ object NotificationUtils {
    const val NOTIFY_INVALID_RESOURCE = 11
    const val NOTIFY_WEBDAV_ACCESS = 12
    const val NOTIFY_LOW_STORAGE = 13
    const val NOTIFY_OPENTASKS = 20
    const val NOTIFY_TASKS_PROVIDER_TOO_OLD = 20
    const val NOTIFY_PERMISSIONS = 21

    const val NOTIFY_LICENSE = 100