chore(mobile): update target SDK version (#11719)

* chore(mobile): update target SDK version

* background service

* remove print statements

* remove extra line

* format kotlin

* Correct permission
This commit is contained in:
Alex 2024-08-15 11:36:43 -05:00 committed by GitHub
parent a4506758aa
commit 49610de4b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 626 additions and 570 deletions

View File

@ -46,7 +46,7 @@ android {
defaultConfig { defaultConfig {
applicationId "app.alextran.immich" applicationId "app.alextran.immich"
minSdkVersion 26 minSdkVersion 26
targetSdkVersion 33 targetSdkVersion 34
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
} }

View File

@ -1,9 +1,38 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="app.alextran.immich" <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="app.alextran.immich"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.MANAGE_MEDIA" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<!-- Foreground service permission -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<application android:label="Immich" android:name=".ImmichApp" android:usesCleartextTraffic="true" <application android:label="Immich" android:name=".ImmichApp" android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher" android:requestLegacyExternalStorage="true" android:icon="@mipmap/ic_launcher" android:requestLegacyExternalStorage="true"
android:largeHeap="true"> android:largeHeap="true">
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:directBootAware="false"
android:enabled="@bool/enable_system_foreground_service_default"
android:exported="false"
android:foregroundServiceType="dataSync|shortService" />
<meta-data <meta-data
android:name="io.flutter.embedding.android.EnableImpeller" android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" /> android:value="false" />
@ -51,23 +80,13 @@
<provider <provider
android:name="androidx.startup.InitializationProvider" android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup" android:authorities="${applicationId}.androidx-startup"
tools:node="remove"></provider> tools:node="remove" />
</application> </application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.MANAGE_MEDIA" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<queries> <queries>
<intent> <intent>

View File

@ -7,7 +7,6 @@ import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import java.security.MessageDigest import java.security.MessageDigest
import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import kotlinx.coroutines.* import kotlinx.coroutines.*
@ -21,7 +20,6 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
private var methodChannel: MethodChannel? = null private var methodChannel: MethodChannel? = null
private var context: Context? = null private var context: Context? = null
private val sha1: MessageDigest = MessageDigest.getInstance("SHA-1")
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
onAttachedToEngine(binding.applicationContext, binding.binaryMessenger) onAttachedToEngine(binding.applicationContext, binding.binaryMessenger)
@ -50,36 +48,47 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
ctx.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE) ctx.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE)
.edit() .edit()
.putBoolean(ContentObserverWorker.SHARED_PREF_SERVICE_ENABLED, true) .putBoolean(ContentObserverWorker.SHARED_PREF_SERVICE_ENABLED, true)
.putLong(BackupWorker.SHARED_PREF_CALLBACK_KEY, args.get(0) as Long) .putLong(BackupWorker.SHARED_PREF_CALLBACK_KEY, args[0] as Long)
.putString(BackupWorker.SHARED_PREF_NOTIFICATION_TITLE, args.get(1) as String) .putString(BackupWorker.SHARED_PREF_NOTIFICATION_TITLE, args[1] as String)
.apply() .apply()
ContentObserverWorker.enable(ctx, immediate = args.get(2) as Boolean) ContentObserverWorker.enable(ctx, immediate = args[2] as Boolean)
result.success(true) result.success(true)
} }
"configure" -> { "configure" -> {
val args = call.arguments<ArrayList<*>>()!! val args = call.arguments<ArrayList<*>>()!!
val requireUnmeteredNetwork = args.get(0) as Boolean val requireUnmeteredNetwork = args[0] as Boolean
val requireCharging = args.get(1) as Boolean val requireCharging = args[1] as Boolean
val triggerUpdateDelay = (args.get(2) as Number).toLong() val triggerUpdateDelay = (args[2] as Number).toLong()
val triggerMaxDelay = (args.get(3) as Number).toLong() val triggerMaxDelay = (args[3] as Number).toLong()
ContentObserverWorker.configureWork(ctx, requireUnmeteredNetwork, requireCharging, triggerUpdateDelay, triggerMaxDelay) ContentObserverWorker.configureWork(
ctx,
requireUnmeteredNetwork,
requireCharging,
triggerUpdateDelay,
triggerMaxDelay
)
result.success(true) result.success(true)
} }
"disable" -> { "disable" -> {
ContentObserverWorker.disable(ctx) ContentObserverWorker.disable(ctx)
BackupWorker.stopWork(ctx) BackupWorker.stopWork(ctx)
result.success(true) result.success(true)
} }
"isEnabled" -> { "isEnabled" -> {
result.success(ContentObserverWorker.isEnabled(ctx)) result.success(ContentObserverWorker.isEnabled(ctx))
} }
"isIgnoringBatteryOptimizations" -> { "isIgnoringBatteryOptimizations" -> {
result.success(BackupWorker.isIgnoringBatteryOptimizations(ctx)) result.success(BackupWorker.isIgnoringBatteryOptimizations(ctx))
} }
"digestFiles" -> { "digestFiles" -> {
val args = call.arguments<ArrayList<String>>()!! val args = call.arguments<ArrayList<String>>()!!
GlobalScope.launch(Dispatchers.IO) { GlobalScope.launch(Dispatchers.IO) {
val buf = ByteArray(BUFSIZE) val buf = ByteArray(BUFFER_SIZE)
val digest: MessageDigest = MessageDigest.getInstance("SHA-1") val digest: MessageDigest = MessageDigest.getInstance("SHA-1")
val hashes = arrayOfNulls<ByteArray>(args.size) val hashes = arrayOfNulls<ByteArray>(args.size)
for (i in args.indices) { for (i in args.indices) {
@ -87,14 +96,12 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
var len = 0 var len = 0
try { try {
val file = FileInputStream(path) val file = FileInputStream(path)
try { file.use { assetFile ->
while (true) { while (true) {
len = file.read(buf) len = assetFile.read(buf)
if (len != BUFSIZE) break if (len != BUFFER_SIZE) break
digest.update(buf) digest.update(buf)
} }
} finally {
file.close()
} }
digest.update(buf, 0, len) digest.update(buf, 0, len)
hashes[i] = digest.digest() hashes[i] = digest.digest()
@ -106,10 +113,11 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
result.success(hashes.asList()) result.success(hashes.asList())
} }
} }
else -> result.notImplemented() else -> result.notImplemented()
} }
} }
} }
private const val TAG = "BackgroundServicePlugin" private const val TAG = "BackgroundServicePlugin"
private const val BUFSIZE = 2*1024*1024; private const val BUFFER_SIZE = 2 * 1024 * 1024;

