mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-08-13 10:28:10 +02:00
Try less messy bg update method
This commit is contained in:
161
lib/main.dart
161
lib/main.dart
@@ -86,6 +86,24 @@ moveStrToEnd(List<String> arr, String str, {String? strB}) {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Background updater function
|
||||||
|
///
|
||||||
|
/// @param List<String>? toCheck: The appIds to check for updates (default to all apps sorted by last update check time)
|
||||||
|
///
|
||||||
|
/// @param List<String>? toInstall: The appIds to attempt to update (defaults to an empty array)
|
||||||
|
///
|
||||||
|
/// @param int? attemptCount: The number of times the function has failed up to this point (defaults to 0)
|
||||||
|
///
|
||||||
|
/// When toCheck is empty, the function is in "install mode" (else it is in "update mode").
|
||||||
|
/// In update mode, all apps in toCheck are checked for updates.
|
||||||
|
/// If an update is available, the appId is either added to toInstall (if a background update is possible) or the user is notified.
|
||||||
|
/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries.
|
||||||
|
///
|
||||||
|
/// Once all update checks are complete, the function is called again in install mode.
|
||||||
|
/// In this mode, all apps in toInstall are downloaded and installed in the background (install result is unknown).
|
||||||
|
/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries.
|
||||||
|
///
|
||||||
|
/// In either mode, if the function fails after the maximum number of tries, the user is notified.
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
|
Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@@ -106,71 +124,104 @@ Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
|
|||||||
if (params['toCheck'] == null) {
|
if (params['toCheck'] == null) {
|
||||||
settingsProvider.lastBGCheckTime = DateTime.now();
|
settingsProvider.lastBGCheckTime = DateTime.now();
|
||||||
}
|
}
|
||||||
params['attemptCount'] = (params['attemptCount'] ?? 0) + 1;
|
int attemptCount = (params['attemptCount'] ?? 0) + 1;
|
||||||
params['toCheck'] =
|
List<String> toCheck = <String>[
|
||||||
params['toCheck'] ?? appsProvider.getAppsSortedByUpdateCheckTime();
|
...(params['toCheck'] ?? appsProvider.getAppsSortedByUpdateCheckTime())
|
||||||
params['toInstall'] = params['toInstall'] ?? (<String>[]);
|
];
|
||||||
|
List<String> toInstall = <String>[...(params['toInstall'] ?? (<String>[]))];
|
||||||
|
|
||||||
List<String> toCheck = <String>[...params['toCheck']];
|
bool installMode = toCheck.isEmpty && toInstall.isNotEmpty;
|
||||||
List<String> toInstall = <String>[...params['toInstall']];
|
|
||||||
|
|
||||||
logs.add(
|
logs.add(
|
||||||
'BG update task $taskId: Started [${toCheck.length},${toInstall.length}]${params['attemptCount'] > 1 ? '. ${params['attemptCount'] - 1} consecutive fail(s)' : ''}.');
|
'BG update task $taskId: Started in ${installMode ? 'install' : 'update'} mode${attemptCount > 1 ? '. ${attemptCount - 1} consecutive fail(s)' : ''}.');
|
||||||
|
|
||||||
if (toCheck.isNotEmpty) {
|
if (!installMode) {
|
||||||
String appId = toCheck.removeAt(0);
|
var didCompleteChecking = false;
|
||||||
AppInMemory? app = appsProvider.apps[appId];
|
for (int i = 0; i < toCheck.length; i++) {
|
||||||
if (app?.app.installedVersion != null) {
|
var appId = toCheck[i];
|
||||||
try {
|
AppInMemory? app = appsProvider.apps[appId];
|
||||||
notificationsProvider.notify(checkingUpdatesNotification,
|
if (app?.app.installedVersion != null) {
|
||||||
cancelExisting: true);
|
try {
|
||||||
App? newApp = await appsProvider.checkUpdate(appId);
|
logs.add('BG update task $taskId: Checking for updates for $appId.');
|
||||||
if (newApp != null) {
|
notificationsProvider.notify(checkingUpdatesNotification,
|
||||||
if (!(await appsProvider.canInstallSilently(app!.app))) {
|
cancelExisting: true);
|
||||||
notificationsProvider.notify(
|
App? newApp = await appsProvider.checkUpdate(appId);
|
||||||
UpdateNotification([newApp], id: newApp.id.hashCode - 1));
|
if (newApp != null) {
|
||||||
} else {
|
if (!(await appsProvider.canInstallSilently(app!.app))) {
|
||||||
toInstall.add(appId);
|
notificationsProvider.notify(
|
||||||
|
UpdateNotification([newApp], id: newApp.id.hashCode - 1));
|
||||||
|
} else {
|
||||||
|
toInstall.add(appId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (i == (toCheck.length - 1)) {
|
||||||
} catch (e) {
|
didCompleteChecking = true;
|
||||||
logs.add(
|
}
|
||||||
'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.');
|
} catch (e) {
|
||||||
if (e is RateLimitError ||
|
|
||||||
e is ClientException && params['attemptCount'] < maxAttempts) {
|
|
||||||
var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15;
|
|
||||||
logs.add(
|
logs.add(
|
||||||
'BG update task $taskId: Next task will start in $remainingMinutes minutes (with $appId moved to the end of the line).');
|
'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.');
|
||||||
toCheck = toInstall = []; // So the next task will not start
|
if (attemptCount < maxAttempts) {
|
||||||
params['toCheck'] = moveStrToEnd(params['toCheck'], appId);
|
var remainingSeconds = e is RateLimitError
|
||||||
AndroidAlarmManager.oneShot(
|
? (e.remainingMinutes * 60)
|
||||||
Duration(minutes: remainingMinutes), taskId + 1, bgUpdateCheck,
|
: e is ClientException
|
||||||
params: params);
|
? (15 * 60)
|
||||||
} else {
|
: 1;
|
||||||
rethrow;
|
logs.add(
|
||||||
|
'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).');
|
||||||
|
var remainingToCheck = moveStrToEnd(toCheck.sublist(i), appId);
|
||||||
|
AndroidAlarmManager.oneShot(
|
||||||
|
Duration(seconds: remainingSeconds), taskId, bgUpdateCheck,
|
||||||
|
params: {
|
||||||
|
'toCheck': remainingToCheck,
|
||||||
|
'toInstall': toInstall,
|
||||||
|
'attemptCount': attemptCount
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
notificationsProvider
|
||||||
|
.notify(ErrorCheckingUpdatesNotification(e.toString()));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
notificationsProvider.cancel(checkingUpdatesNotification.id);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
notificationsProvider.cancel(checkingUpdatesNotification.id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (toInstall.isNotEmpty) {
|
if (didCompleteChecking && toInstall.isNotEmpty) {
|
||||||
toInstall = moveStrToEnd(toInstall, obtainiumId);
|
AndroidAlarmManager.oneShot(
|
||||||
String appId = toInstall.removeAt(0);
|
const Duration(minutes: 0), taskId + 1, bgUpdateCheck,
|
||||||
logs.add(
|
params: {'toCheck': [], 'toInstall': toInstall});
|
||||||
'BG update task $taskId: Attempting to download $appId in the background.');
|
}
|
||||||
await appsProvider.downloadAndInstallLatestApps([appId], null,
|
|
||||||
notificationsProvider: notificationsProvider);
|
|
||||||
logs.add(
|
|
||||||
'BG update task $taskId: Attempting to update $appId in the background.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toCheck.isNotEmpty || toInstall.isNotEmpty) {
|
|
||||||
logs.add('BG update task $taskId: Ended. Next task will start soon.');
|
|
||||||
AndroidAlarmManager.oneShot(
|
|
||||||
const Duration(seconds: 0), taskId + 1, bgUpdateCheck,
|
|
||||||
params: {'toCheck': toCheck, 'toInstall': toInstall});
|
|
||||||
} else {
|
} else {
|
||||||
logs.add('BG update task $taskId: Ended.');
|
toInstall = moveStrToEnd(toInstall, obtainiumId);
|
||||||
|
for (var i = 0; i < toInstall.length; i++) {
|
||||||
|
String appId = toInstall[i];
|
||||||
|
try {
|
||||||
|
logs.add(
|
||||||
|
'BG update task $taskId: Attempting to update $appId in the background.');
|
||||||
|
await appsProvider.downloadAndInstallLatestApps([appId], null,
|
||||||
|
notificationsProvider: notificationsProvider);
|
||||||
|
} catch (e) {
|
||||||
|
logs.add(
|
||||||
|
'BG update task $taskId: Got error on updating $appId \'${e.toString()}\'.');
|
||||||
|
if (attemptCount < maxAttempts) {
|
||||||
|
var remainingSeconds = 1;
|
||||||
|
logs.add(
|
||||||
|
'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).');
|
||||||
|
var remainingToInstall = moveStrToEnd(toInstall.sublist(i), appId);
|
||||||
|
AndroidAlarmManager.oneShot(
|
||||||
|
Duration(seconds: remainingSeconds), taskId, bgUpdateCheck,
|
||||||
|
params: {
|
||||||
|
'toCheck': toCheck,
|
||||||
|
'toInstall': remainingToInstall,
|
||||||
|
'attemptCount': attemptCount
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
notificationsProvider
|
||||||
|
.notify(ErrorCheckingUpdatesNotification(e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user