Files
SyncFlow/app/src/main/kotlin/com/syncflow/SyncFlowApp.kt
T
amir a7c5ed713a feat: fix notifications on Android 13+/16, add Log tab, fix ON_CHANGE detection
- Request POST_NOTIFICATIONS permission at runtime in MainActivity (primary fix
  for notifications never appearing on Android 13+ phones including Android 16)
- Register all 4 notification channels eagerly in SyncFlowApp.onCreate() instead
  of lazily inside workers
- Add FOREGROUND_SERVICE_SHORT_SERVICE permission + shortService foreground type
  for Android 16 foreground service compatibility
- Add global activity Log tab (new tab 2 in main nav) showing all sync events
  across all pairs, grouped by date with pair name, event icon, and file detail
- Fix FileWatchService ON_CHANGE detection: ContentObserver on SAF tree URIs only
  fires for SAF-API writes, not raw filesystem writes. Now resolves primary:/*
  tree URIs to /storage/emulated/0/* and uses FileObserver for reliable detection
- Bump version to 1.0.21 (build 22)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 21:34:48 +00:00

63 lines
2.5 KiB
Kotlin

package com.syncflow
import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import com.syncflow.data.db.SyncPairDao
import com.syncflow.domain.model.ScheduleType
import com.syncflow.worker.FileWatchService
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@HiltAndroidApp
class SyncFlowApp : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
@Inject lateinit var syncPairDao: SyncPairDao
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
createNotificationChannels()
// Start file watcher on every app launch for any existing ON_CHANGE pairs
CoroutineScope(Dispatchers.IO).launch {
val hasOnChange = syncPairDao.getEnabled().any { it.scheduleType == ScheduleType.ON_CHANGE }
if (hasOnChange) FileWatchService.start(this@SyncFlowApp)
}
}
private fun createNotificationChannels() {
val nm = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
listOf(
NotificationChannel("sync_progress", "Sync progress", NotificationManager.IMPORTANCE_LOW).apply {
description = "Shown while a sync is running"
},
NotificationChannel("sync_complete", "Sync complete", NotificationManager.IMPORTANCE_LOW).apply {
description = "Summary after each successful sync"
},
NotificationChannel("sync_alerts", "Sync errors", NotificationManager.IMPORTANCE_DEFAULT).apply {
description = "Alerts for sync failures and conflicts"
},
NotificationChannel("sync_watching", "File watching", NotificationManager.IMPORTANCE_MIN).apply {
description = "Background service watching folders for changes"
setShowBadge(false)
},
).forEach { channel ->
if (nm.getNotificationChannel(channel.id) == null) nm.createNotificationChannel(channel)
}
}
override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.setMinimumLoggingLevel(android.util.Log.INFO)
.build()
}