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>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
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
|
||||
@@ -22,6 +25,7 @@ class SyncFlowApp : Application(), Configuration.Provider {
|
||||
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 }
|
||||
@@ -29,6 +33,27 @@ class SyncFlowApp : Application(), Configuration.Provider {
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user