mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-08-12 09:58:10 +02:00
Various bugfixes
This commit is contained in:
@@ -820,22 +820,82 @@ class AppsProvider with ChangeNotifier {
|
|||||||
appsToInstall =
|
appsToInstall =
|
||||||
moveStrToEnd(appsToInstall, obtainiumId, strB: obtainiumTempId);
|
moveStrToEnd(appsToInstall, obtainiumId, strB: obtainiumTempId);
|
||||||
|
|
||||||
Future<String> updateFn(String id, {bool skipInstalls = false}) async {
|
Future<void> installFn(String id, bool willBeSilent,
|
||||||
|
DownloadedApk? downloadedFile, DownloadedXApkDir? downloadedDir) async {
|
||||||
|
apps[id]?.downloadProgress = -1;
|
||||||
|
notifyListeners();
|
||||||
|
try {
|
||||||
|
bool sayInstalled = true;
|
||||||
|
var contextIfNewInstall =
|
||||||
|
apps[id]?.installedInfo == null ? context : null;
|
||||||
|
bool needBGWorkaround =
|
||||||
|
willBeSilent && context == null && !settingsProvider.useShizuku;
|
||||||
|
if (downloadedFile != null) {
|
||||||
|
if (needBGWorkaround) {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
|
installApk(downloadedFile, contextIfNewInstall,
|
||||||
|
needsBGWorkaround: true);
|
||||||
|
} else {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
|
sayInstalled = await installApk(downloadedFile, contextIfNewInstall,
|
||||||
|
shizukuPretendToBeGooglePlay: apps[id]!
|
||||||
|
.app
|
||||||
|
.additionalSettings['shizukuPretendToBeGooglePlay'] ==
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (needBGWorkaround) {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
|
installXApkDir(downloadedDir!, contextIfNewInstall,
|
||||||
|
needsBGWorkaround: true);
|
||||||
|
} else {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
|
sayInstalled = await installXApkDir(
|
||||||
|
downloadedDir!, contextIfNewInstall,
|
||||||
|
shizukuPretendToBeGooglePlay: apps[id]!
|
||||||
|
.app
|
||||||
|
.additionalSettings['shizukuPretendToBeGooglePlay'] ==
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (willBeSilent && context == null) {
|
||||||
|
if (!settingsProvider.useShizuku) {
|
||||||
|
notificationsProvider?.notify(SilentUpdateAttemptNotification(
|
||||||
|
[apps[id]!.app],
|
||||||
|
id: id.hashCode));
|
||||||
|
} else {
|
||||||
|
notificationsProvider?.notify(SilentUpdateNotification(
|
||||||
|
[apps[id]!.app], sayInstalled,
|
||||||
|
id: id.hashCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sayInstalled) {
|
||||||
|
installedIds.add(id);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
apps[id]?.downloadProgress = null;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<Object?, Object?>> downloadFn(String id,
|
||||||
|
{bool skipInstalls = false}) async {
|
||||||
|
bool willBeSilent = false;
|
||||||
|
DownloadedApk? downloadedFile;
|
||||||
|
DownloadedXApkDir? downloadedDir;
|
||||||
try {
|
try {
|
||||||
var downloadedArtifact =
|
var downloadedArtifact =
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
await downloadApp(apps[id]!.app, context,
|
await downloadApp(apps[id]!.app, context,
|
||||||
notificationsProvider: notificationsProvider,
|
notificationsProvider: notificationsProvider,
|
||||||
useExisting: useExisting);
|
useExisting: useExisting);
|
||||||
DownloadedApk? downloadedFile;
|
|
||||||
DownloadedXApkDir? downloadedDir;
|
|
||||||
if (downloadedArtifact is DownloadedApk) {
|
if (downloadedArtifact is DownloadedApk) {
|
||||||
downloadedFile = downloadedArtifact;
|
downloadedFile = downloadedArtifact;
|
||||||
} else {
|
} else {
|
||||||
downloadedDir = downloadedArtifact as DownloadedXApkDir;
|
downloadedDir = downloadedArtifact as DownloadedXApkDir;
|
||||||
}
|
}
|
||||||
id = downloadedFile?.appId ?? downloadedDir!.appId;
|
id = downloadedFile?.appId ?? downloadedDir!.appId;
|
||||||
bool willBeSilent = await canInstallSilently(apps[id]!.app);
|
willBeSilent = await canInstallSilently(apps[id]!.app);
|
||||||
if (!settingsProvider.useShizuku) {
|
if (!settingsProvider.useShizuku) {
|
||||||
if (!(await settingsProvider.getInstallPermission(enforce: false))) {
|
if (!(await settingsProvider.getInstallPermission(enforce: false))) {
|
||||||
throw ObtainiumError(tr('cancelled'));
|
throw ObtainiumError(tr('cancelled'));
|
||||||
@@ -856,80 +916,33 @@ class AppsProvider with ChangeNotifier {
|
|||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
await waitForUserToReturnToForeground(context);
|
await waitForUserToReturnToForeground(context);
|
||||||
}
|
}
|
||||||
apps[id]?.downloadProgress = -1;
|
|
||||||
notifyListeners();
|
|
||||||
try {
|
|
||||||
if (!skipInstalls) {
|
|
||||||
bool sayInstalled = true;
|
|
||||||
var contextIfNewInstall =
|
|
||||||
apps[id]?.installedInfo == null ? context : null;
|
|
||||||
bool needBGWorkaround =
|
|
||||||
willBeSilent && context == null && !settingsProvider.useShizuku;
|
|
||||||
if (downloadedFile != null) {
|
|
||||||
if (needBGWorkaround) {
|
|
||||||
// ignore: use_build_context_synchronously
|
|
||||||
installApk(downloadedFile, contextIfNewInstall,
|
|
||||||
needsBGWorkaround: true);
|
|
||||||
} else {
|
|
||||||
// ignore: use_build_context_synchronously
|
|
||||||
sayInstalled = await installApk(
|
|
||||||
downloadedFile, contextIfNewInstall,
|
|
||||||
shizukuPretendToBeGooglePlay:
|
|
||||||
apps[id]!.app.additionalSettings[
|
|
||||||
'shizukuPretendToBeGooglePlay'] ==
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (needBGWorkaround) {
|
|
||||||
// ignore: use_build_context_synchronously
|
|
||||||
installXApkDir(downloadedDir!, contextIfNewInstall,
|
|
||||||
needsBGWorkaround: true);
|
|
||||||
} else {
|
|
||||||
// ignore: use_build_context_synchronously
|
|
||||||
sayInstalled = await installXApkDir(
|
|
||||||
downloadedDir!, contextIfNewInstall,
|
|
||||||
shizukuPretendToBeGooglePlay:
|
|
||||||
apps[id]!.app.additionalSettings[
|
|
||||||
'shizukuPretendToBeGooglePlay'] ==
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (willBeSilent && context == null) {
|
|
||||||
if (!settingsProvider.useShizuku) {
|
|
||||||
notificationsProvider?.notify(SilentUpdateAttemptNotification(
|
|
||||||
[apps[id]!.app],
|
|
||||||
id: id.hashCode));
|
|
||||||
} else {
|
|
||||||
notificationsProvider?.notify(SilentUpdateNotification(
|
|
||||||
[apps[id]!.app], sayInstalled,
|
|
||||||
id: id.hashCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sayInstalled) {
|
|
||||||
installedIds.add(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
apps[id]?.downloadProgress = null;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.add(id, e, appName: apps[id]?.name);
|
errors.add(id, e, appName: apps[id]?.name);
|
||||||
}
|
}
|
||||||
return id;
|
return {
|
||||||
|
'id': id,
|
||||||
|
'willBeSilent': willBeSilent,
|
||||||
|
'downloadedFile': downloadedFile,
|
||||||
|
'downloadedDir': downloadedDir
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Map<Object?, Object?>> downloadResults = [];
|
||||||
if (forceParallelDownloads || !settingsProvider.parallelDownloads) {
|
if (forceParallelDownloads || !settingsProvider.parallelDownloads) {
|
||||||
for (var id in appsToInstall) {
|
for (var id in appsToInstall) {
|
||||||
await updateFn(id);
|
downloadResults.add(await downloadFn(id));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
List<String> ids = await Future.wait(
|
downloadResults = await Future.wait(
|
||||||
appsToInstall.map((id) => updateFn(id, skipInstalls: true)));
|
appsToInstall.map((id) => downloadFn(id, skipInstalls: true)));
|
||||||
for (var id in ids) {
|
}
|
||||||
if (!errors.appIdNames.containsKey(id)) {
|
for (var res in downloadResults) {
|
||||||
await updateFn(id);
|
if (!errors.appIdNames.containsKey(res['id'])) {
|
||||||
}
|
await installFn(
|
||||||
|
res['id'] as String,
|
||||||
|
res['willBeSilent'] as bool,
|
||||||
|
res['downloadedFile'] as DownloadedApk?,
|
||||||
|
res['downloadedDir'] as DownloadedXApkDir?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,40 +1179,38 @@ class AppsProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
var sp = SourceProvider();
|
var sp = SourceProvider();
|
||||||
List<List<String>> errors = [];
|
List<List<String>> errors = [];
|
||||||
List<App?> newApps = (await getAppsDir()) // Parse Apps from JSON
|
await Future.wait((await getAppsDir()) // Parse Apps from JSON
|
||||||
.listSync()
|
.listSync()
|
||||||
.where((item) => item.path.toLowerCase().endsWith('.json'))
|
.map((item) async {
|
||||||
.where((item) =>
|
App? app;
|
||||||
singleId == null ||
|
if (item.path.toLowerCase().endsWith('.json') &&
|
||||||
item.path.split('/').last.toLowerCase() ==
|
(singleId == null ||
|
||||||
'${singleId.toLowerCase()}.json')
|
item.path.split('/').last.toLowerCase() ==
|
||||||
.map((e) {
|
'${singleId.toLowerCase()}.json')) {
|
||||||
try {
|
try {
|
||||||
return App.fromJson(jsonDecode(File(e.path).readAsStringSync()));
|
app = App.fromJson(jsonDecode(File(item.path).readAsStringSync()));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err is FormatException) {
|
if (err is FormatException) {
|
||||||
logs.add('Corrupt JSON when loading App (will be ignored): $e');
|
logs.add('Corrupt JSON when loading App (will be ignored): $e');
|
||||||
e.renameSync('${e.path}.corrupt');
|
item.renameSync('${item.path}.corrupt');
|
||||||
} else {
|
} else {
|
||||||
rethrow;
|
rethrow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).toList();
|
|
||||||
for (var app in newApps) {
|
|
||||||
// Put Apps into memory to list them (fast)
|
|
||||||
if (app != null) {
|
if (app != null) {
|
||||||
try {
|
try {
|
||||||
sp.getSource(app.url, overrideSource: app.overrideSource);
|
sp.getSource(app.url, overrideSource: app.overrideSource);
|
||||||
apps.update(
|
apps.update(
|
||||||
app.id,
|
app.id,
|
||||||
(value) => AppInMemory(
|
(value) => AppInMemory(app!, value.downloadProgress,
|
||||||
app, value.downloadProgress, value.installedInfo, value.icon),
|
value.installedInfo, value.icon),
|
||||||
ifAbsent: () => AppInMemory(app, null, null, null));
|
ifAbsent: () => AppInMemory(app!, null, null, null));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.add([app.id, app.finalName, e.toString()]);
|
errors.add([app.id, app.finalName, e.toString()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
if (errors.isNotEmpty) {
|
if (errors.isNotEmpty) {
|
||||||
removeApps(errors.map((e) => e[0]).toList());
|
removeApps(errors.map((e) => e[0]).toList());
|
||||||
@@ -1207,19 +1218,17 @@ class AppsProvider with ChangeNotifier {
|
|||||||
AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList()));
|
AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList()));
|
||||||
}
|
}
|
||||||
// Get install status and other OS info for each App (slow)
|
// Get install status and other OS info for each App (slow)
|
||||||
await Future.wait(apps.values.map((app) {
|
|
||||||
return updateInstallStatusInMemory(app);
|
|
||||||
}));
|
|
||||||
notifyListeners();
|
|
||||||
// Reconcile version differences
|
|
||||||
List<App> modifiedApps = [];
|
List<App> modifiedApps = [];
|
||||||
for (var app in apps.values) {
|
await Future.wait(apps.values.map((app) async {
|
||||||
|
await updateInstallStatusInMemory(app);
|
||||||
var moddedApp =
|
var moddedApp =
|
||||||
getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo);
|
getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo);
|
||||||
if (moddedApp != null) {
|
if (moddedApp != null) {
|
||||||
modifiedApps.add(moddedApp);
|
modifiedApps.add(moddedApp);
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
|
notifyListeners();
|
||||||
|
// Reconcile version differences
|
||||||
if (modifiedApps.isNotEmpty) {
|
if (modifiedApps.isNotEmpty) {
|
||||||
await saveApps(modifiedApps, attemptToCorrectInstallStatus: false);
|
await saveApps(modifiedApps, attemptToCorrectInstallStatus: false);
|
||||||
var removedAppIds = modifiedApps
|
var removedAppIds = modifiedApps
|
||||||
@@ -1241,7 +1250,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
{bool attemptToCorrectInstallStatus = true,
|
{bool attemptToCorrectInstallStatus = true,
|
||||||
bool onlyIfExists = true}) async {
|
bool onlyIfExists = true}) async {
|
||||||
attemptToCorrectInstallStatus = attemptToCorrectInstallStatus;
|
attemptToCorrectInstallStatus = attemptToCorrectInstallStatus;
|
||||||
for (var a in apps) {
|
await Future.wait(apps.map((a) async {
|
||||||
var app = a.deepCopy();
|
var app = a.deepCopy();
|
||||||
PackageInfo? info = await getInstalledInfo(app.id);
|
PackageInfo? info = await getInstalledInfo(app.id);
|
||||||
var icon = await info?.applicationInfo?.getAppIcon();
|
var icon = await info?.applicationInfo?.getAppIcon();
|
||||||
@@ -1263,14 +1272,14 @@ class AppsProvider with ChangeNotifier {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
export(isAuto: true);
|
export(isAuto: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> removeApps(List<String> appIds) async {
|
Future<void> removeApps(List<String> appIds) async {
|
||||||
var apkFiles = APKDir.listSync();
|
var apkFiles = APKDir.listSync();
|
||||||
for (var appId in appIds) {
|
await Future.wait(appIds.map((appId) async {
|
||||||
File file = File('${(await getAppsDir()).path}/$appId.json');
|
File file = File('${(await getAppsDir()).path}/$appId.json');
|
||||||
if (file.existsSync()) {
|
if (file.existsSync()) {
|
||||||
file.deleteSync(recursive: true);
|
file.deleteSync(recursive: true);
|
||||||
@@ -1284,7 +1293,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
if (apps.containsKey(appId)) {
|
if (apps.containsKey(appId)) {
|
||||||
apps.remove(appId);
|
apps.remove(appId);
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
if (appIds.isNotEmpty) {
|
if (appIds.isNotEmpty) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
export(isAuto: true);
|
export(isAuto: true);
|
||||||
@@ -1543,6 +1552,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
settingsMap.forEach((key, value) {
|
settingsMap.forEach((key, value) {
|
||||||
if (value is int) {
|
if (value is int) {
|
||||||
settingsProvider.prefs?.setInt(key, value);
|
settingsProvider.prefs?.setInt(key, value);
|
||||||
|
} else if (value is double) {
|
||||||
|
settingsProvider.prefs?.setDouble(key, value);
|
||||||
} else if (value is bool) {
|
} else if (value is bool) {
|
||||||
settingsProvider.prefs?.setBool(key, value);
|
settingsProvider.prefs?.setBool(key, value);
|
||||||
} else if (value is List) {
|
} else if (value is List) {
|
||||||
|
Reference in New Issue
Block a user