From 55031cc11748035fe1a3e8936df496b84d773afe Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 9 May 2024 12:16:53 -0500 Subject: [PATCH] Revert "feat(android) Check server is reachable before starting background backup (#8989)" (#9324) This reverts commit 0435de50f88dd84b24822e41adac838d77286a70. --- .../example/mobile/BackgroundServicePlugin.kt | 1 - .../kotlin/com/example/mobile/BackupWorker.kt | 126 ++++-------------- .../BackgroundServicePlugin.swift | 6 +- mobile/lib/services/background.service.dart | 7 +- 4 files changed, 29 insertions(+), 111 deletions(-) diff --git a/mobile/android/app/src/main/kotlin/com/example/mobile/BackgroundServicePlugin.kt b/mobile/android/app/src/main/kotlin/com/example/mobile/BackgroundServicePlugin.kt index 1d23c5665c..6541ad5755 100644 --- a/mobile/android/app/src/main/kotlin/com/example/mobile/BackgroundServicePlugin.kt +++ b/mobile/android/app/src/main/kotlin/com/example/mobile/BackgroundServicePlugin.kt @@ -52,7 +52,6 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler { .putBoolean(ContentObserverWorker.SHARED_PREF_SERVICE_ENABLED, true) .putLong(BackupWorker.SHARED_PREF_CALLBACK_KEY, args.get(0) as Long) .putString(BackupWorker.SHARED_PREF_NOTIFICATION_TITLE, args.get(1) as String) - .putString(BackupWorker.SHARED_PREF_SERVER_URL, args.get(3) as String) .apply() ContentObserverWorker.enable(ctx, immediate = args.get(2) as Boolean) result.success(true) diff --git a/mobile/android/app/src/main/kotlin/com/example/mobile/BackupWorker.kt b/mobile/android/app/src/main/kotlin/com/example/mobile/BackupWorker.kt index 214fca983b..b6b78c2cba 100644 --- a/mobile/android/app/src/main/kotlin/com/example/mobile/BackupWorker.kt +++ b/mobile/android/app/src/main/kotlin/com/example/mobile/BackupWorker.kt @@ -11,8 +11,8 @@ import android.os.PowerManager import android.os.SystemClock import android.util.Log import androidx.annotation.RequiresApi -import androidx.concurrent.futures.CallbackToFutureAdapter import androidx.core.app.NotificationCompat +import androidx.concurrent.futures.ResolvableFuture import androidx.work.BackoffPolicy import androidx.work.Constraints import androidx.work.ForegroundInfo @@ -30,16 +30,6 @@ import io.flutter.embedding.engine.loader.FlutterLoader import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.view.FlutterCallbackInformation -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import kotlinx.coroutines.withTimeoutOrNull -import java.io.IOException -import java.net.HttpURLConnection -import java.net.InetAddress -import java.net.URL import java.util.concurrent.TimeUnit /** @@ -52,6 +42,7 @@ import java.util.concurrent.TimeUnit */ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ctx, params), MethodChannel.MethodCallHandler { + private val resolvableFuture = ResolvableFuture.create() private var engine: FlutterEngine? = null private lateinit var backgroundChannel: MethodChannel private val notificationManager = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager @@ -61,80 +52,35 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct private var notificationDetailBuilder: NotificationCompat.Builder? = null private var fgFuture: ListenableFuture? = null - private val job = Job() - private lateinit var completer: CallbackToFutureAdapter.Completer - private val resolvableFuture = CallbackToFutureAdapter.getFuture { completer -> - this.completer = completer - null - } - - init { - resolvableFuture.addListener( - Runnable { - if (resolvableFuture.isCancelled) { - job.cancel() - } - }, - taskExecutor.serialTaskExecutor - ) - } - override fun startWork(): ListenableFuture { + Log.d(TAG, "startWork") val ctx = applicationContext - val prefs = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE) - prefs.getString(SHARED_PREF_SERVER_URL, null) - ?.takeIf { it.isNotEmpty() } - ?.let { serverUrl -> doCoroutineWork(serverUrl) } - ?: doWork() - return resolvableFuture - } - - /** - * This function is used to check if server URL is reachable before starting the backup work. - * Check must be done in a background to avoid blocking the main thread. - */ - private fun doCoroutineWork(serverUrl : String) { - CoroutineScope(Dispatchers.Default + job).launch { - val isReachable = isUrlReachableHttp(serverUrl) - withContext(Dispatchers.Main) { - if (isReachable) { - doWork() - } else { - // Fail when the URL is not reachable - completer.set(Result.failure()) - } - } + if (!flutterLoader.initialized()) { + flutterLoader.startInitialization(ctx) } - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // Create a Notification channel if necessary + createChannel() + } + if (isIgnoringBatteryOptimizations) { + // normal background services can only up to 10 minutes + // foreground services are allowed to run indefinitely + // requires battery optimizations to be disabled (either manually by the user + // or by the system learning that immich is important to the user) + val title = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE) + .getString(SHARED_PREF_NOTIFICATION_TITLE, NOTIFICATION_DEFAULT_TITLE)!! + showInfo(getInfoBuilder(title, indeterminate=true).build()) + } + engine = FlutterEngine(ctx) - private fun doWork() { - Log.d(TAG, "doWork") - val ctx = applicationContext + flutterLoader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) { + runDart() + } - if (!flutterLoader.initialized()) { - flutterLoader.startInitialization(ctx) - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - // Create a Notification channel if necessary - createChannel() - } - if (isIgnoringBatteryOptimizations) { - // normal background services can only up to 10 minutes - // foreground services are allowed to run indefinitely - // requires battery optimizations to be disabled (either manually by the user - // or by the system learning that immich is important to the user) - val title = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE) - .getString(SHARED_PREF_NOTIFICATION_TITLE, NOTIFICATION_DEFAULT_TITLE)!! - showInfo(getInfoBuilder(title, indeterminate=true).build()) - } - engine = FlutterEngine(ctx) - - flutterLoader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) { - runDart() - } + return resolvableFuture } /** @@ -193,7 +139,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct engine = null if (result != null) { Log.d(TAG, "stopEngine result=${result}") - this.completer.set(result) + resolvableFuture.set(result) } waitOnSetForegroundAsync() } @@ -324,7 +270,6 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct const val SHARED_PREF_CALLBACK_KEY = "callbackDispatcherHandle" const val SHARED_PREF_NOTIFICATION_TITLE = "notificationTitle" const val SHARED_PREF_LAST_CHANGE = "lastChange" - const val SHARED_PREF_SERVER_URL = "serverUrl" private const val TASK_NAME_BACKUP = "immich/BackupWorker" private const val NOTIFICATION_CHANNEL_ID = "immich/backgroundService" @@ -415,26 +360,3 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct } private const val TAG = "BackupWorker" - -/** - * Check if the given URL is reachable via HTTP - */ -suspend fun isUrlReachableHttp(url: String, timeoutMillis: Long = 5000L): Boolean { - return withTimeoutOrNull(timeoutMillis) { - var httpURLConnection: HttpURLConnection? = null - try { - httpURLConnection = (URL(url).openConnection() as HttpURLConnection).apply { - requestMethod = "HEAD" - connectTimeout = timeoutMillis.toInt() - readTimeout = timeoutMillis.toInt() - } - httpURLConnection.connect() - httpURLConnection.responseCode == HttpURLConnection.HTTP_OK - } catch (e: Exception) { - Log.e(TAG, "Failed to reach server URL: $e") - false - } finally { - httpURLConnection?.disconnect() - } - } == true -} diff --git a/mobile/ios/Runner/BackgroundSync/BackgroundServicePlugin.swift b/mobile/ios/Runner/BackgroundSync/BackgroundServicePlugin.swift index 20626c6aa1..c84b037daf 100644 --- a/mobile/ios/Runner/BackgroundSync/BackgroundServicePlugin.swift +++ b/mobile/ios/Runner/BackgroundSync/BackgroundServicePlugin.swift @@ -171,9 +171,9 @@ class BackgroundServicePlugin: NSObject, FlutterPlugin { return } - // Requires 3 or more arguments in the array - guard args.count >= 3 else { - print("Requires 3 or more arguments and received \(args.count)") + // Requires 3 arguments in the array + guard args.count == 3 else { + print("Requires 3 arguments and received \(args.count)") result(FlutterMethodNotImplemented) return } diff --git a/mobile/lib/services/background.service.dart b/mobile/lib/services/background.service.dart index 99c56f8bc5..8e451cc271 100644 --- a/mobile/lib/services/background.service.dart +++ b/mobile/lib/services/background.service.dart @@ -20,7 +20,6 @@ import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/services/api.service.dart'; import 'package:immich_mobile/utils/backup_progress.dart'; import 'package:immich_mobile/utils/diff.dart'; -import 'package:immich_mobile/utils/url_helper.dart'; import 'package:isar/isar.dart'; import 'package:path_provider_ios/path_provider_ios.dart'; import 'package:photo_manager/photo_manager.dart'; @@ -69,10 +68,8 @@ class BackgroundService { final callback = PluginUtilities.getCallbackHandle(_nativeEntry)!; final String title = "backup_background_service_default_notification".tr(); - final bool ok = await _foregroundChannel.invokeMethod( - 'enable', - [callback.toRawHandle(), title, immediate, getServerUrl()], - ); + final bool ok = await _foregroundChannel + .invokeMethod('enable', [callback.toRawHandle(), title, immediate]); return ok; } catch (error) { return false;