mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-30 12:30:16 +02:00
More work on silent updates (not working in BG)
This commit is contained in:
@@ -26,9 +26,23 @@ void bgTaskCallback() {
|
||||
await notificationsProvider
|
||||
.cancel(ErrorCheckingUpdatesNotification('').id);
|
||||
await appsProvider.loadApps();
|
||||
List<App> updates = await appsProvider.checkUpdates();
|
||||
if (updates.isNotEmpty) {
|
||||
notificationsProvider.notify(UpdateNotification(updates),
|
||||
// List<String> existingUpdateIds = // TODO: Uncomment this and below when it works
|
||||
// appsProvider.getExistingUpdates(installedOnly: true);
|
||||
List<App> newUpdates = await appsProvider.checkUpdates();
|
||||
// List<String> silentlyUpdated = await appsProvider
|
||||
// .downloadAndInstallLatestApp(
|
||||
// [...newUpdates.map((e) => e.id), ...existingUpdateIds], null);
|
||||
// if (silentlyUpdated.isNotEmpty) {
|
||||
// newUpdates
|
||||
// .where((element) => !silentlyUpdated.contains(element.id))
|
||||
// .toList();
|
||||
// notificationsProvider.notify(
|
||||
// SilentUpdateNotification(
|
||||
// silentlyUpdated.map((e) => appsProvider.apps[e]!.app).toList()),
|
||||
// cancelExisting: true);
|
||||
// }
|
||||
if (newUpdates.isNotEmpty) {
|
||||
notificationsProvider.notify(UpdateNotification(newUpdates),
|
||||
cancelExisting: true);
|
||||
}
|
||||
return Future.value(true);
|
||||
@@ -85,7 +99,7 @@ class MyApp extends StatelessWidget {
|
||||
if (settingsProvider.updateInterval > 0) {
|
||||
Workmanager().registerPeriodicTask('bg-update-check', 'bg-update-check',
|
||||
frequency: Duration(minutes: settingsProvider.updateInterval),
|
||||
initialDelay: Duration(minutes: settingsProvider.updateInterval),
|
||||
// initialDelay: Duration(minutes: settingsProvider.updateInterval),
|
||||
constraints: Constraints(networkType: NetworkType.connected),
|
||||
existingWorkPolicy: ExistingWorkPolicy.replace);
|
||||
} else {
|
||||
|
@@ -25,8 +25,8 @@ class _AppPageState extends State<AppPage> {
|
||||
var sourceProvider = SourceProvider();
|
||||
AppInMemory? app = appsProvider.apps[widget.appId];
|
||||
var source = app != null ? sourceProvider.getSource(app.app.url) : null;
|
||||
if (!appsProvider.areDownloadsRunning()) {
|
||||
appsProvider.getUpdate(app!.app.id).catchError((e) {
|
||||
if (!appsProvider.areDownloadsRunning() && app != null) {
|
||||
appsProvider.getUpdate(app.app.id).catchError((e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(e.toString())),
|
||||
);
|
||||
@@ -221,7 +221,7 @@ class _AppPageState extends State<AppPage> {
|
||||
.downloadAndInstallLatestApp(
|
||||
[app!.app.id],
|
||||
context).then((res) {
|
||||
if (res && mounted) {
|
||||
if (res.isNotEmpty && mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
});
|
||||
|
@@ -98,6 +98,7 @@ class AppsProvider with ChangeNotifier {
|
||||
.isNotEmpty;
|
||||
|
||||
Future<bool> canInstallSilently(App app) async {
|
||||
// TODO: This is unreliable - try to get from OS
|
||||
var osInfo = await DeviceInfoPlugin().androidInfo;
|
||||
return app.installedVersion != null &&
|
||||
osInfo.version.sdkInt! >= 30 &&
|
||||
@@ -131,19 +132,20 @@ class AppsProvider with ChangeNotifier {
|
||||
|
||||
// Given a list of AppIds, uses stored info about the apps to download APKs and install them
|
||||
// If the APKs can be installed silently, they are
|
||||
// If no BuildContext is provided, apps that require user interaction are ignored
|
||||
// If user input is needed and the App is in the background, a notification is sent to get the user's attention
|
||||
// Returns upon successful download, regardless of installation result
|
||||
Future<bool> downloadAndInstallLatestApp(
|
||||
List<String> appIds, BuildContext context) async {
|
||||
// Returns an array of Ids for Apps that were successfully downloaded, regardless of installation result
|
||||
Future<List<String>> downloadAndInstallLatestApp(
|
||||
List<String> appIds, BuildContext? context) async {
|
||||
Map<String, String> appsToInstall = {};
|
||||
for (var id in appIds) {
|
||||
if (apps[id] == null) {
|
||||
throw 'App not found';
|
||||
}
|
||||
|
||||
// If the App has more than one APK, the user should pick one
|
||||
// If the App has more than one APK, the user should pick one (if context provided)
|
||||
String? apkUrl = apps[id]!.app.apkUrls[apps[id]!.app.preferredApkIndex];
|
||||
if (apps[id]!.app.apkUrls.length > 1) {
|
||||
if (apps[id]!.app.apkUrls.length > 1 && context != null) {
|
||||
// ignore: use_build_context_synchronously
|
||||
await askUserToReturnToForeground(context);
|
||||
apkUrl = await showDialog(
|
||||
@@ -152,9 +154,10 @@ class AppsProvider with ChangeNotifier {
|
||||
return APKPicker(app: apps[id]!.app, initVal: apkUrl);
|
||||
});
|
||||
}
|
||||
// If the picked APK comes from an origin different from the source, get user confirmation
|
||||
// If the picked APK comes from an origin different from the source, get user confirmation (if context provided)
|
||||
if (apkUrl != null &&
|
||||
Uri.parse(apkUrl).origin != Uri.parse(apps[id]!.app.url).origin) {
|
||||
Uri.parse(apkUrl).origin != Uri.parse(apps[id]!.app.url).origin &&
|
||||
context != null) {
|
||||
// ignore: use_build_context_synchronously
|
||||
await askUserToReturnToForeground(context);
|
||||
if (await showDialog(
|
||||
@@ -173,7 +176,11 @@ class AppsProvider with ChangeNotifier {
|
||||
apps[id]!.app.preferredApkIndex = urlInd;
|
||||
await saveApp(apps[id]!.app);
|
||||
}
|
||||
appsToInstall.putIfAbsent(id, () => apkUrl!);
|
||||
if (context != null ||
|
||||
(await canInstallSilently(apps[id]!.app) &&
|
||||
apps[id]!.app.apkUrls.length == 1)) {
|
||||
appsToInstall.putIfAbsent(id, () => apkUrl!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,13 +202,15 @@ class AppsProvider with ChangeNotifier {
|
||||
await installApk(u);
|
||||
}
|
||||
|
||||
for (var i in regularInstalls) {
|
||||
// ignore: use_build_context_synchronously
|
||||
await askUserToReturnToForeground(context);
|
||||
await installApk(i);
|
||||
if (context != null) {
|
||||
for (var i in regularInstalls) {
|
||||
// ignore: use_build_context_synchronously
|
||||
await askUserToReturnToForeground(context);
|
||||
await installApk(i);
|
||||
}
|
||||
}
|
||||
|
||||
return downloadedFiles.isNotEmpty;
|
||||
return downloadedFiles.map((e) => e.appId).toList();
|
||||
}
|
||||
|
||||
Future<Directory> getAppsDir() async {
|
||||
@@ -300,12 +309,13 @@ class AppsProvider with ChangeNotifier {
|
||||
return updates;
|
||||
}
|
||||
|
||||
List<String> getExistingUpdates() {
|
||||
List<String> getExistingUpdates({bool installedOnly = false}) {
|
||||
List<String> updateAppIds = [];
|
||||
List<String> appIds = apps.keys.toList();
|
||||
for (int i = 0; i < appIds.length; i++) {
|
||||
App? app = apps[appIds[i]]!.app;
|
||||
if (app.installedVersion != app.latestVersion) {
|
||||
if (app.installedVersion != app.latestVersion &&
|
||||
(app.installedVersion != null || !installedOnly)) {
|
||||
updateAppIds.add(app.id);
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,22 @@ class UpdateNotification extends ObtainiumNotification {
|
||||
}
|
||||
}
|
||||
|
||||
class SilentUpdateNotification extends ObtainiumNotification {
|
||||
SilentUpdateNotification(List<App> updates)
|
||||
: super(
|
||||
3,
|
||||
'Apps Updated',
|
||||
'',
|
||||
'APPS_UPDATED',
|
||||
'Apps Updated',
|
||||
'Notifies the user that updates to one or more Apps were applied in the background',
|
||||
Importance.defaultImportance) {
|
||||
message = updates.length == 1
|
||||
? '${updates[0].name} was updated to ${updates[0].latestVersion}.'
|
||||
: '${(updates.length == 2 ? '${updates[0].name} and ${updates[1].name}' : '${updates[0].name} and ${updates.length - 1} more apps')} were updated.';
|
||||
}
|
||||
}
|
||||
|
||||
class ErrorCheckingUpdatesNotification extends ObtainiumNotification {
|
||||
ErrorCheckingUpdatesNotification(String error)
|
||||
: super(
|
||||
|
20
pubspec.lock
20
pubspec.lock
@@ -7,7 +7,7 @@ packages:
|
||||
name: animations
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
version: "2.0.5"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -175,7 +175,7 @@ packages:
|
||||
name: file_picker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
version: "5.2.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -215,7 +215,7 @@ packages:
|
||||
name: flutter_local_notifications
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "10.0.0"
|
||||
version: "11.0.1"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -295,7 +295,7 @@ packages:
|
||||
name: json_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.6.0"
|
||||
version: "4.7.0"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -393,7 +393,7 @@ packages:
|
||||
name: permission_handler
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "10.0.0"
|
||||
version: "10.0.1"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -414,7 +414,7 @@ packages:
|
||||
name: permission_handler_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.7.0"
|
||||
version: "3.7.1"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -538,7 +538,7 @@ packages:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.1"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -566,7 +566,7 @@ packages:
|
||||
name: timezone
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
version: "0.9.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -636,7 +636,7 @@ packages:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.1.4"
|
||||
webview_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -650,7 +650,7 @@ packages:
|
||||
name: webview_flutter_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.10.1"
|
||||
version: "2.10.2"
|
||||
webview_flutter_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@@ -38,7 +38,7 @@ dependencies:
|
||||
cupertino_icons: ^1.0.5
|
||||
path_provider: ^2.0.11
|
||||
flutter_fgbg: ^0.2.0 # Try removing reliance on this
|
||||
flutter_local_notifications: ^10.0.0
|
||||
flutter_local_notifications: ^11.0.1
|
||||
provider: ^6.0.3
|
||||
http: ^0.13.5
|
||||
webview_flutter: ^3.0.4
|
||||
|
Reference in New Issue
Block a user