View File

@ -4,6 +4,7 @@ import android.app.Notification
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE
import android.os.Build import android.os.Build
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@ -40,12 +41,14 @@ import java.util.concurrent.TimeUnit
* Called by Android WorkManager when all constraints for the work are met, * Called by Android WorkManager when all constraints for the work are met,
* i.e. battery is not low and optionally Wifi and charging are active. * i.e. battery is not low and optionally Wifi and charging are active.
*/ */
class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ctx, params), MethodChannel.MethodCallHandler { class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ctx, params),
MethodChannel.MethodCallHandler {
private val resolvableFuture = ResolvableFuture.create<Result>() private val resolvableFuture = ResolvableFuture.create<Result>()
private var engine: FlutterEngine? = null private var engine: FlutterEngine? = null
private lateinit var backgroundChannel: MethodChannel private lateinit var backgroundChannel: MethodChannel
private val notificationManager = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager private val notificationManager =
ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private val isIgnoringBatteryOptimizations = isIgnoringBatteryOptimizations(applicationContext) private val isIgnoringBatteryOptimizations = isIgnoringBatteryOptimizations(applicationContext)
private var timeBackupStarted: Long = 0L private var timeBackupStarted: Long = 0L
private var notificationBuilder: NotificationCompat.Builder? = null private var notificationBuilder: NotificationCompat.Builder? = null
@ -61,10 +64,11 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
if (!flutterLoader.initialized()) { if (!flutterLoader.initialized()) {
flutterLoader.startInitialization(ctx) flutterLoader.startInitialization(ctx)
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create a Notification channel if necessary // Create a Notification channel
createChannel() createChannel()
}
Log.d(TAG, "isIgnoringBatteryOptimizations $isIgnoringBatteryOptimizations")
if (isIgnoringBatteryOptimizations) { if (isIgnoringBatteryOptimizations) {
// normal background services can only up to 10 minutes // normal background services can only up to 10 minutes
// foreground services are allowed to run indefinitely // foreground services are allowed to run indefinitely
@ -74,6 +78,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
.getString(SHARED_PREF_NOTIFICATION_TITLE, NOTIFICATION_DEFAULT_TITLE)!! .getString(SHARED_PREF_NOTIFICATION_TITLE, NOTIFICATION_DEFAULT_TITLE)!!
showInfo(getInfoBuilder(title, indeterminate = true).build()) showInfo(getInfoBuilder(title, indeterminate = true).build())
} }
engine = FlutterEngine(ctx) engine = FlutterEngine(ctx)
flutterLoader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) { flutterLoader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
@ -89,8 +94,10 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
*/ */
private fun runDart() { private fun runDart() {
val callbackDispatcherHandle = applicationContext.getSharedPreferences( val callbackDispatcherHandle = applicationContext.getSharedPreferences(
SHARED_PREF_NAME, Context.MODE_PRIVATE).getLong(SHARED_PREF_CALLBACK_KEY, 0L) SHARED_PREF_NAME, Context.MODE_PRIVATE
val callbackInformation = FlutterCallbackInformation.lookupCallbackInformation(callbackDispatcherHandle) ).getLong(SHARED_PREF_CALLBACK_KEY, 0L)
val callbackInformation =
FlutterCallbackInformation.lookupCallbackInformation(callbackDispatcherHandle)
val appBundlePath = flutterLoader.findAppBundlePath() val appBundlePath = flutterLoader.findAppBundlePath()
engine?.let { engine -> engine?.let { engine ->
@ -123,11 +130,10 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
private fun waitOnSetForegroundAsync() { private fun waitOnSetForegroundAsync() {
val fgFuture = this.fgFuture val fgFuture = this.fgFuture
if (fgFuture != null && !fgFuture.isCancelled() && !fgFuture.isDone()) { if (fgFuture != null && !fgFuture.isCancelled && !fgFuture.isDone) {
try { try {
fgFuture.get(500, TimeUnit.MILLISECONDS) fgFuture.get(500, TimeUnit.MILLISECONDS)
} } catch (e: Exception) {
catch (e: Exception) {
// ignored, there is nothing to be done // ignored, there is nothing to be done
} }
} }
@ -144,6 +150,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
waitOnSetForegroundAsync() waitOnSetForegroundAsync()
} }
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
override fun onMethodCall(call: MethodCall, r: MethodChannel.Result) { override fun onMethodCall(call: MethodCall, r: MethodChannel.Result) {
when (call.method) { when (call.method) {
"initialized" -> { "initialized" -> {
@ -167,26 +174,32 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
} }
) )
} }
"updateNotification" -> { "updateNotification" -> {
val args = call.arguments<ArrayList<*>>()!! val args = call.arguments<ArrayList<*>>()!!
val title = args.get(0) as String? val title = args[0] as String?
val content = args.get(1) as String? val content = args[1] as String?
val progress = args.get(2) as Int val progress = args[2] as Int
val max = args.get(3) as Int val max = args[3] as Int
val indeterminate = args.get(4) as Boolean val indeterminate = args[4] as Boolean
val isDetail = args.get(5) as Boolean val isDetail = args[5] as Boolean
val onlyIfFG = args.get(6) as Boolean val onlyIfFG = args[6] as Boolean
if (!onlyIfFG || isIgnoringBatteryOptimizations) { if (!onlyIfFG || isIgnoringBatteryOptimizations) {
showInfo(getInfoBuilder(title, content, isDetail, progress, max, indeterminate).build(), isDetail) showInfo(
getInfoBuilder(title, content, isDetail, progress, max, indeterminate).build(),
isDetail
)
} }
} }
"showError" -> { "showError" -> {
val args = call.arguments<ArrayList<*>>()!! val args = call.arguments<ArrayList<*>>()!!
val title = args.get(0) as String val title = args[0] as String
val content = args.get(1) as String? val content = args[1] as String?
val individualTag = args.get(2) as String? val individualTag = args[2] as String?
showError(title, content, individualTag) showError(title, content, individualTag)
} }
"clearErrorNotifications" -> clearErrorNotifications() "clearErrorNotifications" -> clearErrorNotifications()
"hasContentChanged" -> { "hasContentChanged" -> {
val lastChange = applicationContext val lastChange = applicationContext
@ -196,6 +209,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
timeBackupStarted = SystemClock.uptimeMillis() timeBackupStarted = SystemClock.uptimeMillis()
r.success(hasContentChanged) r.success(hasContentChanged)
} }
else -> r.notImplemented() else -> r.notImplemented()
} }
} }
@ -221,8 +235,13 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
private fun showInfo(notification: Notification, isDetail: Boolean = false) { private fun showInfo(notification: Notification, isDetail: Boolean = false) {
val id = if (isDetail) NOTIFICATION_DETAIL_ID else NOTIFICATION_ID val id = if (isDetail) NOTIFICATION_DETAIL_ID else NOTIFICATION_ID
if (isIgnoringBatteryOptimizations && !isDetail) { if (isIgnoringBatteryOptimizations && !isDetail) {
fgFuture = setForegroundAsync(ForegroundInfo(id, notification)) fgFuture = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
setForegroundAsync(ForegroundInfo(id, notification, FOREGROUND_SERVICE_TYPE_SHORT_SERVICE))
} else {
setForegroundAsync(ForegroundInfo(id, notification))
}
} else { } else {
notificationManager.notify(id, notification) notificationManager.notify(id, notification)
} }
@ -257,11 +276,18 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
return builder.setProgress(max, progress, indeterminate) return builder.setProgress(max, progress, indeterminate)
} }
@RequiresApi(Build.VERSION_CODES.O)
private fun createChannel() { private fun createChannel() {
val foreground = NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW) val foreground = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_ID,
NotificationManager.IMPORTANCE_LOW
)
notificationManager.createNotificationChannel(foreground) notificationManager.createNotificationChannel(foreground)
val error = NotificationChannel(NOTIFICATION_CHANNEL_ERROR_ID, NOTIFICATION_CHANNEL_ERROR_ID, NotificationManager.IMPORTANCE_HIGH) val error = NotificationChannel(
NOTIFICATION_CHANNEL_ERROR_ID,
NOTIFICATION_CHANNEL_ERROR_ID,
NotificationManager.IMPORTANCE_HIGH
)
notificationManager.createNotificationChannel(error) notificationManager.createNotificationChannel(error)
} }
@ -283,21 +309,26 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
/** /**
* Enqueues the BackupWorker to run once the constraints are met * Enqueues the BackupWorker to run once the constraints are met
*/ */
fun enqueueBackupWorker(context: Context, fun enqueueBackupWorker(
context: Context,
requireWifi: Boolean = false, requireWifi: Boolean = false,
requireCharging: Boolean = false, requireCharging: Boolean = false,
delayMilliseconds: Long = 0L) { delayMilliseconds: Long = 0L
) {
val workRequest = buildWorkRequest(requireWifi, requireCharging, delayMilliseconds) val workRequest = buildWorkRequest(requireWifi, requireCharging, delayMilliseconds)
WorkManager.getInstance(context).enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.KEEP, workRequest) WorkManager.getInstance(context)
.enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.KEEP, workRequest)
Log.d(TAG, "enqueueBackupWorker: BackupWorker enqueued") Log.d(TAG, "enqueueBackupWorker: BackupWorker enqueued")
} }
/** /**
* Updates the constraints of an already enqueued BackupWorker * Updates the constraints of an already enqueued BackupWorker
*/ */
fun updateBackupWorker(context: Context, fun updateBackupWorker(
context: Context,
requireWifi: Boolean = false, requireWifi: Boolean = false,
requireCharging: Boolean = false) { requireCharging: Boolean = false
) {
try { try {
val wm = WorkManager.getInstance(context) val wm = WorkManager.getInstance(context)
val workInfoFuture = wm.getWorkInfosForUniqueWork(TASK_NAME_BACKUP) val workInfoFuture = wm.getWorkInfosForUniqueWork(TASK_NAME_BACKUP)
@ -314,7 +345,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
} }
Log.d(TAG, "updateBackupWorker: BackupWorker not enqueued") Log.d(TAG, "updateBackupWorker: BackupWorker not enqueued")
} catch (e: Exception) { } catch (e: Exception) {
Log.d(TAG, "updateBackupWorker failed: ${e}") Log.d(TAG, "updateBackupWorker failed: $e")
} }
} }
@ -330,17 +361,15 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
* Returns `true` if the app is ignoring battery optimizations * Returns `true` if the app is ignoring battery optimizations
*/ */
fun isIgnoringBatteryOptimizations(ctx: Context): Boolean { fun isIgnoringBatteryOptimizations(ctx: Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { val powerManager = ctx.getSystemService(Context.POWER_SERVICE) as PowerManager
val pwrm = ctx.getSystemService(Context.POWER_SERVICE) as PowerManager return powerManager.isIgnoringBatteryOptimizations(ctx.packageName)
val name = ctx.packageName
return pwrm.isIgnoringBatteryOptimizations(name)
}
return true
} }
private fun buildWorkRequest(requireWifi: Boolean = false, private fun buildWorkRequest(
requireWifi: Boolean = false,
requireCharging: Boolean = false, requireCharging: Boolean = false,
delayMilliseconds: Long = 0L): OneTimeWorkRequest { delayMilliseconds: Long = 0L
): OneTimeWorkRequest {
val constraints = Constraints.Builder() val constraints = Constraints.Builder()
.setRequiredNetworkType(if (requireWifi) NetworkType.UNMETERED else NetworkType.CONNECTED) .setRequiredNetworkType(if (requireWifi) NetworkType.UNMETERED else NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true) .setRequiresBatteryNotLow(true)

View File

@ -26,7 +26,7 @@ class ContentObserverWorker(ctx: Context, params: WorkerParameters) : Worker(ctx
if (!isEnabled(applicationContext)) { if (!isEnabled(applicationContext)) {
return Result.failure() return Result.failure()
} }
if (getTriggeredContentUris().size > 0) { if (triggeredContentUris.size > 0) {
startBackupWorker(applicationContext, delayMilliseconds = 0) startBackupWorker(applicationContext, delayMilliseconds = 0)
} }
enqueueObserverWorker(applicationContext, ExistingWorkPolicy.REPLACE) enqueueObserverWorker(applicationContext, ExistingWorkPolicy.REPLACE)
@ -35,10 +35,10 @@ class ContentObserverWorker(ctx: Context, params: WorkerParameters) : Worker(ctx
companion object { companion object {
const val SHARED_PREF_SERVICE_ENABLED = "serviceEnabled" const val SHARED_PREF_SERVICE_ENABLED = "serviceEnabled"
const val SHARED_PREF_REQUIRE_WIFI = "requireWifi" private const val SHARED_PREF_REQUIRE_WIFI = "requireWifi"
const val SHARED_PREF_REQUIRE_CHARGING = "requireCharging" private const val SHARED_PREF_REQUIRE_CHARGING = "requireCharging"
const val SHARED_PREF_TRIGGER_UPDATE_DELAY = "triggerUpdateDelay" private const val SHARED_PREF_TRIGGER_UPDATE_DELAY = "triggerUpdateDelay"
const val SHARED_PREF_TRIGGER_MAX_DELAY = "triggerMaxDelay" private const val SHARED_PREF_TRIGGER_MAX_DELAY = "triggerMaxDelay"
private const val TASK_NAME_OBSERVER = "immich/ContentObserver" private const val TASK_NAME_OBSERVER = "immich/ContentObserver"
@ -106,7 +106,7 @@ class ContentObserverWorker(ctx: Context, params: WorkerParameters) : Worker(ctx
WorkManager WorkManager
.getInstance(context) .getInstance(context)
.enqueueUniqueWork(TASK_NAME_OBSERVER, ExistingWorkPolicy.REPLACE, work) .enqueueUniqueWork(TASK_NAME_OBSERVER, ExistingWorkPolicy.REPLACE, work)
.getResult() .result
.get() .get()
Log.d(TAG, "workManagerAppClearedWorkaround") Log.d(TAG, "workManagerAppClearedWorkaround")
} }