[mob] improve background processing (#5442)
## Description Use workmanager on android and iOS. ## Tests
This commit is contained in:
@@ -142,4 +142,14 @@ dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||
|
||||
|
||||
constraints {
|
||||
implementation("androidx.work:work-runtime:2.8.1") {
|
||||
because("Align work-runtime versions")
|
||||
}
|
||||
implementation("androidx.work:work-runtime-ktx:2.8.1") {
|
||||
because("Align work-runtime-ktx versions")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,6 @@ allprojects {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
// mavenLocal() // for FDroid
|
||||
maven {
|
||||
url "${project(':background_fetch').projectDir}/libs"
|
||||
}
|
||||
maven {
|
||||
url "${project(':ffmpeg_kit_flutter').projectDir}/libs"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
PODS:
|
||||
- app_links (0.0.2):
|
||||
- Flutter
|
||||
- background_fetch (1.3.7):
|
||||
- Flutter
|
||||
- battery_info (0.0.1):
|
||||
- Flutter
|
||||
- connectivity_plus (0.0.1):
|
||||
@@ -129,9 +127,6 @@ PODS:
|
||||
- libwebp/sharpyuv (1.5.0)
|
||||
- libwebp/webp (1.5.0):
|
||||
- libwebp/sharpyuv
|
||||
- local_auth_darwin (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- local_auth_ios (0.0.1):
|
||||
- Flutter
|
||||
- Mantle (2.2.0):
|
||||
@@ -193,7 +188,7 @@ PODS:
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.17)
|
||||
- Sentry/HybridSDK (8.46.0)
|
||||
- sentry_flutter (8.14.1):
|
||||
- sentry_flutter (8.14.2):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Sentry/HybridSDK (= 8.46.0)
|
||||
@@ -242,10 +237,11 @@ PODS:
|
||||
- Flutter
|
||||
- wakelock_plus (0.0.1):
|
||||
- Flutter
|
||||
- workmanager (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- app_links (from `.symlinks/plugins/app_links/ios`)
|
||||
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
|
||||
- battery_info (from `.symlinks/plugins/battery_info/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- cupertino_http (from `.symlinks/plugins/cupertino_http/darwin`)
|
||||
@@ -270,7 +266,6 @@ DEPENDENCIES:
|
||||
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`)
|
||||
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||
- launcher_icon_switcher (from `.symlinks/plugins/launcher_icon_switcher/ios`)
|
||||
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
||||
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
|
||||
- maps_launcher (from `.symlinks/plugins/maps_launcher/ios`)
|
||||
- media_extension (from `.symlinks/plugins/media_extension/ios`)
|
||||
@@ -302,9 +297,10 @@ DEPENDENCIES:
|
||||
- video_thumbnail (from `.symlinks/plugins/video_thumbnail/ios`)
|
||||
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
- workmanager (from `.symlinks/plugins/workmanager/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/ente-io/ffmpeg-kit-custom-repo-ios.git:
|
||||
https://github.com/ente-io/ffmpeg-kit-custom-repo-ios:
|
||||
- ffmpeg_kit_custom
|
||||
trunk:
|
||||
- Firebase
|
||||
@@ -329,8 +325,6 @@ SPEC REPOS:
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
:path: ".symlinks/plugins/app_links/ios"
|
||||
background_fetch:
|
||||
:path: ".symlinks/plugins/background_fetch/ios"
|
||||
battery_info:
|
||||
:path: ".symlinks/plugins/battery_info/ios"
|
||||
connectivity_plus:
|
||||
@@ -379,8 +373,6 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/integration_test/ios"
|
||||
launcher_icon_switcher:
|
||||
:path: ".symlinks/plugins/launcher_icon_switcher/ios"
|
||||
local_auth_darwin:
|
||||
:path: ".symlinks/plugins/local_auth_darwin/darwin"
|
||||
local_auth_ios:
|
||||
:path: ".symlinks/plugins/local_auth_ios/ios"
|
||||
maps_launcher:
|
||||
@@ -443,85 +435,86 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/volume_controller/ios"
|
||||
wakelock_plus:
|
||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||
workmanager:
|
||||
:path: ".symlinks/plugins/workmanager/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: f3e17e4ee5e357b39d8b95290a9b2c299fca71c6
|
||||
background_fetch: 39f11371c0dce04b001c4bfd5e782bcccb0a85e2
|
||||
battery_info: b6c551049266af31556b93c9d9b9452cfec0219f
|
||||
connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d
|
||||
cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba
|
||||
dart_ui_isolate: d5bcda83ca4b04f129d70eb90110b7a567aece14
|
||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||
app_links: 76b66b60cc809390ca1ad69bfd66b998d2387ac7
|
||||
battery_info: 83f3aae7be2fccefab1d2bf06b8aa96f11c8bcdd
|
||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
|
||||
dart_ui_isolate: 46f6714abe6891313267153ef6f9748d8ecfcab1
|
||||
device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89
|
||||
ffmpeg_kit_custom: 682b4f2f1ff1f8abae5a92f6c3540f2441d5be99
|
||||
ffmpeg_kit_flutter: 9dce4803991478c78c6fb9f972703301101095fe
|
||||
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
||||
ffmpeg_kit_flutter: 915b345acc97d4142e8a9a8549d177ff10f043f5
|
||||
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||
Firebase: d80354ed7f6df5f9aca55e9eb47cc4b634735eaf
|
||||
firebase_core: 6e223dfa350b2edceb729cea505eaaef59330682
|
||||
firebase_messaging: 07fde77ae28c08616a1d4d870450efc2b38cf40d
|
||||
firebase_core: 6cbed78b4f298ed103a9fd034e6dbc846320480f
|
||||
firebase_messaging: 5e0adf2eb18b0ee59aa0c109314c091a0497ecac
|
||||
FirebaseCore: 99fe0c4b44a39f37d99e6404e02009d2db5d718d
|
||||
FirebaseCoreInternal: df24ce5af28864660ecbd13596fc8dd3a8c34629
|
||||
FirebaseInstallations: 6c963bd2a86aca0481eef4f48f5a4df783ae5917
|
||||
FirebaseMessaging: 487b634ccdf6f7b7ff180fdcb2a9935490f764e8
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
flutter_email_sender: e03bdda7637bcd3539bfe718fddd980e9508efaa
|
||||
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
|
||||
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
|
||||
flutter_local_notifications: ff50f8405aaa0ccdc7dcfb9022ca192e8ad9688f
|
||||
flutter_native_splash: f71420956eb811e6d310720fee915f1d42852e7a
|
||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||
flutter_sodium: a00383520fc689c688b66fd3092984174712493e
|
||||
flutter_timezone: ac3da59ac941ff1c98a2e1f0293420e020120282
|
||||
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
|
||||
flutter_email_sender: aa1e9772696691d02cd91fea829856c11efb8e58
|
||||
flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1
|
||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
||||
flutter_native_splash: 6cad9122ea0fad137d23137dd14b937f3e90b145
|
||||
flutter_secure_storage: 2c2ff13db9e0a5647389bff88b0ecac56e3f3418
|
||||
flutter_sodium: 7e4621538491834eba53bd524547854bcbbd6987
|
||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57
|
||||
image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43
|
||||
in_app_purchase_storekit: a1ce04056e23eecc666b086040239da7619cd783
|
||||
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
|
||||
launcher_icon_switcher: 8e0ad2131a20c51c1dd939896ee32e70cd845b37
|
||||
home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f
|
||||
image_editor_common: 3de87e7c4804f4ae24c8f8a998362b98c105cac1
|
||||
in_app_purchase_storekit: d1a48cb0f8b29dbf5f85f782f5dd79b21b90a5e6
|
||||
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
|
||||
launcher_icon_switcher: 84c218d233505aa7d8655d8fa61a3ba802c022da
|
||||
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
|
||||
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
|
||||
local_auth_ios: 5046a18c018dd973247a0564496c8898dbb5adf9
|
||||
local_auth_ios: f7a1841beef3151d140a967c2e46f30637cdf451
|
||||
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
|
||||
maps_launcher: 2e5b6a2d664ec6c27f82ffa81b74228d770ab203
|
||||
media_extension: 6618f07abd762cdbfaadf1b0c56a287e820f0c84
|
||||
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
||||
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
||||
motion_sensors: 03f55b7c637a7e365a0b5f9697a449f9059d5d91
|
||||
motionphoto: 8b65ce50c7d7ff3c767534fc3768b2eed9ac24e4
|
||||
move_to_background: cd3091014529ec7829e342ad2d75c0a11f4378a5
|
||||
maps_launcher: edf829809ba9e894d70e569bab11c16352dedb45
|
||||
media_extension: 671e2567880d96c95c65c9a82ccceed8f2e309fd
|
||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||
motion_sensors: 741e702c17467b9569a92165dda8d4d88c6167f1
|
||||
motionphoto: 23e2aeb5c6380112f69468d71f970fa7438e5ed1
|
||||
move_to_background: 7e3467dd2a1d1013e98c9c1cb93fd53cd7ef9d84
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
native_video_player: 5d36066807b680e181473e6890dde643ac85380d
|
||||
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
|
||||
onnxruntime: e7c2ae44385191eaad5ae64c935a72debaddc997
|
||||
native_video_player: e363dd14f6a498ad8a8f7e6486a0db046ad19f13
|
||||
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
|
||||
onnxruntime: f9b296392c96c42882be020a59dbeac6310d81b2
|
||||
onnxruntime-c: a909204639a1f035f575127ac406f781ac797c9c
|
||||
onnxruntime-objc: b6fab0f1787aa6f7190c2013f03037df4718bd8b
|
||||
open_mail_app: 70273c53f768beefdafbe310c3d9086e4da3cb02
|
||||
open_mail_app: 7314a609e88eed22d53671279e189af7a0ab0f11
|
||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
|
||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
photo_manager: ff695c7a1dd5bc379974953a2b5c0a293f7c4c8a
|
||||
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||
photo_manager: d2fbcc0f2d82458700ee6256a15018210a81d413
|
||||
privacy_screen: 3159a541f5d3a31bea916cfd4e58f9dc722b3fd4
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
receive_sharing_intent: 79c848f5b045674ad60b9fea3bafea59962ad2c1
|
||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
||||
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
|
||||
sentry_flutter: 6a134f9d381e49f22ea25a67736cf0cf4d02ec9c
|
||||
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
|
||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
||||
sentry_flutter: 27892878729f42701297c628eb90e7c6529f3684
|
||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 3c950dc86011117c307eb0b28c4a7bb449dce9f1
|
||||
sqlite3_flutter_libs: 069c435986dd4b63461aecd68f4b30be4a9e9daa
|
||||
system_info_plus: 5393c8da281d899950d751713575fbf91c7709aa
|
||||
thermal: a9261044101ae8f532fa29cab4e8270b51b3f55c
|
||||
ua_client_hints: aeabd123262c087f0ce151ef96fa3ab77bfc8b38
|
||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||
video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3
|
||||
video_thumbnail: 94ba6705afbaa120b77287080424930f23ea0c40
|
||||
volume_controller: 2e3de73d6e7e81a0067310d17fb70f2f86d71ac7
|
||||
wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56
|
||||
sqlite3_flutter_libs: 3c323550ef3b928bc0aa9513c841e45a7d242832
|
||||
system_info_plus: 555ce7047fbbf29154726db942ae785c29211740
|
||||
thermal: d4c48be750d1ddbab36b0e2dcb2471531bc8df41
|
||||
ua_client_hints: 92fe0d139619b73ec9fcb46cc7e079a26178f586
|
||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||
video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
|
||||
video_thumbnail: 584ccfa55d8fd2f3d5507218b0a18d84c839c620
|
||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||
wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49
|
||||
workmanager: 01be2de7f184bd15de93a1812936a2b7f42ef07e
|
||||
|
||||
PODFILE CHECKSUM: a8ef88ad74ba499756207e7592c6071a96756d18
|
||||
|
||||
|
||||
@@ -527,7 +527,6 @@
|
||||
"${BUILT_PRODUCTS_DIR}/SDWebImageWebPCoder/SDWebImageWebPCoder.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/Sentry/Sentry.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/app_links/app_links.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/background_fetch/background_fetch.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/battery_info/battery_info.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/cupertino_http/cupertino_http.framework",
|
||||
@@ -549,7 +548,6 @@
|
||||
"${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/launcher_icon_switcher/launcher_icon_switcher.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/local_auth_darwin/local_auth_darwin.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/maps_launcher/maps_launcher.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/media_extension/media_extension.framework",
|
||||
@@ -581,6 +579,7 @@
|
||||
"${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/volume_controller/volume_controller.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/wakelock_plus/wakelock_plus.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/workmanager/workmanager.framework",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg_kit_custom/ffmpegkit.framework/ffmpegkit",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg_kit_custom/libavcodec.framework/libavcodec",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg_kit_custom/libavdevice.framework/libavdevice",
|
||||
@@ -623,7 +622,6 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageWebPCoder.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sentry.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/app_links.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/background_fetch.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/battery_info.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cupertino_http.framework",
|
||||
@@ -645,7 +643,6 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/launcher_icon_switcher.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_darwin.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/maps_launcher.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/media_extension.framework",
|
||||
@@ -677,6 +674,7 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/volume_controller.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock_plus.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/workmanager.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ffmpegkit.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavcodec.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavdevice.framework",
|
||||
|
||||
@@ -2,6 +2,7 @@ import AVFoundation
|
||||
import Flutter
|
||||
import UIKit
|
||||
import app_links
|
||||
import workmanager
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
@@ -15,6 +16,14 @@ import app_links
|
||||
}
|
||||
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
WorkmanagerPlugin.setPluginRegistrantCallback { registry in
|
||||
GeneratedPluginRegistrant.register(with: registry)
|
||||
}
|
||||
var freqInMinutes = 30 * 60
|
||||
// Register a periodic task in iOS 13+
|
||||
WorkmanagerPlugin.registerPeriodicTask(
|
||||
withIdentifier: "io.ente.frame.iOSBackgroundAppRefresh",
|
||||
frequency: NSNumber(value: freqInMinutes))
|
||||
|
||||
// Retrieve the link from parameters
|
||||
if let url = AppLinks.shared.getLink(launchOptions: launchOptions) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<dict>
|
||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||
<array>
|
||||
<string>com.transistorsoft.fetch</string>
|
||||
<string>io.ente.frame.iOSBackgroundAppRefresh</string>
|
||||
</array>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
|
||||
@@ -2,7 +2,6 @@ import "dart:async";
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:adaptive_theme/adaptive_theme.dart';
|
||||
import 'package:background_fetch/background_fetch.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
@@ -24,18 +23,15 @@ import "package:photos/services/people_home_widget_service.dart";
|
||||
import 'package:photos/services/sync/sync_service.dart';
|
||||
import 'package:photos/ui/tabs/home_widget.dart';
|
||||
import "package:photos/ui/viewer/actions/file_viewer.dart";
|
||||
import "package:photos/utils/bg_task_utils.dart";
|
||||
import "package:photos/utils/intent_util.dart";
|
||||
import "package:photos/utils/standalone/debouncer.dart";
|
||||
|
||||
class EnteApp extends StatefulWidget {
|
||||
final Future<void> Function(String) runBackgroundTask;
|
||||
final Future<void> Function(String) killBackgroundTask;
|
||||
final AdaptiveThemeMode? savedThemeMode;
|
||||
final Locale? locale;
|
||||
|
||||
const EnteApp(
|
||||
this.runBackgroundTask,
|
||||
this.killBackgroundTask,
|
||||
this.locale,
|
||||
this.savedThemeMode, {
|
||||
super.key,
|
||||
@@ -51,9 +47,9 @@ class EnteApp extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
|
||||
final _logger = Logger("EnteAppState");
|
||||
late Locale? locale;
|
||||
late StreamSubscription<MemoriesChangedEvent> _memoriesChangedSubscription;
|
||||
final _logger = Logger("EnteAppState");
|
||||
late StreamSubscription<PeopleChangedEvent> _peopleChangedSubscription;
|
||||
late Debouncer _changeCallbackDebouncer;
|
||||
|
||||
@@ -112,7 +108,7 @@ class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
|
||||
: MediaExtentionAction(action: IntentAction.main);
|
||||
AppLifecycleService.instance.setMediaExtensionAction(mediaExtentionAction);
|
||||
if (mediaExtentionAction.action == IntentAction.main) {
|
||||
_configureBackgroundFetch();
|
||||
await BgTaskUtils.configureWorkmanager();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,29 +193,4 @@ class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
|
||||
AppLifecycleService.instance.onAppInBackground(stateChangeReason);
|
||||
}
|
||||
}
|
||||
|
||||
void _configureBackgroundFetch() {
|
||||
BackgroundFetch.configure(
|
||||
BackgroundFetchConfig(
|
||||
minimumFetchInterval: 15,
|
||||
forceAlarmManager: false,
|
||||
stopOnTerminate: false,
|
||||
startOnBoot: true,
|
||||
enableHeadless: true,
|
||||
requiresBatteryNotLow: true,
|
||||
requiresCharging: false,
|
||||
requiresStorageNotLow: false,
|
||||
requiresDeviceIdle: false,
|
||||
requiredNetworkType: NetworkType.ANY,
|
||||
), (String taskId) async {
|
||||
await widget.runBackgroundTask(taskId);
|
||||
}, (taskId) {
|
||||
_logger.info("BG task timeout taskID: $taskId");
|
||||
widget.killBackgroundTask(taskId);
|
||||
}).then((int status) {
|
||||
_logger.info('[BackgroundFetch] configure success: $status');
|
||||
}).catchError((e) {
|
||||
_logger.info('[BackgroundFetch] configure ERROR: $e');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:native_dio_adapter/native_dio_adapter.dart';
|
||||
import "package:native_dio_adapter/native_dio_adapter.dart";
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import "package:photos/core/configuration.dart";
|
||||
import "package:photos/core/event_bus.dart";
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import "package:adaptive_theme/adaptive_theme.dart";
|
||||
import 'package:background_fetch/background_fetch.dart';
|
||||
import "package:computer/computer.dart";
|
||||
import 'package:ente_crypto/ente_crypto.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
@@ -22,7 +21,6 @@ import 'package:photos/core/error-reporting/super_logging.dart';
|
||||
import 'package:photos/core/errors.dart';
|
||||
import 'package:photos/core/network/network.dart';
|
||||
import "package:photos/db/ml/db.dart";
|
||||
import 'package:photos/db/upload_locks_db.dart';
|
||||
import 'package:photos/ente_theme_data.dart';
|
||||
import "package:photos/extensions/stop_watch.dart";
|
||||
import "package:photos/l10n/l10n.dart";
|
||||
@@ -53,13 +51,12 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
final _logger = Logger("main");
|
||||
|
||||
bool _isProcessRunning = false;
|
||||
const kLastBGTaskHeartBeatTime = "bg_task_hb_time";
|
||||
const kLastFGTaskHeartBeatTime = "fg_task_hb_time";
|
||||
const kHeartBeatFrequency = Duration(seconds: 1);
|
||||
const kFGSyncFrequency = Duration(minutes: 5);
|
||||
const kFGHomeWidgetSyncFrequency = Duration(minutes: 15);
|
||||
const kBGTaskTimeout = Duration(seconds: 25);
|
||||
const kBGTaskTimeout = Duration(seconds: 28);
|
||||
const kBGPushTimeout = Duration(seconds: 28);
|
||||
const kFGTaskDeathTimeoutInMicroseconds = 5000000;
|
||||
|
||||
@@ -71,7 +68,6 @@ void main() async {
|
||||
final savedThemeMode = await AdaptiveTheme.getThemeMode();
|
||||
await _runInForeground(savedThemeMode);
|
||||
|
||||
unawaited(BackgroundFetch.registerHeadlessTask(_headlessTaskHandler));
|
||||
if (Platform.isAndroid) FlutterDisplayMode.setHighRefreshRate().ignore();
|
||||
SystemChrome.setSystemUIOverlayStyle(
|
||||
const SystemUiOverlayStyle(
|
||||
@@ -87,14 +83,13 @@ void main() async {
|
||||
}
|
||||
|
||||
Future<void> _runInForeground(AdaptiveThemeMode? savedThemeMode) async {
|
||||
return await _runWithLogs(() async {
|
||||
return await runWithLogs(() async {
|
||||
_logger.info("Starting app in foreground");
|
||||
await _init(false, via: 'mainMethod');
|
||||
final Locale? locale = await getLocale(noFallback: true);
|
||||
runApp(
|
||||
AppLock(
|
||||
builder: (args) =>
|
||||
EnteApp(_runBackgroundTask, _killBGTask, locale, savedThemeMode),
|
||||
builder: (args) => EnteApp(locale, savedThemeMode),
|
||||
lockScreen: const LockScreen(),
|
||||
enabled: await Configuration.instance.shouldShowLockScreen() ||
|
||||
localSettings.isOnGuestView(),
|
||||
@@ -115,7 +110,12 @@ ThemeMode _themeMode(AdaptiveThemeMode? savedThemeMode) {
|
||||
return ThemeMode.system;
|
||||
}
|
||||
|
||||
Future<void> _homeWidgetSync() async {
|
||||
Future<void> _homeWidgetSync([bool isBackground = false]) async {
|
||||
if (isBackground && Platform.isIOS) {
|
||||
_logger.info("Home widget sync skipped in background on iOS");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await HomeWidgetService.instance.initHomeWidget();
|
||||
} catch (e, s) {
|
||||
@@ -123,59 +123,59 @@ Future<void> _homeWidgetSync() async {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _runBackgroundTask(String taskId, {String mode = 'normal'}) async {
|
||||
if (_isProcessRunning) {
|
||||
_logger.info("Background task triggered when process was already running");
|
||||
await _sync('bgTaskActiveProcess');
|
||||
await BackgroundFetch.finish(taskId);
|
||||
} else {
|
||||
_runWithLogs(
|
||||
() async {
|
||||
_logger.info("Starting background task in $mode mode");
|
||||
// ignore: unawaited_futures
|
||||
_runInBackground(taskId);
|
||||
},
|
||||
prefix: "[bg]",
|
||||
).ignore();
|
||||
}
|
||||
Future<void> runBackgroundTask(
|
||||
String taskId,
|
||||
TimeLogger tlog, {
|
||||
String mode = 'normal',
|
||||
}) async {
|
||||
await _runMinimally(taskId, tlog);
|
||||
}
|
||||
|
||||
Future<void> _runInBackground(String taskId) async {
|
||||
await Future.delayed(const Duration(seconds: 3));
|
||||
if (await _isRunningInForeground()) {
|
||||
_logger.info("FG task running, skipping BG taskID: $taskId");
|
||||
await BackgroundFetch.finish(taskId);
|
||||
return;
|
||||
} else {
|
||||
_logger.info("FG task is not running");
|
||||
}
|
||||
_logger.info("[BackgroundFetch] Event received: $taskId");
|
||||
_scheduleBGTaskKill(taskId);
|
||||
if (Platform.isIOS) {
|
||||
_scheduleSuicide(kBGTaskTimeout, taskId); // To prevent OS from punishing us
|
||||
}
|
||||
await _init(true, via: 'runViaBackgroundTask');
|
||||
await Future.wait(
|
||||
[
|
||||
_homeWidgetSync(),
|
||||
() async {
|
||||
updateService.showUpdateNotification().ignore();
|
||||
await _sync('bgSync');
|
||||
}(),
|
||||
],
|
||||
Future<void> _runMinimally(String taskId, TimeLogger tlog) async {
|
||||
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
|
||||
await Configuration.instance.init();
|
||||
|
||||
// App LifeCycle
|
||||
AppLifecycleService.instance.init(prefs);
|
||||
AppLifecycleService.instance.onAppInBackground('init via: WorkManager $tlog');
|
||||
|
||||
// Crypto rel.
|
||||
await Computer.shared().turnOn(workersCount: 4);
|
||||
CryptoUtil.init();
|
||||
|
||||
// Init Network Utils
|
||||
await NetworkClient.instance.init(packageInfo);
|
||||
|
||||
// Global Services
|
||||
ServiceLocator.instance.init(
|
||||
prefs,
|
||||
NetworkClient.instance.enteDio,
|
||||
NetworkClient.instance.getDio(),
|
||||
packageInfo,
|
||||
);
|
||||
await BackgroundFetch.finish(taskId);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/73796478/546896
|
||||
@pragma('vm:entry-point')
|
||||
void _headlessTaskHandler(HeadlessTask task) {
|
||||
debugPrint("_headlessTaskHandler");
|
||||
if (task.timeout) {
|
||||
BackgroundFetch.finish(task.taskId);
|
||||
} else {
|
||||
_runBackgroundTask(task.taskId, mode: "headless");
|
||||
}
|
||||
await CollectionsService.instance.init(prefs);
|
||||
|
||||
// Upload & Sync Related
|
||||
await FileUploader.instance.init(prefs, true);
|
||||
LocalFileUpdateService.instance.init(prefs);
|
||||
await LocalSyncService.instance.init(prefs);
|
||||
RemoteSyncService.instance.init(prefs);
|
||||
await SyncService.instance.init(prefs);
|
||||
|
||||
// Misc Services
|
||||
await UserService.instance.init();
|
||||
NotificationService.instance.init(prefs);
|
||||
if (Platform.isAndroid) HomeWidgetService.instance.init(prefs);
|
||||
|
||||
// Begin Execution
|
||||
// only runs for android
|
||||
updateService.showUpdateNotification().ignore();
|
||||
await _sync('bgTaskActiveProcess');
|
||||
// only runs for android
|
||||
await _homeWidgetSync(true);
|
||||
}
|
||||
|
||||
Future<void> _init(bool isBackground, {String via = ''}) async {
|
||||
@@ -193,7 +193,6 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
|
||||
}
|
||||
});
|
||||
if (!isBackground) _heartBeatOnInit(0);
|
||||
_isProcessRunning = true;
|
||||
_logger.info("Initializing... inBG =$isBackground via: $via $tlog");
|
||||
final SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
@@ -263,12 +262,11 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
|
||||
}
|
||||
|
||||
if (Platform.isIOS) {
|
||||
// ignore: unawaited_futures
|
||||
PushService.instance.init().then((_) {
|
||||
FirebaseMessaging.onBackgroundMessage(
|
||||
_firebaseMessagingBackgroundHandler,
|
||||
);
|
||||
});
|
||||
}).ignore();
|
||||
}
|
||||
_logger.info("PushService/HomeWidget done $tlog");
|
||||
VideoPreviewService.instance.init(preferences);
|
||||
@@ -330,7 +328,7 @@ Future<void> _sync(String caller) async {
|
||||
}
|
||||
}
|
||||
|
||||
Future _runWithLogs(Function() function, {String prefix = ""}) async {
|
||||
Future runWithLogs(Function() function, {String prefix = ""}) async {
|
||||
await SuperLogging.main(
|
||||
LogConfig(
|
||||
body: function,
|
||||
@@ -378,17 +376,6 @@ Future<void> _scheduleFGSync(String caller) async {
|
||||
});
|
||||
}
|
||||
|
||||
void _scheduleBGTaskKill(String taskId) async {
|
||||
if (await _isRunningInForeground()) {
|
||||
_logger.info("Found app in FG, committing seppuku. $taskId");
|
||||
await _killBGTask(taskId);
|
||||
return;
|
||||
}
|
||||
Future.delayed(kHeartBeatFrequency, () async {
|
||||
_scheduleBGTaskKill(taskId);
|
||||
});
|
||||
}
|
||||
|
||||
Future<bool> _isRunningInForeground() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.reload();
|
||||
@@ -400,22 +387,10 @@ Future<bool> _isRunningInForeground() async {
|
||||
(currentTime - kFGTaskDeathTimeoutInMicroseconds);
|
||||
}
|
||||
|
||||
Future<void> _killBGTask([String? taskId]) async {
|
||||
await UploadLocksDB.instance.releaseLocksAcquiredByOwnerBefore(
|
||||
ProcessType.background.toString(),
|
||||
DateTime.now().microsecondsSinceEpoch,
|
||||
);
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(kLastBGTaskHeartBeatTime);
|
||||
if (taskId != null) {
|
||||
await BackgroundFetch.finish(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
final bool isRunningInFG = await _isRunningInForeground(); // hb
|
||||
final bool isInForeground = AppLifecycleService.instance.isForeground;
|
||||
if (_isProcessRunning) {
|
||||
if (await _isRunningInForeground()) {
|
||||
_logger.info(
|
||||
"Background push received when app is alive and runningInFS: $isRunningInFG inForeground: $isInForeground",
|
||||
);
|
||||
@@ -424,20 +399,16 @@ Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
}
|
||||
} else {
|
||||
// App is dead
|
||||
// ignore: unawaited_futures
|
||||
_runWithLogs(
|
||||
runWithLogs(
|
||||
() async {
|
||||
_logger.info("Background push received");
|
||||
if (Platform.isIOS) {
|
||||
_scheduleSuicide(kBGPushTimeout); // To prevent OS from punishing us
|
||||
}
|
||||
await _init(true, via: 'firebasePush');
|
||||
if (PushService.shouldSync(message)) {
|
||||
await _sync('firebaseBgSyncNoActiveProcess');
|
||||
}
|
||||
},
|
||||
prefix: "[fbg]",
|
||||
);
|
||||
).ignore();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,12 +421,3 @@ Future<void> _logFGHeartBeatInfo(SharedPreferences prefs) async {
|
||||
: DateTime.fromMicrosecondsSinceEpoch(lastFGTaskHeartBeatTime).toString();
|
||||
_logger.info('isAlreadyRunningFG: $isRunningInFG, last Beat: $lastRun');
|
||||
}
|
||||
|
||||
void _scheduleSuicide(Duration duration, [String? taskID]) {
|
||||
final taskIDVal = taskID ?? 'no taskID';
|
||||
_logger.warning("Schedule seppuku taskID: $taskIDVal");
|
||||
Future.delayed(duration, () {
|
||||
_logger.warning("TLE, committing seppuku for taskID: $taskIDVal");
|
||||
_killBGTask(taskID);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -236,6 +236,7 @@ class MultiPartUploader {
|
||||
options: Options(
|
||||
headers: {
|
||||
Headers.contentLengthHeader: fileSize,
|
||||
Headers.contentTypeHeader: "application/octet-stream",
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -127,12 +127,16 @@ class RemoteSyncService {
|
||||
await syncDeviceCollectionFilesForUpload();
|
||||
}
|
||||
|
||||
fileDataService.syncFDStatus().then((_) {
|
||||
if (!flagService.hasGrantedMLConsent) {
|
||||
VideoPreviewService.instance
|
||||
.queueFiles(); // Only in case ML is disabled. if ML is enabled the MLService will queue streaming when ML is done
|
||||
}
|
||||
}).ignore();
|
||||
if (
|
||||
// Only Uploading Previews in fg to prevent heating issues
|
||||
AppLifecycleService.instance.isForeground &&
|
||||
// if ML is enabled the MLService will queue when ML is done
|
||||
!flagService.hasGrantedMLConsent) {
|
||||
fileDataService.syncFDStatus().then((_) {
|
||||
VideoPreviewService.instance.queueFiles();
|
||||
}).ignore();
|
||||
}
|
||||
|
||||
final filesToBeUploaded = await _getFilesToBeUploaded();
|
||||
final hasUploadedFiles = await _uploadFiles(filesToBeUploaded);
|
||||
if (filesToBeUploaded.isNotEmpty) {
|
||||
@@ -152,8 +156,7 @@ class RemoteSyncService {
|
||||
if (hasMoreFilesToBackup && !_shouldThrottleSync()) {
|
||||
// Skipping a resync to ensure that files that were ignored in this
|
||||
// session are not processed now
|
||||
// ignore: unawaited_futures
|
||||
sync();
|
||||
await sync();
|
||||
} else {
|
||||
_logger.info("Fire backup completed event");
|
||||
Bus.instance.fire(SyncStatusUpdate(SyncStatus.completedBackup));
|
||||
@@ -175,20 +178,19 @@ class RemoteSyncService {
|
||||
} catch (e, s) {
|
||||
_existingSync?.complete();
|
||||
_existingSync = null;
|
||||
// rethrow whitelisted error so that UI status can be updated correctly.
|
||||
if (e is UnauthorizedError ||
|
||||
e is NoActiveSubscriptionError ||
|
||||
e is WiFiUnavailableError ||
|
||||
e is StorageLimitExceededError ||
|
||||
e is SyncStopRequestedError ||
|
||||
e is NoMediaLocationAccessError) {
|
||||
_logger.warning("Error executing remote sync", e, s);
|
||||
_logger.warning("Error executing remote sync", e, s);
|
||||
|
||||
if (flagService.internalUser ||
|
||||
// rethrow whitelisted error so that UI status can be updated correctly.
|
||||
{
|
||||
UnauthorizedError,
|
||||
NoActiveSubscriptionError,
|
||||
WiFiUnavailableError,
|
||||
StorageLimitExceededError,
|
||||
SyncStopRequestedError,
|
||||
NoMediaLocationAccessError,
|
||||
}.contains(e.runtimeType)) {
|
||||
rethrow;
|
||||
} else {
|
||||
_logger.severe("Error executing remote sync ", e, s);
|
||||
if (flagService.internalUser) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
_isExistingSyncSilent = false;
|
||||
@@ -602,6 +604,22 @@ class RemoteSyncService {
|
||||
await _uploader.fetchUploadURLs(toBeUploaded);
|
||||
}
|
||||
final List<Future> futures = [];
|
||||
|
||||
for (final file in filesToBeUploaded) {
|
||||
if (_shouldThrottleSync() &&
|
||||
futures.length >= kMaximumPermissibleUploadsInThrottledMode) {
|
||||
_logger.info("Skipping some new files as we are throttling uploads");
|
||||
break;
|
||||
}
|
||||
// prefer existing collection ID for manually uploaded files.
|
||||
// See https://github.com/ente-io/photos-app/pull/187
|
||||
final collectionID = file.collectionID ??
|
||||
(await _collectionsService
|
||||
.getOrCreateForPath(file.deviceFolder ?? 'Unknown Folder'))
|
||||
.id;
|
||||
_uploadFile(file, collectionID, futures);
|
||||
}
|
||||
|
||||
for (final uploadedFileID in updatedFileIDs) {
|
||||
if (_shouldThrottleSync() &&
|
||||
futures.length >= kMaximumPermissibleUploadsInThrottledMode) {
|
||||
@@ -633,21 +651,6 @@ class RemoteSyncService {
|
||||
}
|
||||
}
|
||||
|
||||
for (final file in filesToBeUploaded) {
|
||||
if (_shouldThrottleSync() &&
|
||||
futures.length >= kMaximumPermissibleUploadsInThrottledMode) {
|
||||
_logger.info("Skipping some new files as we are throttling uploads");
|
||||
break;
|
||||
}
|
||||
// prefer existing collection ID for manually uploaded files.
|
||||
// See https://github.com/ente-io/photos-app/pull/187
|
||||
final collectionID = file.collectionID ??
|
||||
(await _collectionsService
|
||||
.getOrCreateForPath(file.deviceFolder ?? 'Unknown Folder'))
|
||||
.id;
|
||||
_uploadFile(file, collectionID, futures);
|
||||
}
|
||||
|
||||
try {
|
||||
await Future.wait(futures);
|
||||
} on InvalidFileError {
|
||||
@@ -933,26 +936,24 @@ class RemoteSyncService {
|
||||
}
|
||||
|
||||
bool _shouldThrottleSync() {
|
||||
return Platform.isIOS && !AppLifecycleService.instance.isForeground;
|
||||
return !flagService.enableMobMultiPart ||
|
||||
!localSettings.userEnabledMultiplePart;
|
||||
}
|
||||
|
||||
// _sortByTime sort by creation time (desc).
|
||||
// This is done to upload most recent photo first.
|
||||
void _sortByTime(List<EnteFile> file) {
|
||||
file.sort((first, second) {
|
||||
// 1. fileType: move videos to end when in bg
|
||||
if (!AppLifecycleService.instance.isForeground &&
|
||||
first.fileType != second.fileType) {
|
||||
if (first.fileType == FileType.video) return 1;
|
||||
if (second.fileType == FileType.video) return -1;
|
||||
}
|
||||
|
||||
// 2. creationTime descending
|
||||
return second.creationTime!.compareTo(first.creationTime!);
|
||||
});
|
||||
// move updated files towards the end
|
||||
file.sort((first, second) {
|
||||
if (first.updationTime == second.updationTime) {
|
||||
return 0;
|
||||
}
|
||||
if (first.updationTime == -1) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool _shouldShowNotification(int collectionID) {
|
||||
|
||||
106
mobile/lib/utils/bg_task_utils.dart
Normal file
106
mobile/lib/utils/bg_task_utils.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
import "dart:io";
|
||||
|
||||
import "package:logging/logging.dart";
|
||||
import "package:permission_handler/permission_handler.dart";
|
||||
import "package:photos/db/upload_locks_db.dart";
|
||||
import "package:photos/extensions/stop_watch.dart";
|
||||
import "package:photos/main.dart";
|
||||
import "package:photos/utils/file_uploader.dart";
|
||||
import "package:shared_preferences/shared_preferences.dart";
|
||||
import "package:workmanager/workmanager.dart" as workmanager;
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void callbackDispatcher() {
|
||||
workmanager.Workmanager().executeTask((taskName, inputData) async {
|
||||
final TimeLogger tlog = TimeLogger();
|
||||
Future<bool> result = Future.error("Task didn't run");
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
await runWithLogs(
|
||||
() async {
|
||||
try {
|
||||
BgTaskUtils.$.info('Task started $tlog');
|
||||
await runBackgroundTask(taskName, tlog).timeout(
|
||||
Platform.isIOS ? kBGTaskTimeout : const Duration(hours: 1),
|
||||
onTimeout: () async {
|
||||
BgTaskUtils.$.warning(
|
||||
"TLE, committing seppuku for taskID: $taskName",
|
||||
);
|
||||
await BgTaskUtils.releaseResourcesForKill(taskName, prefs);
|
||||
},
|
||||
);
|
||||
BgTaskUtils.$.info('Task run successful $tlog');
|
||||
result = Future.value(true);
|
||||
} catch (e) {
|
||||
BgTaskUtils.$.warning('Task error: $e');
|
||||
await BgTaskUtils.releaseResourcesForKill(taskName, prefs);
|
||||
result = Future.error(e.toString());
|
||||
}
|
||||
},
|
||||
prefix: "[bg]",
|
||||
).onError((_, __) {
|
||||
result = Future.error("Didn't finished correctly!");
|
||||
return;
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
class BgTaskUtils {
|
||||
static final $ = Logger("BgTaskUtils");
|
||||
|
||||
static Future<void> releaseResourcesForKill(
|
||||
String taskId,
|
||||
SharedPreferences prefs,
|
||||
) async {
|
||||
await UploadLocksDB.instance.releaseLocksAcquiredByOwnerBefore(
|
||||
ProcessType.background.toString(),
|
||||
DateTime.now().microsecondsSinceEpoch,
|
||||
);
|
||||
await prefs.remove(kLastBGTaskHeartBeatTime);
|
||||
}
|
||||
|
||||
static Future configureWorkmanager() async {
|
||||
if (Platform.isIOS) {
|
||||
final status = await Permission.backgroundRefresh.status;
|
||||
if (status != PermissionStatus.granted) {
|
||||
$.warning(
|
||||
"Background refresh permission is not granted. Please grant it to start the background service.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
$.warning("Configuring Work Manager for background tasks");
|
||||
const iOSBackgroundAppRefresh = "io.ente.frame.iOSBackgroundAppRefresh";
|
||||
const androidPeriodicTask = "io.ente.photos.androidPeriodicTask";
|
||||
final backgroundTaskIdentifier =
|
||||
Platform.isIOS ? iOSBackgroundAppRefresh : androidPeriodicTask;
|
||||
try {
|
||||
await workmanager.Workmanager().initialize(
|
||||
callbackDispatcher,
|
||||
isInDebugMode: false,
|
||||
);
|
||||
await workmanager.Workmanager().registerPeriodicTask(
|
||||
backgroundTaskIdentifier,
|
||||
backgroundTaskIdentifier,
|
||||
frequency: Platform.isIOS
|
||||
? const Duration(minutes: 30)
|
||||
: const Duration(minutes: 15),
|
||||
initialDelay: const Duration(minutes: 10),
|
||||
constraints: workmanager.Constraints(
|
||||
networkType: workmanager.NetworkType.connected,
|
||||
requiresCharging: false,
|
||||
requiresStorageNotLow: false,
|
||||
requiresDeviceIdle: false,
|
||||
),
|
||||
existingWorkPolicy: workmanager.ExistingWorkPolicy.append,
|
||||
backoffPolicy: workmanager.BackoffPolicy.linear,
|
||||
backoffPolicyDelay: const Duration(minutes: 15),
|
||||
);
|
||||
$.info("WorkManager configured");
|
||||
} catch (e) {
|
||||
$.warning("Failed to configure WorkManager: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
|
||||
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "72.0.0"
|
||||
version: "76.0.0"
|
||||
_flutterfire_internals:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -21,7 +21,7 @@ packages:
|
||||
dependency: transitive
|
||||
description: dart
|
||||
source: sdk
|
||||
version: "0.3.2"
|
||||
version: "0.3.3"
|
||||
adaptive_theme:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -34,10 +34,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
|
||||
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.7.0"
|
||||
version: "6.11.0"
|
||||
android_intent_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -127,21 +127,13 @@ packages:
|
||||
source: hosted
|
||||
version: "1.5.8"
|
||||
async:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: async
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
background_fetch:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: background_fetch
|
||||
sha256: e9f26ae54d88310b7ac2a68f2f9fcee0081a4d5f11100f233a70702021e7ac4f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.7"
|
||||
battery_info:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -325,10 +317,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
version: "1.19.0"
|
||||
computer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1424,18 +1416,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
|
||||
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.5"
|
||||
version: "10.0.7"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
|
||||
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.5"
|
||||
version: "3.0.8"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1544,10 +1536,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: macros
|
||||
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
|
||||
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.2-main.4"
|
||||
version: "0.1.3-main.0"
|
||||
maps_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -2197,18 +2189,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry
|
||||
sha256: "077b03f9ee44cfb1eaadbf8af58255e670de62b3f240ca154ce96a5591dc3885"
|
||||
sha256: "599701ca0693a74da361bc780b0752e1abc98226cf5095f6b069648116c896bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.14.1"
|
||||
version: "8.14.2"
|
||||
sentry_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry_flutter
|
||||
sha256: a348e2a365a8ad7682dd09db54f50f19f1c87180b8278f088bc393c511aea5e0
|
||||
sha256: "5ba2cf40646a77d113b37a07bd69f61bb3ec8a73cbabe5537b05a7c89d2656f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.14.1"
|
||||
version: "8.14.2"
|
||||
share_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -2317,7 +2309,7 @@ packages:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
version: "0.0.0"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -2442,10 +2434,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
version: "1.12.0"
|
||||
step_progress_indicator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -2474,10 +2466,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
styled_text:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -2538,26 +2530,26 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e"
|
||||
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.25.7"
|
||||
version: "1.25.8"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.2"
|
||||
version: "0.7.3"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696"
|
||||
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.4"
|
||||
version: "0.6.5"
|
||||
thermal:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -2821,10 +2813,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
|
||||
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.2.5"
|
||||
version: "14.3.0"
|
||||
volume_controller:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -2885,10 +2877,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webdriver
|
||||
sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
|
||||
sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "3.0.4"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -2945,6 +2937,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
workmanager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: workmanager
|
||||
sha256: f3c3ce6d79cce53eee4a29dd2e8328c25db5ba5d9062fcc5e8f3c71e0af9b7e4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -12,7 +12,7 @@ description: ente photos application
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
|
||||
version: 1.1.01+1054
|
||||
version: 1.1.1+1054
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
@@ -24,7 +24,7 @@ dependencies:
|
||||
animated_list_plus: ^0.5.2
|
||||
app_links: ^6.4.0
|
||||
archive: ^3.6.1
|
||||
background_fetch: ^1.3.7
|
||||
async: ^2.11.0
|
||||
battery_info: # replace with battery_plus
|
||||
git:
|
||||
url: https://github.com/ente-io/battery_info
|
||||
@@ -212,6 +212,7 @@ dependencies:
|
||||
wakelock_plus: ^1.1.1
|
||||
wechat_assets_picker: ^9.5.1
|
||||
widgets_to_image: ^0.0.2
|
||||
workmanager: ^0.6.0
|
||||
xml: ^6.3.0
|
||||
|
||||
dependency_overrides:
|
||||
|
||||
Reference in New Issue
Block a user