Skip to content

Commit b2ca208

Browse files
fix: ensure background worker is scheduled when the app is dismissed (#22032)
* fix: ensure background worker is scheduled when the app is dismissed * remove logs * fix: use native locks (#22081) * fix: native locks * use atomicints * change count check --------- Co-authored-by: shenlong-tanwen <[email protected]> --------- Co-authored-by: shenlong <[email protected]> Co-authored-by: shenlong-tanwen <[email protected]>
1 parent 2e94528 commit b2ca208

File tree

5 files changed

+45
-2
lines changed

5 files changed

+45
-2
lines changed

mobile/android/app/src/main/kotlin/app/alextran/immich/ImmichApp.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package app.alextran.immich
33
import android.app.Application
44
import androidx.work.Configuration
55
import androidx.work.WorkManager
6+
import app.alextran.immich.background.BackgroundWorkerApiImpl
67

78
class ImmichApp : Application() {
89
override fun onCreate() {
@@ -14,6 +15,8 @@ class ImmichApp : Application() {
1415
// Thus, the BackupWorker is not started. If the system kills the process after each initialization
1516
// (because of low memory etc.), the backup is never performed.
1617
// As a workaround, we also run a backup check when initializing the application
18+
1719
ContentObserverWorker.startBackupWorker(context = this, delayMilliseconds = 0)
20+
BackgroundWorkerApiImpl.enqueueBackgroundWorker(this)
1821
}
1922
}

mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package app.alextran.immich
33
import android.content.Context
44
import android.os.Build
55
import android.os.ext.SdkExtensions
6+
import app.alextran.immich.background.BackgroundEngineLock
67
import app.alextran.immich.background.BackgroundWorkerApiImpl
78
import app.alextran.immich.background.BackgroundWorkerFgHostApi
89
import app.alextran.immich.connectivity.ConnectivityApi
@@ -25,6 +26,7 @@ class MainActivity : FlutterFragmentActivity() {
2526
fun registerPlugins(ctx: Context, flutterEngine: FlutterEngine) {
2627
flutterEngine.plugins.add(BackgroundServicePlugin())
2728
flutterEngine.plugins.add(HttpSSLOptionsPlugin())
29+
flutterEngine.plugins.add(BackgroundEngineLock())
2830

2931
val messenger = flutterEngine.dartExecutor.binaryMessenger
3032
val nativeSyncApiImpl =
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package app.alextran.immich.background
2+
3+
import android.util.Log
4+
import androidx.work.WorkManager
5+
import io.flutter.embedding.engine.FlutterEngineCache
6+
import io.flutter.embedding.engine.plugins.FlutterPlugin
7+
import java.util.concurrent.atomic.AtomicInteger
8+
9+
private const val TAG = "BackgroundEngineLock"
10+
11+
class BackgroundEngineLock : FlutterPlugin {
12+
companion object {
13+
const val ENGINE_CACHE_KEY = "immich::background_worker::engine"
14+
var engineCount = AtomicInteger(0)
15+
}
16+
17+
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
18+
// work manager task is running while the main app is opened, cancel the worker
19+
if (engineCount.incrementAndGet() > 1 && FlutterEngineCache.getInstance()
20+
.get(ENGINE_CACHE_KEY) != null
21+
) {
22+
WorkManager.getInstance(binding.applicationContext)
23+
.cancelUniqueWork(BackgroundWorkerApiImpl.BACKGROUND_WORKER_NAME)
24+
FlutterEngineCache.getInstance().remove(ENGINE_CACHE_KEY)
25+
}
26+
Log.i(TAG, "Flutter engine attached. Attached Engines count: $engineCount")
27+
}
28+
29+
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
30+
engineCount.decrementAndGet()
31+
Log.i(TAG, "Flutter engine detached. Attached Engines count: $engineCount")
32+
}
33+
}

mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture
1919
import com.google.common.util.concurrent.SettableFuture
2020
import io.flutter.FlutterInjector
2121
import io.flutter.embedding.engine.FlutterEngine
22+
import io.flutter.embedding.engine.FlutterEngineCache
2223
import io.flutter.embedding.engine.dart.DartExecutor
2324
import io.flutter.embedding.engine.loader.FlutterLoader
2425
import java.util.concurrent.TimeUnit
@@ -75,6 +76,9 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
7576

7677
loader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
7778
engine = FlutterEngine(ctx)
79+
FlutterEngineCache.getInstance().remove(BackgroundEngineLock.ENGINE_CACHE_KEY);
80+
FlutterEngineCache.getInstance()
81+
.put(BackgroundEngineLock.ENGINE_CACHE_KEY, engine!!)
7882

7983
// Register custom plugins
8084
MainActivity.registerPlugins(ctx, engine!!)
@@ -188,6 +192,7 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
188192
isComplete = true
189193
engine?.destroy()
190194
engine = null
195+
FlutterEngineCache.getInstance().remove(BackgroundEngineLock.ENGINE_CACHE_KEY);
191196
flutterApi = null
192197
notificationManager.cancel(NOTIFICATION_ID)
193198
waitForForegroundPromotion()

mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerApiImpl.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
2626
}
2727

2828
companion object {
29-
private const val BACKGROUND_WORKER_NAME = "immich/BackgroundWorkerV1"
29+
const val BACKGROUND_WORKER_NAME = "immich/BackgroundWorkerV1"
3030
private const val OBSERVER_WORKER_NAME = "immich/MediaObserverV1"
3131

3232
fun enqueueMediaObserver(ctx: Context) {
@@ -56,7 +56,7 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
5656
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
5757
.build()
5858
WorkManager.getInstance(ctx)
59-
.enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.REPLACE, work)
59+
.enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.KEEP, work)
6060

6161
Log.i(TAG, "Enqueued background worker with name: $BACKGROUND_WORKER_NAME")
6262
}

0 commit comments

Comments
 (0)