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

Unverified Commit 3331ee11 authored by Ricki Hirner's avatar Ricki Hirner
Browse files

[WIP] Improve WorkManager usage

parent 6d0c3dd2
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -4,13 +4,13 @@ apply plugin: 'kotlin-kapt'
apply plugin: 'com.mikepenz.aboutlibraries.plugin'

android {
    compileSdkVersion 31
    compileSdkVersion 32
    buildToolsVersion '32.0.0'

    defaultConfig {
        applicationId "at.bitfire.icsdroid"
        minSdkVersion 21
        targetSdkVersion 31
        targetSdkVersion 32

        versionCode 60
        versionName "2.1-alpha.1"
@@ -65,7 +65,7 @@ android {
}

dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'

    implementation project(':cert4android')
+4 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ package at.bitfire.icsdroid

import android.app.Application
import androidx.appcompat.app.AppCompatDelegate
import at.bitfire.icsdroid.ui.NotificationUtils
import at.bitfire.icsdroid.ui.Settings

class MyApp: Application() {
@@ -13,6 +14,9 @@ class MyApp: Application() {
    override fun onCreate() {
        super.onCreate()

        // create notification channels
        NotificationUtils.createChannels(this)

        // dark mode is not persisted over app restarts
        if (Settings(this).forceDarkMode())
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
+4 −2
Original line number Diff line number Diff line
@@ -9,15 +9,17 @@ import android.app.PendingIntent
import android.content.*
import android.os.Bundle
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.work.WorkManager
import at.bitfire.icsdroid.ui.CalendarListActivity
import at.bitfire.icsdroid.ui.NotificationUtils
import kotlinx.coroutines.runBlocking

class SyncAdapter(
        context: Context
): AbstractThreadedSyncAdapter(context, false) {

    override fun onPerformSync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
    override fun onPerformSync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult): Unit = runBlocking {
        val manual = extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL)
        SyncWorker.run(context, manual)
    }
@@ -29,7 +31,7 @@ class SyncAdapter(
    }

    override fun onSecurityException(account: Account?, extras: Bundle?, authority: String?, syncResult: SyncResult?) {
        val nm = NotificationUtils.createChannels(context)
        val nm = NotificationManagerCompat.from(context)
        val notification = NotificationCompat.Builder(context, NotificationUtils.CHANNEL_SYNC)
                .setSmallIcon(R.drawable.ic_sync_problem_white)
                .setContentTitle(context.getString(R.string.sync_permission_required))
+30 −13
Original line number Diff line number Diff line
@@ -10,10 +10,15 @@ import android.content.ContentProviderClient
import android.content.Context
import android.provider.CalendarContract
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.work.*
import at.bitfire.ical4android.CalendarStorageException
import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat
import at.bitfire.icsdroid.db.LocalCalendar
import at.bitfire.icsdroid.ui.NotificationUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.withContext
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
@@ -22,7 +27,7 @@ import kotlin.math.min
class SyncWorker(
        context: Context,
        workerParams: WorkerParameters
): Worker(context, workerParams) {
): CoroutineWorker(context, workerParams) {

    companion object {

@@ -30,21 +35,25 @@ class SyncWorker(

        private val nrSyncThreads = min(Runtime.getRuntime().availableProcessors(), 4)


        /**
         * Enqueues a sync job for immediate execution. If the sync is forced,
         * the "requires network connection" constraint won't be set.
         *
         * @param context     required for managing work
         * @param force       *true* enqueues the sync regardless of the network state; *false* adds a [NetworkType.CONNECTED] constraint
         *
         * @return            WorkManager operation
         */
        fun run(context: Context, force: Boolean = false) {
        fun run(context: Context, force: Boolean = false): Operation {
            val request = OneTimeWorkRequestBuilder<SyncWorker>()

            val policy: ExistingWorkPolicy
            if (force) {
                Log.i(Constants.TAG, "Manual sync, ignoring network condition")

                // work is user-initiated
                request.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)

                // overwrite existing syncs (which may have unwanted constraints)
                policy = ExistingWorkPolicy.REPLACE

@@ -58,7 +67,7 @@ class SyncWorker(
                policy = ExistingWorkPolicy.KEEP
            }

            WorkManager.getInstance(context)
            return WorkManager.getInstance(context)
                .beginUniqueWork(NAME, policy, request.build())
                .enqueue()
        }
@@ -70,10 +79,10 @@ class SyncWorker(


    private val syncQueue = LinkedBlockingQueue<Runnable>()
    private val syncExecutor = ThreadPoolExecutor(nrSyncThreads, nrSyncThreads, 5, TimeUnit.SECONDS, syncQueue)
    private val syncExecutor = ThreadPoolExecutor(nrSyncThreads, nrSyncThreads, 5, TimeUnit.SECONDS, syncQueue).asCoroutineDispatcher()

    @SuppressLint("Recycle")
    override fun doWork(): Result {
    override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
        applicationContext.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.let { providerClient ->
            try {
                return performSync(AppAccount.get(applicationContext), providerClient)
@@ -84,6 +93,19 @@ class SyncWorker(
        return Result.failure()
    }

    override suspend fun getForegroundInfo(): ForegroundInfo {
        val notify = NotificationCompat.Builder(applicationContext, NotificationUtils.CHANNEL_SYNC)
            .setContentTitle("Synchronizing")
            .setProgress(1, 0, true)
        return ForegroundInfo(NotificationUtils.NOTIFY_SYNC, notify.build())
    }

    /*override fun onStopped() {
        super.onStopped()
        syncExecutor.shutdownNow()
    }*/


    private fun performSync(account: Account, provider: ContentProviderClient): Result {
        Log.i(Constants.TAG, "Synchronizing ${account.name}")
        try {
@@ -104,9 +126,4 @@ class SyncWorker(
        return Result.success()
    }


    override fun onStopped() {
        syncExecutor.shutdownNow()
    }

}
+4 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ object NotificationUtils {
    const val CHANNEL_SYNC = "sync"

    const val NOTIFY_PERMISSION = 0
    const val NOTIFY_SYNC = 1


    val flagImmutableCompat: Int =
@@ -25,15 +26,12 @@ object NotificationUtils {
            0


    fun createChannels(context: Context): NotificationManager {
        val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    fun createChannels(context: Context) {
        if (Build.VERSION.SDK_INT >= 26) {
            val nm = context.getSystemService(NotificationManager::class.java)
            nm.createNotificationChannel(NotificationChannel(CHANNEL_SYNC,
                    context.getString(R.string.notification_channel_sync_problem), NotificationManager.IMPORTANCE_LOW))
                    context.getString(R.string.notification_channel_sync), NotificationManager.IMPORTANCE_LOW))
        }

        return nm
    }

}
 No newline at end of file
Loading