mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-03 14:53:28 +01:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			e8f9159571
			...
			foreground
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2c6e95f902 | ||
| 
						 | 
					7dbf3ac102 | 
							
								
								
									
										2
									
								
								.flutter
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								.flutter
									
									
									
									
									
								
							 Submodule .flutter updated: 6fba2447e9...fcf2c11572
									
								
							@@ -61,6 +61,13 @@
 | 
			
		||||
            android:enabled="true"
 | 
			
		||||
            android:exported="true"
 | 
			
		||||
            android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" />
 | 
			
		||||
        <service 
 | 
			
		||||
            android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
 | 
			
		||||
            android:foregroundServiceType="specialUse"
 | 
			
		||||
            android:exported="false" />
 | 
			
		||||
        <meta-data
 | 
			
		||||
            android:name="dev.imranr.obtainium.service.NOTIFICATION_ICON"
 | 
			
		||||
            android:resource="@drawable/ic_notification" />
 | 
			
		||||
    </application>
 | 
			
		||||
    <uses-permission android:name="android.permission.INTERNET" />
 | 
			
		||||
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
 | 
			
		||||
@@ -74,6 +81,8 @@
 | 
			
		||||
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
 | 
			
		||||
        android:maxSdkVersion="29" />
 | 
			
		||||
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
 | 
			
		||||
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 | 
			
		||||
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
 | 
			
		||||
    <!-- Required to query activities that can process text, see:
 | 
			
		||||
         https://developer.android.com/training/package-visibility and
 | 
			
		||||
         https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-hdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-hdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 965 B  | 
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-mdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-mdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 843 B  | 
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-xhdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-xhdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-xxhdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-xxhdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-xxxhdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable-xxxhdpi/ic_notification.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.0 KiB  | 
@@ -330,6 +330,8 @@
 | 
			
		||||
    "documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions and other resources that will help you understand how to use the app.",
 | 
			
		||||
    "batteryOptimizationNote": "Note that background downloads may work more reliably if you disable OS battery optimizations for Obtainium.",
 | 
			
		||||
    "fileDeletionError": "Failed to delete file (try deleting it manually then try again): \"{}\"",
 | 
			
		||||
    "foregroundService": "Obtainium foreground service",
 | 
			
		||||
    "fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Remove app?",
 | 
			
		||||
        "other": "Remove apps?"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										147
									
								
								lib/main.dart
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								lib/main.dart
									
									
									
									
									
								
							@@ -9,16 +9,15 @@ import 'package:obtainium/providers/native_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/notifications_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/settings_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
import 'package:permission_handler/permission_handler.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
import 'package:dynamic_color/dynamic_color.dart';
 | 
			
		||||
import 'package:device_info_plus/device_info_plus.dart';
 | 
			
		||||
import 'package:background_fetch/background_fetch.dart';
 | 
			
		||||
import 'package:easy_localization/easy_localization.dart';
 | 
			
		||||
// ignore: implementation_imports
 | 
			
		||||
import 'package:easy_localization/src/easy_localization_controller.dart';
 | 
			
		||||
// ignore: implementation_imports
 | 
			
		||||
import 'package:easy_localization/src/localization.dart';
 | 
			
		||||
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
 | 
			
		||||
 | 
			
		||||
