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

Commit e625044d authored by Fahim Salam Chowdhury's avatar Fahim Salam Chowdhury 👽
Browse files

Setup syncAllAccount after login

parent 8f263d74
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
/*
 * Copyright MURENA SAS 2023
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package at.bitfire.davdroid.syncadapter

import android.content.Context
import androidx.hilt.work.HiltWorker
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import at.bitfire.davdroid.log.Logger
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import java.util.concurrent.TimeUnit
import java.util.logging.Level

/** Right after login to the cloud account, there is no guarantee the sync setup is finished, so user's might not see the calendar, task, contact accounts setup.
 * To resolve this we need to try syncing for a specific time limit with a multiplying wait time.
 * We need to use OneTimeWorker instead of PeriodicTimeWorker, because PeriodicTimWorker requires >= 15 min between it's job. But in our case, the job delays are in seconds.
 **/
@HiltWorker
class SyncAllAccountWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParameters: WorkerParameters,
) : Worker(appContext, workerParameters) {

    companion object {
        private const val NAME = "sync-all-accounts"
        private const val WAIT_SEC = "wait-sec"
        private const val DEFAULT_WAIT_SEC: Long = 5
        private const val WAIT_LIMIT_IN_SEC: Long = 120

        fun enqueue(context: Context, waitSec: Long = DEFAULT_WAIT_SEC) {
            if (waitSec > WAIT_LIMIT_IN_SEC) {
                return
            }

            val data = Data.Builder()
            data.putLong(WAIT_SEC, waitSec)

            WorkManager.getInstance(context).enqueueUniqueWork(
                NAME, ExistingWorkPolicy.REPLACE,
                OneTimeWorkRequestBuilder<SyncAllAccountWorker>()
                    .setInitialDelay(
                        waitSec,
                        TimeUnit.SECONDS
                    )   // wait some time before sync all accounts
                    .setInputData(data.build())
                    .build()
            )
        }
    }

    override fun doWork(): Result {
        Logger.log.log(Level.FINE, "sync all accounts work started")

        val result = SyncUtils.syncAllAccounts(applicationContext)
        if (!result) {
            return Result.success()
        }

        enqueueNext()
        return Result.success()
    }

    private fun enqueueNext() {
        var waitSec = inputData.getLong(WAIT_SEC, DEFAULT_WAIT_SEC)

        if (waitSec < DEFAULT_WAIT_SEC) {
            waitSec = DEFAULT_WAIT_SEC
        }

        enqueue(applicationContext, waitSec * 2)
    }
}
+32 −1
Original line number Diff line number Diff line
@@ -14,10 +14,13 @@ import android.content.pm.PackageManager
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.os.Build
import android.view.MenuItem
import androidx.annotation.StringRes
import androidx.annotation.WorkerThread
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import at.bitfire.davdroid.Constants
import at.bitfire.davdroid.DavUtils
import at.bitfire.davdroid.InvalidAccountException
import at.bitfire.davdroid.PermissionUtils
import at.bitfire.davdroid.R
@@ -157,4 +160,32 @@ object SyncUtils {
        }
    }

    private fun allAccounts(context: Context): List<Account> {
        val accountManager = AccountManager.get(context)
        val accounts = mutableListOf<Account>()

        accounts.addAll(getAccountsByType(context, accountManager, R.string.account_type))
        accounts.addAll(getAccountsByType(context, accountManager, R.string.eelo_account_type))
        accounts.addAll(getAccountsByType(context, accountManager, R.string.google_account_type))

        return accounts
    }

    private fun getAccountsByType(context: Context, accountManager: AccountManager, @StringRes type: Int): Array<out Account> {
        val accountType = context.getString(type)
        return accountManager.getAccountsByType(accountType)
    }

    fun syncAllAccounts(context: Context): Boolean {
        val accounts = allAccounts(context)
        if (accounts.isEmpty()) {
            return false
        }

        accounts.forEach {
                DavUtils.requestSync(context, it)
        }

        return true
    }
}
+2 −18
Original line number Diff line number Diff line
@@ -4,28 +4,19 @@

package at.bitfire.davdroid.ui

import android.accounts.AccountManager
import android.app.Activity
import android.content.Intent
import android.content.SyncStatusObserver
import android.content.pm.ShortcutManager
import android.os.Build
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.GravityCompat
import at.bitfire.davdroid.DavUtils
import at.bitfire.davdroid.R
import at.bitfire.davdroid.databinding.ActivityAccountsBinding
import at.bitfire.davdroid.syncadapter.SyncUtils
import at.bitfire.davdroid.ui.setup.LoginActivity
import com.google.android.material.navigation.NavigationView
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
@@ -92,14 +83,7 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele
        return true
    }


    private fun allAccounts() =
            AccountManager.get(this).getAccountsByType(getString(R.string.account_type))

    fun syncAllAccounts(item: MenuItem? = null) {
        val accounts = allAccounts()
        for (account in accounts)
            DavUtils.requestSync(this, account)
        SyncUtils.syncAllAccounts(this)
    }

}
+7 −1
Original line number Diff line number Diff line
@@ -24,7 +24,11 @@ import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.*
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import at.bitfire.davdroid.Constants
import at.bitfire.davdroid.DavUtils
import at.bitfire.davdroid.InvalidAccountException
@@ -41,6 +45,7 @@ import at.bitfire.davdroid.servicedetection.RefreshCollectionsWorker
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.settings.SettingsManager
import at.bitfire.davdroid.syncadapter.AccountUtils
import at.bitfire.davdroid.syncadapter.SyncAllAccountWorker
import at.bitfire.vcard4android.GroupMethod
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
@@ -352,6 +357,7 @@ class AccountDetailsFragment : Fragment() {
                }

                DavUtils.requestSync(activity, account)
                SyncAllAccountWorker.enqueue(context, 2)

                result.postValue(true)
            }