diff --git a/lib/entities/background_tasks.dart b/lib/entities/background_tasks.dart index ce1e2f6d8..6588cd948 100644 --- a/lib/entities/background_tasks.dart +++ b/lib/entities/background_tasks.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:background_fetch/background_fetch.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -11,7 +12,7 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:workmanager/workmanager.dart'; +// import 'package:workmanager/workmanager.dart'; import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/di.dart'; @@ -19,74 +20,74 @@ const moneroSyncTaskKey = "com.fotolockr.cakewallet.monero_sync_task"; @pragma('vm:entry-point') void callbackDispatcher() { - Workmanager().executeTask((task, inputData) async { - try { - switch (task) { - case moneroSyncTaskKey: + // Workmanager().executeTask((task, inputData) async { + // try { + // switch (task) { + // case moneroSyncTaskKey: - /// The work manager runs on a separate isolate from the main flutter isolate. - /// thus we initialize app configs first; hive, getIt, etc... - await initializeAppConfigs(); + // /// The work manager runs on a separate isolate from the main flutter isolate. + // /// thus we initialize app configs first; hive, getIt, etc... + // await initializeAppConfigs(); - final walletLoadingService = getIt.get(); + // final walletLoadingService = getIt.get(); - final node = getIt.get().getCurrentNode(WalletType.monero); + // final node = getIt.get().getCurrentNode(WalletType.monero); - final typeRaw = getIt.get().getInt(PreferencesKey.currentWalletType); + // final typeRaw = getIt.get().getInt(PreferencesKey.currentWalletType); - WalletBase? wallet; + // WalletBase? wallet; - if (inputData!['sync_all'] as bool) { - /// get all Monero wallets of the user and sync them - final List moneroWallets = getIt - .get() - .wallets - .where((element) => element.type == WalletType.monero) - .toList(); + // if (inputData!['sync_all'] as bool) { + // /// get all Monero wallets of the user and sync them + // final List moneroWallets = getIt + // .get() + // .wallets + // .where((element) => element.type == WalletType.monero) + // .toList(); - for (int i = 0; i < moneroWallets.length; i++) { - wallet = await walletLoadingService.load(WalletType.monero, moneroWallets[i].name); + // for (int i = 0; i < moneroWallets.length; i++) { + // wallet = await walletLoadingService.load(WalletType.monero, moneroWallets[i].name); - await wallet.connectToNode(node: node); - await wallet.startSync(); - } - } else { - /// if the user chose to sync only active wallet - /// if the current wallet is monero; sync it only - if (typeRaw == WalletType.monero.index) { - final name = - getIt.get().getString(PreferencesKey.currentWalletName); + // await wallet.connectToNode(node: node); + // await wallet.startSync(); + // } + // } else { + // /// if the user chose to sync only active wallet + // /// if the current wallet is monero; sync it only + // if (typeRaw == WalletType.monero.index) { + // final name = + // getIt.get().getString(PreferencesKey.currentWalletName); - wallet = await walletLoadingService.load(WalletType.monero, name!); + // wallet = await walletLoadingService.load(WalletType.monero, name!); - await wallet.connectToNode(node: node); - await wallet.startSync(); - } - } + // await wallet.connectToNode(node: node); + // await wallet.startSync(); + // } + // } - if (wallet?.syncStatus.progress() == null) { - return Future.error("No Monero wallet found"); - } + // if (wallet?.syncStatus.progress() == null) { + // return Future.error("No Monero wallet found"); + // } - for (int i = 0;; i++) { - await Future.delayed(const Duration(seconds: 1)); - if (wallet?.syncStatus.progress() == 1.0) { - break; - } - if (i > 600) { - return Future.error("Synchronization Timed out"); - } - } - break; - } + // for (int i = 0;; i++) { + // await Future.delayed(const Duration(seconds: 1)); + // if (wallet?.syncStatus.progress() == 1.0) { + // break; + // } + // if (i > 600) { + // return Future.error("Synchronization Timed out"); + // } + // } + // break; + // } - return Future.value(true); - } catch (error, stackTrace) { - print(error); - print(stackTrace); - return Future.error(error); - } - }); + // return Future.value(true); + // } catch (error, stackTrace) { + // print(error); + // print(stackTrace); + // return Future.error(error); + // } + // }); } class BackgroundTasks { @@ -107,55 +108,151 @@ class BackgroundTasks { final SyncMode syncMode = settingsStore.currentSyncMode; final bool syncAll = settingsStore.currentSyncAll; - if (syncMode.type == SyncType.disabled) { - cancelSyncTask(); - return; + late int fetchInterval; + switch (syncMode.type) { + case SyncType.unobtrusive: + fetchInterval = 1440; // 1 day + break; + case SyncType.aggressive: + fetchInterval = 15; // minutes + break; + case SyncType.disabled: + cancelSyncTask(); + return; } - await Workmanager().initialize( - callbackDispatcher, - isInDebugMode: kDebugMode, + int status = await BackgroundFetch.configure( + BackgroundFetchConfig( + minimumFetchInterval: fetchInterval, + enableHeadless: syncMode.type == SyncType.aggressive, // android only + stopOnTerminate: syncMode.type != SyncType.aggressive, // android only + startOnBoot: true, + requiresBatteryNotLow: false, + requiresCharging: false, + requiredNetworkType: NetworkType.NONE, + requiresDeviceIdle: false, + requiresStorageNotLow: false, + ), + // event handler: + (String taskId) async { + // This is the fetch-event callback. + print("[BackgroundFetch] Event received $taskId"); + + /// The work manager runs on a separate isolate from the main flutter isolate. + /// thus we initialize app configs first; hive, getIt, etc... + await initializeAppConfigs(); + + final walletLoadingService = getIt.get(); + + final node = getIt.get().getCurrentNode(WalletType.monero); + + final typeRaw = getIt.get().getInt(PreferencesKey.currentWalletType); + + WalletBase? wallet; + + /// get all Monero wallets of the user and sync them + final List moneroWallets = getIt + .get() + .wallets + .where((element) => element.type == WalletType.monero) + .toList(); + + for (int i = 0; i < moneroWallets.length; i++) { + wallet = await walletLoadingService.load(WalletType.monero, moneroWallets[i].name); + + await wallet.connectToNode(node: node); + await wallet.startSync(); + } + + // TODO: + // /// if the user chose to sync only active wallet + // /// if the current wallet is monero; sync it only + // if (typeRaw == WalletType.monero.index) { + // final name = + // getIt.get().getString(PreferencesKey.currentWalletName); + + // wallet = await walletLoadingService.load(WalletType.monero, name!); + + // await wallet.connectToNode(node: node); + // await wallet.startSync(); + // } + + if (wallet?.syncStatus.progress() == null) { + return Future.error("No Monero wallet found"); + } + + for (int i = 0;; i++) { + await Future.delayed(const Duration(seconds: 1)); + if (wallet?.syncStatus.progress() == 1.0) { + break; + } + if (i > 600) { + return Future.error("Synchronization Timed out"); + } + } + + // IMPORTANT: You must signal completion of your fetch task or the OS can punish your app + // for taking too long in the background. + BackgroundFetch.finish(taskId); + }, + // timeout handler: + (String taskId) { + // This task has been completed, another fetch event can be scheduled. + print("[BackgroundFetch] TASK TIMEOUT $taskId"); + }, ); - final inputData = {"sync_all": syncAll}; - final constraints = Constraints( - networkType: - syncMode.type == SyncType.unobtrusive ? NetworkType.unmetered : NetworkType.connected, - requiresBatteryNotLow: syncMode.type == SyncType.unobtrusive, - requiresCharging: syncMode.type == SyncType.unobtrusive, - requiresDeviceIdle: syncMode.type == SyncType.unobtrusive, - ); + print('[BackgroundFetch] configure success: $status'); - if (Platform.isIOS) { - await Workmanager().registerOneOffTask( - moneroSyncTaskKey, - moneroSyncTaskKey, - initialDelay: syncMode.frequency, - existingWorkPolicy: ExistingWorkPolicy.replace, - inputData: inputData, - constraints: constraints, - ); - return; - } + status = await BackgroundFetch.start(); + print('[BackgroundFetch] start success: $status'); - await Workmanager().registerPeriodicTask( - moneroSyncTaskKey, - moneroSyncTaskKey, - initialDelay: syncMode.frequency, - frequency: syncMode.frequency, - existingWorkPolicy: changeExisting ? ExistingWorkPolicy.replace : ExistingWorkPolicy.keep, - inputData: inputData, - constraints: constraints, - ); + // await Workmanager().initialize( + // callbackDispatcher, + // isInDebugMode: kDebugMode, + // ); + + // final inputData = {"sync_all": syncAll}; + // final constraints = Constraints( + // networkType: + // syncMode.type == SyncType.unobtrusive ? NetworkType.unmetered : NetworkType.connected, + // requiresBatteryNotLow: syncMode.type == SyncType.unobtrusive, + // requiresCharging: syncMode.type == SyncType.unobtrusive, + // requiresDeviceIdle: syncMode.type == SyncType.unobtrusive, + // ); + + // if (Platform.isIOS) { + // await Workmanager().registerOneOffTask( + // moneroSyncTaskKey, + // moneroSyncTaskKey, + // initialDelay: syncMode.frequency, + // existingWorkPolicy: ExistingWorkPolicy.replace, + // inputData: inputData, + // constraints: constraints, + // ); + // return; + // } + + // await Workmanager().registerPeriodicTask( + // moneroSyncTaskKey, + // moneroSyncTaskKey, + // initialDelay: syncMode.frequency, + // frequency: syncMode.frequency, + // existingWorkPolicy: changeExisting ? ExistingWorkPolicy.replace : ExistingWorkPolicy.keep, + // inputData: inputData, + // constraints: constraints, + // ); } catch (error, stackTrace) { print(error); print(stackTrace); } } - void cancelSyncTask() { + void cancelSyncTask() async { try { - Workmanager().cancelByUniqueName(moneroSyncTaskKey); + // Workmanager().cancelByUniqueName(moneroSyncTaskKey); + int status = await BackgroundFetch.stop(); + print('[BackgroundFetch] stop success: $status'); } catch (error, stackTrace) { print(error); print(stackTrace); diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 1e5a2df26..fad727446 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -66,6 +66,7 @@ dependencies: permission_handler: ^10.0.0 device_display_brightness: ^0.0.6 workmanager: ^0.5.1 + background_fetch: ^1.2.1 platform_device_id: ^1.0.1 wakelock: ^0.6.2 flutter_mailer: ^2.0.2