diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibrarySyncWorker.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibrarySyncWorker.kt index 69810c10e..ef0f9e822 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibrarySyncWorker.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibrarySyncWorker.kt @@ -40,81 +40,20 @@ class LibrarySyncWorker @AssistedInject constructor( private val datastoreRepository: DatastoreRepository, ) : CoroutineWorker(appContext, workerParams) { - companion object { - const val NOTIFICATION_CHANNEL_ID = "LIBRARY_SYNC_WORKER_CHANNEL" - const val NOTIFICATION_CHANNEL_NAME = "Sync library" - const val NOTIFICATION_ID = 2 - } - - override suspend fun getForegroundInfo(): ForegroundInfo { - val notification = createNotification() - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - ForegroundInfo( - NOTIFICATION_ID, - notification, - ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC - ) - } else { - ForegroundInfo(NOTIFICATION_ID, notification) - } - } - override suspend fun doWork(): Result { return try { - // Start foreground service immediately - setForeground(getForegroundInfo()) - withContext(Dispatchers.IO) { performItemSync() loadUsingSearchAPI() Log.d("LibrarySyncWorker", "Library sync completed successfully") Result.success() } - } catch (e: IllegalStateException) { - Log.w("LibrarySyncWorker", "Couldn't start foreground service", e) - // Continue with the work without the foreground service - try { - performItemSync() - loadUsingSearchAPI() - Log.d("LibrarySyncWorker", "Library sync completed without foreground service") - Result.success() - } catch (e: Exception) { - Log.e("LibrarySyncWorker", "Failed to sync library without foreground service", e) - Result.failure() - } } catch (e: Exception) { Log.e("LibrarySyncWorker", "Unexpected error in LibrarySyncWorker", e) Result.failure() } } - private fun createNotification(): Notification { - val channelId = createNotificationChannel() - - return NotificationCompat.Builder(applicationContext, channelId) - .setContentTitle("Syncing library items") - .setContentText("Your library is being synced") - .setSmallIcon(R.drawable.ic_notification) - .setPriority(NotificationCompat.PRIORITY_HIGH) - .setCategory(NotificationCompat.CATEGORY_SERVICE) - .build() - } - - private fun createNotificationChannel(): String { - val channel = NotificationChannel( - NOTIFICATION_CHANNEL_ID, - NOTIFICATION_CHANNEL_NAME, - NotificationManager.IMPORTANCE_HIGH - ).apply { - description = "Notification channel for library syncing" - } - - val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - notificationManager.createNotificationChannel(channel) - - return NOTIFICATION_CHANNEL_ID - } - private suspend fun performItemSync( cursor: String? = null, since: String = getLastSyncTime()?.toString() ?: Instant.MIN.toString(), @@ -133,7 +72,7 @@ class LibrarySyncWorker @AssistedInject constructor( if (result.hasError) { result.errorString?.let { errorString -> - println("SYNC ERROR: $errorString") + Log.e("LibrarySyncWorker", "SYNC ERROR: $errorString") } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/save/SaveSheetActivity.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/save/SaveSheetActivity.kt index 4fbbed9f3..ba480fb9f 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/save/SaveSheetActivity.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/save/SaveSheetActivity.kt @@ -37,6 +37,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import java.util.concurrent.TimeUnit import kotlin.time.Duration.Companion.seconds import kotlin.time.toJavaDuration @@ -134,23 +135,26 @@ class SaveSheetActivity : AppCompatActivity() { } private fun WorkManager.enqueueSaveWorker(context: Context, url: String) { - val constraints = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) + val saveData = workDataOf("url" to url) + + val saveWork = OneTimeWorkRequestBuilder() + .setInputData(saveData) + .setConstraints(Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build()) .build() - val inputData = Data.Builder() - .putString("url", url) - .build() - - val saveURLWorkRequest = OneTimeWorkRequest.Builder(SaveURLWorker::class.java) - .setConstraints(constraints) - .setInputData(inputData) - .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) - .addTag(url) + val syncWork = OneTimeWorkRequestBuilder() + .setConstraints(Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build()) + .setInitialDelay(5, TimeUnit.SECONDS) .build() WorkManager.getInstance(context) - .enqueueUniqueWork("saveUrl", ExistingWorkPolicy.REPLACE, saveURLWorkRequest) + .beginUniqueWork("saveAndSync", ExistingWorkPolicy.REPLACE, saveWork) + .then(syncWork) + .enqueue() } @Composable diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/save/SaveURLWorker.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/save/SaveURLWorker.kt index 0d2646a4a..027ffd5d8 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/save/SaveURLWorker.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/save/SaveURLWorker.kt @@ -36,31 +36,9 @@ class SaveURLWorker @AssistedInject constructor( private val datastoreRepository: DatastoreRepository, ) : CoroutineWorker(appContext, workerParams) { - companion object { - const val NOTIFICATION_CHANNEL_ID = "SAVE_URL_WORKER_CHANNEL" - const val NOTIFICATION_CHANNEL_NAME = "URL Saver" - const val NOTIFICATION_ID = 1 - } - - override suspend fun getForegroundInfo(): ForegroundInfo { - val notification = createNotification() - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - ForegroundInfo( - NOTIFICATION_ID, - notification, - ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC - ) - } else { - ForegroundInfo(NOTIFICATION_ID, notification) - } - } - override suspend fun doWork(): Result { - return try { - // Start foreground service immediately - setForeground(getForegroundInfo()) - - withContext(Dispatchers.IO) { + return withContext(Dispatchers.IO) { + try { val url = inputData.getString("url") if (url == null) { Log.e("SaveURLWorker", "No URL provided") @@ -74,21 +52,10 @@ class SaveURLWorker @AssistedInject constructor( Log.e("SaveURLWorker", "Failed to save URL") Result.failure() } - } - } catch (e: IllegalStateException) { - Log.w("SaveURLWorker", "Couldn't start foreground service", e) - // Continue with the work without the foreground service - val url = inputData.getString("url") - if (url != null && saveURL(url)) { - Log.d("SaveURLWorker", "URL saved successfully without foreground service") - Result.success() - } else { - Log.e("SaveURLWorker", "Failed to save URL without foreground service") + } catch (e: Exception) { + Log.e("SaveURLWorker", "Unexpected error in SaveURLWorker", e) Result.failure() } - } catch (e: Exception) { - Log.e("SaveURLWorker", "Unexpected error in SaveURLWorker", e) - Result.failure() } } @@ -102,7 +69,7 @@ class SaveURLWorker @AssistedInject constructor( val cleanedUrl = cleanUrl(url) ?: url - try { + return try { val timezone = TimeZone.getDefault().id val locale = Locale.current.toLanguageTag() @@ -117,11 +84,10 @@ class SaveURLWorker @AssistedInject constructor( ) ) ).execute() - return (response.data?.saveUrl?.onSaveSuccess?.url != null) + (response.data?.saveUrl?.onSaveSuccess?.url != null) } catch (e: Exception) { - Log.d("omnivore", "FAILED TO SAVE ITEM") - e.printStackTrace() - return false + Log.e("SaveURLWorker", "Failed to save item", e) + false } } @@ -129,43 +95,10 @@ class SaveURLWorker @AssistedInject constructor( val pattern = Pattern.compile("\\b(?:https?|ftp)://\\S+") val matcher = pattern.matcher(text) - if (matcher.find()) { - return matcher.group() - } - return null - } - - private fun createNotification(): Notification { - val channelId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - createNotificationChannel() + return if (matcher.find()) { + matcher.group() } else { - "" - } - - return NotificationCompat.Builder(applicationContext, channelId) - .setContentTitle("Saving URL") - .setContentText("Your URL is being saved in the background.") - .setSmallIcon(R.drawable.ic_notification) // Ensure this icon is valid - .setPriority(NotificationCompat.PRIORITY_HIGH) - .build() - } - - private fun createNotificationChannel(): String { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val channel = NotificationChannel( - NOTIFICATION_CHANNEL_ID, - NOTIFICATION_CHANNEL_NAME, - NotificationManager.IMPORTANCE_HIGH // Changed from LOW to HIGH - ).apply { - description = "Notification channel for URL saving" - } - - val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - notificationManager.createNotificationChannel(channel) - - NOTIFICATION_CHANNEL_ID - } else { - "" + null } } }