mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-10-31 13:33:28 +01: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