mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-10-28 12:03:45 +01:00 
			
		
		
		
	Compare commits
	
		
			14 Commits
		
	
	
		
			v0.13.24-b
			...
			v0.13.25-b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 5269aad90d | ||
|  | eaeee188eb | ||
|  | 8c850e06ca | ||
|  | 0f754a8da8 | ||
|  | 81c4d4f393 | ||
|  | 5317aee18d | ||
|  | b66eeba3b5 | ||
|  | 522ff1ddf7 | ||
|  | 7ef9c43ee3 | ||
|  | 05ac76e3e9 | ||
|  | 4838402797 | ||
|  | 0de12c7c07 | ||
|  | 0dadd8bffe | ||
|  | 75a0cb1189 | 
| @@ -49,7 +49,6 @@ android { | ||||
|     } | ||||
|  | ||||
|     defaultConfig { | ||||
|         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). | ||||
|         applicationId "dev.imranr.obtainium" | ||||
|         // You can update the following values to match your application needs. | ||||
|         // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. | ||||
|   | ||||
| @@ -246,7 +246,7 @@ | ||||
|     "gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel", | ||||
|     "sortByFileNamesNotLinks": "Sortiere nach Dateinamen, anstelle von ganzen Links", | ||||
|     "filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern", | ||||
|     "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", | ||||
|     "customLinkFilterRegex": "Benutzerdefinierter Link Filter nach Regulärem Ausdruck (Standard '.apk$')", | ||||
|     "removeAppQuestion": { | ||||
|         "one": "App entfernen?", | ||||
|         "other": "Apps entfernen?" | ||||
|   | ||||
| @@ -229,24 +229,24 @@ | ||||
|     "dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید", | ||||
|     "dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید", | ||||
|     "moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید", | ||||
|     "gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو را فعال می کند and Better APK Discovery)", | ||||
|     "gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو و کشف بهتر APK را فعال میکند)", | ||||
|     "about": "درباره", | ||||
|     "requiresCredentialsInSettings": "این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)", | ||||
|     "checkOnStart": "بررسی در شروع", | ||||
|     "tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید", | ||||
|     "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", | ||||
|     "pickHighestVersionCode": "Auto-select highest version code APK", | ||||
|     "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", | ||||
|     "disablePageTransitions": "Disable page transition animations", | ||||
|     "reversePageTransitions": "Reverse page transition animations", | ||||
|     "minStarCount": "Minimum Star Count", | ||||
|     "addInfoBelow": "Add this info below.", | ||||
|     "addInfoInSettings": "Add this info in the Settings.", | ||||
|     "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", | ||||
|     "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", | ||||
|     "sortByFileNamesNotLinks": "Sort by file names instead of full links", | ||||
|     "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", | ||||
|     "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", | ||||
|     "removeOnExternalUninstall": "حذف خودکار برنامه های حذف نصب شده خارجی", | ||||
|     "pickHighestVersionCode": "انتخاب خودکار بالاترین کد نسخه APK", | ||||
|     "checkUpdateOnDetailPage": "برای باز کردن صفحه جزئیات برنامه، بهروزرسانیها را بررسی کنید", | ||||
|     "disablePageTransitions": "غیرفعال کردن انیمیشن های انتقال صفحه", | ||||
|     "reversePageTransitions": "انیمیشن های انتقال معکوس صفحه", | ||||
|     "minStarCount": "حداقل تعداد ستاره", | ||||
|     "addInfoBelow": "این اطلاعات را در زیر اضافه کنید", | ||||
|     "addInfoInSettings": "این اطلاعات را در تنظیمات اضافه کنید.", | ||||
|     "githubSourceNote": "با استفاده از کلید API می توان از محدودیت نرخ GitHub جلوگیری کرد.", | ||||
|     "gitlabSourceNote": "استخراج APK GitLab ممکن است بدون کلید API کار نکند.", | ||||
|     "sortByFileNamesNotLinks": "مرتب سازی بر اساس نام فایل به جای پیوندهای کامل", | ||||
|     "filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید", | ||||
|     "customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیشفرض '.apk$')", | ||||
|     "removeAppQuestion": { | ||||
|         "one": "برنامه حذف شود؟", | ||||
|         "other": "برنامه ها حذف شوند؟" | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
|     "githubPATFormat": "ユーザー名:トークン", | ||||
|     "includePrereleases": "プレリリースを含む", | ||||
|     "fallbackToOlderReleases": "旧リリースへのフォールバック", | ||||
|     "filterReleaseTitlesByRegEx": "正規表現でリリースタイトルを絞り込む", | ||||
|     "filterReleaseTitlesByRegEx": "正規表現でリリースタイトルをフィルタリングする", | ||||
|     "invalidRegEx": "無効な正規表現", | ||||
|     "noDescription": "説明はありません", | ||||
|     "cancel": "キャンセル", | ||||
| @@ -88,7 +88,7 @@ | ||||
|     "showOutdatedOnly": "アップデートが存在するアプリのみ表示する", | ||||
|     "filter": "フィルター", | ||||
|     "filterActive": "フィルター *", | ||||
|     "filterApps": "アプリを絞り込む", | ||||
|     "filterApps": "アプリをフィルタリングする", | ||||
|     "appName": "アプリ名", | ||||
|     "author": "作者", | ||||
|     "upToDateApps": "最新のアプリ", | ||||
| @@ -211,7 +211,7 @@ | ||||
|     "copiedToClipboard": "クリップボードにコピーしました", | ||||
|     "storagePermissionDenied": "ストレージ権限が拒否されました", | ||||
|     "selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。", | ||||
|     "filterAPKsByRegEx": "正規表現でAPKを絞り込む", | ||||
|     "filterAPKsByRegEx": "正規表現でAPKをフィルタリングする", | ||||
|     "removeFromObtainium": "Obtainiumから削除する", | ||||
|     "uninstallFromDevice": "デバイスからアンインストールする", | ||||
|     "onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。", | ||||
| @@ -244,9 +244,9 @@ | ||||
|     "addInfoInSettings": "設定でこの情報を追加してください。", | ||||
|     "githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。", | ||||
|     "gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。", | ||||
|     "sortByFileNamesNotLinks": "Sort by file names instead of full links", | ||||
|     "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", | ||||
|     "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", | ||||
|     "sortByFileNamesNotLinks": "フルのリンクではなくファイル名でソートする", | ||||
|     "filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする", | ||||
|     "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')", | ||||
|     "removeAppQuestion": { | ||||
|         "one": "アプリを削除しますか?", | ||||
|         "other": "アプリを削除しますか?" | ||||
|   | ||||
| @@ -250,7 +250,7 @@ | ||||
|     "gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.", | ||||
|     "sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków", | ||||
|     "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", | ||||
|     "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", | ||||
|     "customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")", | ||||
|     "removeAppQuestion": { | ||||
|         "one": "Usunąć aplikację?", | ||||
|         "other": "Usunąć aplikacje?" | ||||
|   | ||||
| @@ -244,9 +244,9 @@ | ||||
|     "addInfoInSettings": "在“设置”中添加此凭据。", | ||||
|     "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。", | ||||
|     "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", | ||||
|     "sortByFileNamesNotLinks": "Sort by file names instead of full links", | ||||
|     "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", | ||||
|     "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", | ||||
|     "sortByFileNamesNotLinks": "根据文件名而不是完整链接来排序", | ||||
|     "filterReleaseNotesByRegEx": "用正则表达式筛选发布说明", | ||||
|     "customLinkFilterRegex": "用正则表达式自定义链接筛选(默认 '.apk$')", | ||||
|     "removeAppQuestion": { | ||||
|         "one": "是否删除应用?", | ||||
|         "other": "是否删除应用?" | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; | ||||
| // ignore: implementation_imports | ||||
| import 'package:easy_localization/src/localization.dart'; | ||||
|  | ||||
| const String currentVersion = '0.13.24'; | ||||
| const String currentVersion = '0.13.25'; | ||||
| const String currentReleaseTag = | ||||
|     'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES | ||||
|  | ||||
|   | ||||
| @@ -643,15 +643,15 @@ class AppsPageState extends State<AppsPage> { | ||||
|                     label: tr('installX', args: [ | ||||
|                       plural('apps', newInstallIdsAllOrSelected.length) | ||||
|                     ]), | ||||
|                     defaultValue: existingUpdateIdsAllOrSelected.isNotEmpty)); | ||||
|                     defaultValue: existingUpdateIdsAllOrSelected.isEmpty)); | ||||
|               } | ||||
|               if (trackOnlyUpdateIdsAllOrSelected.isNotEmpty) { | ||||
|                 formItems.add(GeneratedFormSwitch('trackonlies', | ||||
|                     label: tr('markXTrackOnlyAsUpdated', args: [ | ||||
|                       plural('apps', trackOnlyUpdateIdsAllOrSelected.length) | ||||
|                     ]), | ||||
|                     defaultValue: existingUpdateIdsAllOrSelected.isNotEmpty || | ||||
|                         newInstallIdsAllOrSelected.isNotEmpty)); | ||||
|                     defaultValue: existingUpdateIdsAllOrSelected.isEmpty && | ||||
|                         newInstallIdsAllOrSelected.isEmpty)); | ||||
|               } | ||||
|               showDialog<Map<String, dynamic>?>( | ||||
|                   context: context, | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import 'dart:io'; | ||||
|  | ||||
| import 'package:android_intent_plus/flag.dart'; | ||||
| import 'package:android_package_installer/android_package_installer.dart'; | ||||
| import 'package:android_package_manager/android_package_manager.dart'; | ||||
| import 'package:device_info_plus/device_info_plus.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| @@ -29,6 +30,8 @@ import 'package:http/http.dart'; | ||||
| import 'package:android_intent_plus/android_intent.dart'; | ||||
| import 'package:flutter_archive/flutter_archive.dart'; | ||||
|  | ||||
| final pm = AndroidPackageManager(); | ||||
|  | ||||
| class AppInMemory { | ||||
|   late App app; | ||||
|   double? downloadProgress; | ||||
| @@ -322,16 +325,39 @@ class AppsProvider with ChangeNotifier { | ||||
|       .isNotEmpty; | ||||
|  | ||||
|   Future<bool> canInstallSilently(App app) async { | ||||
|     return false; | ||||
|     // TODO: Uncomment the below if silent updates are ever figured out | ||||
|     // // NOTE: This is unreliable - try to get from OS in the future | ||||
|     // if (app.apkUrls.length > 1) { | ||||
|     //    return false; | ||||
|     // } | ||||
|     // var osInfo = await DeviceInfoPlugin().androidInfo; | ||||
|     // return app.installedVersion != null && | ||||
|     //     osInfo.version.sdkInt >= 30 && | ||||
|     //     osInfo.version.release.compareTo('12') >= 0; | ||||
|     if (app.apkUrls.length > 1) { | ||||
|       // Manual API selection means silent install is not possible | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     var osInfo = await DeviceInfoPlugin().androidInfo; | ||||
|     String? installerPackageName; | ||||
|     try { | ||||
|       installerPackageName = osInfo.version.sdkInt >= 30 | ||||
|           ? (await pm.getInstallSourceInfo(packageName: app.id)) | ||||
|               ?.installingPackageName | ||||
|           : (await pm.getInstallerPackageName(packageName: app.id)); | ||||
|     } catch (e) { | ||||
|       // Probably not installed - ignore | ||||
|     } | ||||
|     if (installerPackageName != obtainiumId) { | ||||
|       // If we did not install the app (or it isn't installed), silent install is not possible | ||||
|       return false; | ||||
|     } | ||||
|     var targetSDK; | ||||
|     try { | ||||
|       targetSDK = (await pm.getPackageInfo(packageName: app.id)) | ||||
|           ?.applicationInfo | ||||
|           ?.targetSdkVersion; | ||||
|     } catch (e) { | ||||
|       // Weird if you get here - ignore | ||||
|     } | ||||
|  | ||||
|     // The OS must also be new enough and the APK should target a new enough API | ||||
|     return osInfo.version.sdkInt >= 30 && | ||||
|         targetSDK != null && | ||||
|         targetSDK >= // https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setRequireUserAction(int) | ||||
|             (osInfo.version.sdkInt - 3); | ||||
|   } | ||||
|  | ||||
|   Future<void> waitForUserToReturnToForeground(BuildContext context) async { | ||||
| @@ -359,8 +385,7 @@ class AppsProvider with ChangeNotifier { | ||||
|         zipFile: File(filePath), destinationDir: Directory(destinationPath)); | ||||
|   } | ||||
|  | ||||
|   Future<void> installXApkDir(DownloadedXApkDir dir, | ||||
|       {bool silent = false}) async { | ||||
|   Future<void> installXApkDir(DownloadedXApkDir dir) async { | ||||
|     // We don't know which APKs in an XAPK are supported by the user's device | ||||
|     // So we try installing all of them and assume success if at least one installed | ||||
|     // If 0 APKs installed, throw the first install error encountered | ||||
| @@ -373,8 +398,7 @@ class AppsProvider with ChangeNotifier { | ||||
|         if (file.path.toLowerCase().endsWith('.apk')) { | ||||
|           try { | ||||
|             somethingInstalled = somethingInstalled || | ||||
|                 await installApk(DownloadedApk(dir.appId, file), | ||||
|                     silent: silent); | ||||
|                 await installApk(DownloadedApk(dir.appId, file)); | ||||
|           } catch (e) { | ||||
|             logs.add( | ||||
|                 'Could not install APK from XAPK \'${file.path}\': ${e.toString()}'); | ||||
| @@ -394,8 +418,7 @@ class AppsProvider with ChangeNotifier { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future<bool> installApk(DownloadedApk file, {bool silent = false}) async { | ||||
|     // TODO: Use 'silent' when/if ever possible | ||||
|   Future<bool> installApk(DownloadedApk file) async { | ||||
|     var newInfo = await PackageArchiveInfo.fromPath(file.file.path); | ||||
|     AppInfo? appInfo; | ||||
|     try { | ||||
| @@ -571,7 +594,6 @@ class AppsProvider with ChangeNotifier { | ||||
|         } | ||||
|         bool willBeSilent = await canInstallSilently( | ||||
|             apps[downloadedFile?.appId ?? downloadedDir!.appId]!.app); | ||||
|         willBeSilent = false; // TODO: Remove this when silent updates work | ||||
|         if (!(await settingsProvider?.getInstallPermission(enforce: false) ?? | ||||
|             true)) { | ||||
|           throw ObtainiumError(tr('cancelled')); | ||||
| @@ -584,9 +606,9 @@ class AppsProvider with ChangeNotifier { | ||||
|         notifyListeners(); | ||||
|         try { | ||||
|           if (downloadedFile != null) { | ||||
|             await installApk(downloadedFile, silent: willBeSilent); | ||||
|             await installApk(downloadedFile); | ||||
|           } else { | ||||
|             await installXApkDir(downloadedDir!, silent: willBeSilent); | ||||
|             await installXApkDir(downloadedDir!); | ||||
|           } | ||||
|         } finally { | ||||
|           apps[id]?.downloadProgress = null; | ||||
|   | ||||
							
								
								
									
										17
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								pubspec.lock
									
									
									
									
									
								
							| @@ -26,6 +26,15 @@ packages: | ||||
|       url: "https://github.com/ImranR98/android_package_installer" | ||||
|     source: git | ||||
|     version: "0.0.1" | ||||
|   android_package_manager: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       path: "." | ||||
|       ref: master | ||||
|       resolved-ref: "6e68991ef9c6232695abce2eef345d3cca2f52ac" | ||||
|       url: "https://github.com/ImranR98/android_package_manager" | ||||
|     source: git | ||||
|     version: "0.5.4" | ||||
|   animations: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @@ -578,10 +587,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: platform | ||||
|       sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" | ||||
|       sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.1.0" | ||||
|     version: "3.1.1" | ||||
|   plugin_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -871,10 +880,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: webview_flutter_platform_interface | ||||
|       sha256: "564ef378cafc1a0e29f1d76ce175ef517a0a6115875dff7b43fccbef2b0aeb30" | ||||
|       sha256: "0ca3cfcc6781a7de701d580917af4a9efc4e3e129f8ead95a80587f0a749480a" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.4.0" | ||||
|     version: "2.5.0" | ||||
|   webview_flutter_wkwebview: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
							
								
								
									
										12
									
								
								pubspec.yaml
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								pubspec.yaml
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| name: obtainium | ||||
| description: A new Flutter project. | ||||
| description: Get Android App Updates Directly From the Source. | ||||
|  | ||||
| # The following line prevents the package from being accidentally published to | ||||
| # pub.dev using `flutter pub publish`. This is preferred for private packages. | ||||
| @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev | ||||
| # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | ||||
| # In Windows, build-name is used as the major, minor, and patch parts | ||||
| # of the product and file versions while build-number is used as the build suffix. | ||||
| version: 0.13.24+188 # When changing this, update the tag in main() accordingly | ||||
| version: 0.13.25+189 # When changing this, update the tag in main() accordingly | ||||
|  | ||||
| environment: | ||||
|   sdk: '>=2.18.2 <3.0.0' | ||||
| @@ -55,9 +55,13 @@ dependencies: | ||||
|     git: | ||||
|       url: https://github.com/ImranR98/android_package_installer | ||||
|       ref: main | ||||
|   android_package_manager: | ||||
|     git: | ||||
|         url: https://github.com/ImranR98/android_package_manager | ||||
|         ref: master | ||||
|   share_plus: ^7.0.0 | ||||
|   installed_apps: ^1.3.1 | ||||
|   package_archive_info: ^0.1.0 | ||||
|   installed_apps: ^1.3.1 # TODO: Remove when android_package_manager supports getting icon as UInt8List and versionCode | ||||
|   package_archive_info: ^0.1.0 # TODO: Remove when android_package_manager supports getting versionCode | ||||
|   android_alarm_manager_plus: ^3.0.0 | ||||
|   sqflite: ^2.2.0+3 | ||||
|   easy_localization: ^3.0.1 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user