List<MapEntry<Locale, String>> supportedLocales = const [
 | 
			
		||||
  MapEntry(Locale('en'), 'English'),
 | 
			
		||||
@@ -86,16 +85,31 @@ Future<void> loadTranslations() async {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@pragma('vm:entry-point')
 | 
			
		||||
void backgroundFetchHeadlessTask(HeadlessTask task) async {
 | 
			
		||||
  String taskId = task.taskId;
 | 
			
		||||
  bool isTimeout = task.timeout;
 | 
			
		||||
  if (isTimeout) {
 | 
			
		||||
    print('BG update task timed out.');
 | 
			
		||||
    BackgroundFetch.finish(taskId);
 | 
			
		||||
    return;
 | 
			
		||||
void startCallback() {
 | 
			
		||||
  FlutterForegroundTask.setTaskHandler(MyTaskHandler());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class MyTaskHandler extends TaskHandler {
 | 
			
		||||
  static const String incrementCountCommand = 'incrementCount';
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Future<void> onStart(DateTime timestamp, TaskStarter starter) async {
 | 
			
		||||
    print('onStart(starter: ${starter.name})');
 | 
			
		||||
    bgUpdateCheck('bg_check', null);
 | 
			
		||||
  }
 | 
			
		||||
  await bgUpdateCheck(taskId, null);
 | 
			
		||||
  BackgroundFetch.finish(taskId);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void onRepeatEvent(DateTime timestamp) {
 | 
			
		||||
    bgUpdateCheck('bg_check', null);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Future<void> onDestroy(DateTime timestamp, bool isTimeout) async {
 | 
			
		||||
    print('Foreground service onDestroy(isTimeout: $isTimeout)');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void onReceiveData(Object data) {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void main() async {
 | 
			
		||||
@@ -119,6 +133,7 @@ void main() async {
 | 
			
		||||
  }
 | 
			
		||||
  final np = NotificationsProvider();
 | 
			
		||||
  await np.initialize();
 | 
			
		||||
  FlutterForegroundTask.initCommunicationPort();
 | 
			
		||||
  runApp(
 | 
			
		||||
    MultiProvider(
 | 
			
		||||
      providers: [
 | 
			
		||||
@@ -136,7 +151,6 @@ void main() async {
 | 
			
		||||
      ),
 | 
			
		||||
    ),
 | 
			
		||||
  );
 | 
			
		||||
  BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Obtainium extends StatefulWidget {
 | 
			
		||||
@@ -152,32 +166,81 @@ class _ObtainiumState extends State<Obtainium> {
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    super.initState();
 | 
			
		||||
    initPlatformState();
 | 
			
		||||
    // FlutterForegroundTask.addTaskDataCallback(onReceiveForegroundServiceData);
 | 
			
		||||
    WidgetsBinding.instance.addPostFrameCallback((_) {
 | 
			
		||||
      requestNonOptionalPermissions();
 | 
			
		||||
      initForegroundService();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<void> initPlatformState() async {
 | 
			
		||||
    await BackgroundFetch.configure(
 | 
			
		||||
      BackgroundFetchConfig(
 | 
			
		||||
        minimumFetchInterval: 15,
 | 
			
		||||
        stopOnTerminate: false,
 | 
			
		||||
        startOnBoot: true,
 | 
			
		||||
        enableHeadless: true,
 | 
			
		||||
        requiresBatteryNotLow: false,
 | 
			
		||||
        requiresCharging: false,
 | 
			
		||||
        requiresStorageNotLow: false,
 | 
			
		||||
        requiresDeviceIdle: false,
 | 
			
		||||
        requiredNetworkType: NetworkType.ANY,
 | 
			
		||||
  Future<void> requestNonOptionalPermissions() async {
 | 
			
		||||
    final NotificationPermission notificationPermission =
 | 
			
		||||
        await FlutterForegroundTask.checkNotificationPermission();
 | 
			
		||||
    if (notificationPermission != NotificationPermission.granted) {
 | 
			
		||||
      await FlutterForegroundTask.requestNotificationPermission();
 | 
			
		||||
    }
 | 
			
		||||
    if (!await FlutterForegroundTask.isIgnoringBatteryOptimizations) {
 | 
			
		||||
      await FlutterForegroundTask.requestIgnoreBatteryOptimization();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void initForegroundService() {
 | 
			
		||||
    FlutterForegroundTask.init(
 | 
			
		||||
      androidNotificationOptions: AndroidNotificationOptions(
 | 
			
		||||
        channelId: 'bg_update',
 | 
			
		||||
        channelName: tr('foregroundService'),
 | 
			
		||||
        channelDescription: tr('foregroundService'),
 | 
			
		||||
        onlyAlertOnce: true,
 | 
			
		||||
      ),
 | 
			
		||||
      iosNotificationOptions: const IOSNotificationOptions(
 | 
			
		||||
        showNotification: false,
 | 
			
		||||
        playSound: false,
 | 
			
		||||
      ),
 | 
			
		||||
      foregroundTaskOptions: ForegroundTaskOptions(
 | 
			
		||||
        eventAction: ForegroundTaskEventAction.repeat(900000),
 | 
			
		||||
        autoRunOnBoot: true,
 | 
			
		||||
        autoRunOnMyPackageReplaced: true,
 | 
			
		||||
        allowWakeLock: true,
 | 
			
		||||
        allowWifiLock: true,
 | 
			
		||||
      ),
 | 
			
		||||
      (String taskId) async {
 | 
			
		||||
        await bgUpdateCheck(taskId, null);
 | 
			
		||||
        BackgroundFetch.finish(taskId);
 | 
			
		||||
      },
 | 
			
		||||
      (String taskId) async {
 | 
			
		||||
        context.read<LogsProvider>().add('BG update task timed out.');
 | 
			
		||||
        BackgroundFetch.finish(taskId);
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
    if (!mounted) return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<ServiceRequestResult?> startForegroundService(bool restart) async {
 | 
			
		||||
    if (await FlutterForegroundTask.isRunningService) {
 | 
			
		||||
      if (restart) {
 | 
			
		||||
        return FlutterForegroundTask.restartService();
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      return FlutterForegroundTask.startService(
 | 
			
		||||
        serviceTypes: [ForegroundServiceTypes.specialUse],
 | 
			
		||||
        serviceId: 666,
 | 
			
		||||
        notificationTitle: tr('foregroundService'),
 | 
			
		||||
        notificationText: tr('fgServiceNotice'),
 | 
			
		||||
        notificationIcon: NotificationIcon(
 | 
			
		||||
          metaDataName: 'dev.imranr.obtainium.service.NOTIFICATION_ICON',
 | 
			
		||||
        ),
 | 
			
		||||
        callback: startCallback,
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  stopForegroundService() async {
 | 
			
		||||
    if (await FlutterForegroundTask.isRunningService) {
 | 
			
		||||
      return FlutterForegroundTask.stopService();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // void onReceiveForegroundServiceData(Object data) {
 | 
			
		||||
  //   print('onReceiveTaskData: $data');
 | 
			
		||||
  // }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    // Remove a callback to receive data sent from the TaskHandler.
 | 
			
		||||
    // FlutterForegroundTask.removeTaskDataCallback(onReceiveForegroundServiceData);
 | 
			
		||||
    super.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
@@ -186,15 +249,18 @@ class _ObtainiumState extends State<Obtainium> {
 | 
			
		||||
    AppsProvider appsProvider = context.read<AppsProvider>();
 | 
			
		||||
    LogsProvider logs = context.read<LogsProvider>();
 | 
			
		||||
    NotificationsProvider notifs = context.read<NotificationsProvider>();
 | 
			
		||||
 | 
			
		||||
    if (settingsProvider.updateInterval == 0) {
 | 
			
		||||
      stopForegroundService();
 | 
			
		||||
    } else {
 | 
			
		||||
      startForegroundService(false);
 | 
			
		||||
    }
 | 
			
		||||
    if (settingsProvider.prefs == null) {
 | 
			
		||||
      settingsProvider.initializeSettings();
 | 
			
		||||
    } else {
 | 
			
		||||
      bool isFirstRun = settingsProvider.checkAndFlipFirstRun();
 | 
			
		||||
      if (isFirstRun) {
 | 
			
		||||
        logs.add('This is the first ever run of Obtainium.');
 | 
			
		||||
        // If this is the first run, ask for notification permissions and add Obtainium to the Apps list
 | 
			
		||||
        Permission.notification.request();
 | 
			
		||||
        // If this is the first run, add Obtainium to the Apps list
 | 
			
		||||
        if (!fdroid) {
 | 
			
		||||
          getInstalledInfo(obtainiumId)
 | 
			
		||||
              .then((value) {
 | 
			
		||||
@@ -236,7 +302,8 @@ class _ObtainiumState extends State<Obtainium> {
 | 
			
		||||
      notifs.checkLaunchByNotif();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return DynamicColorBuilder(
 | 
			
		||||
    return WithForegroundTask(
 | 
			
		||||
      child: DynamicColorBuilder(
 | 
			
		||||
        builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
 | 
			
		||||
          // Decide on a colour/brightness scheme based on OS and user settings
 | 
			
		||||
          ColorScheme lightColorScheme;
 | 
			
		||||
@@ -292,12 +359,14 @@ class _ObtainiumState extends State<Obtainium> {
 | 
			
		||||
            ),
 | 
			
		||||
            home: Shortcuts(
 | 
			
		||||
              shortcuts: <LogicalKeySet, Intent>{
 | 
			
		||||
              LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
 | 
			
		||||
                LogicalKeySet(LogicalKeyboardKey.select):
 | 
			
		||||
                    const ActivateIntent(),
 | 
			
		||||
              },
 | 
			
		||||
              child: const HomePage(),
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								pubspec.lock
									
									
									
									
									
								
							@@ -104,10 +104,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: battery_plus
 | 
			
		||||
      sha256: a0409fe7d21905987eb1348ad57c634f913166f14f0c8936b73d3f5940fac551
 | 
			
		||||
      sha256: fb794c34cee2e4ea31005fb17ff15e1d904951ec7f15eedead741021870ee834
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.2.1"
 | 
			
		||||
    version: "6.2.2"
 | 
			
		||||
  battery_plus_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -216,18 +216,18 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: device_info_plus
 | 
			
		||||
      sha256: "0c6396126421b590089447154c5f98a5de423b70cfb15b1578fd018843ee6f53"
 | 
			
		||||
      sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "11.4.0"
 | 
			
		||||
    version: "11.5.0"
 | 
			
		||||
  device_info_plus_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: device_info_plus_platform_interface
 | 
			
		||||
      sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2"
 | 
			
		||||
      sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "7.0.2"
 | 
			
		||||
    version: "7.0.3"
 | 
			
		||||
  dynamic_color:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
@@ -377,6 +377,14 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.7.1"
 | 
			
		||||
  flutter_foreground_task:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_foreground_task
 | 
			
		||||
      sha256: "9f1b25a81db95d7119d2c5cffc654048cbdd49d4056183e1beadc1a6a38f3e29"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "9.1.0"
 | 
			
		||||
  flutter_keyboard_visibility:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -995,10 +1003,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: synchronized
 | 
			
		||||
      sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6"
 | 
			
		||||
      sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.3.1"
 | 
			
		||||
    version: "3.4.0"
 | 
			
		||||
  term_glyph:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -1201,4 +1209,4 @@ packages:
 | 
			
		||||
    version: "6.3.0"
 | 
			
		||||
sdks:
 | 
			
		||||
  dart: ">=3.8.1 <4.0.0"
 | 
			
		||||
  flutter: ">=3.27.0"
 | 
			
		||||
  flutter: ">=3.29.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -94,6 +94,7 @@ dependencies:
 | 
			
		||||
  # package. See that file for information about deactivating specific lint
 | 
			
		||||
  # rules and activating additional ones.
 | 
			
		||||
  flutter_lints: ^6.0.0
 | 
			
		||||
  flutter_foreground_task: ^9.1.0
 | 
			
		||||
 | 
			
		||||
flutter_launcher_icons:
 | 
			
		||||
  android: "ic_launcher"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user