mirror of
https://github.com/revanced/revanced-manager
synced 2024-05-14 13:56:57 +02:00
fix: improve installed apps check
This commit is contained in:
parent
56e85ca7cf
commit
9f82b9b275
@ -396,7 +396,7 @@ class MainActivity : FlutterActivity() {
|
|||||||
"update",
|
"update",
|
||||||
mapOf(
|
mapOf(
|
||||||
"progress" to 1.0,
|
"progress" to 1.0,
|
||||||
"header" to "Finished",
|
"header" to "Finished!",
|
||||||
"log" to "Finished"
|
"log" to "Finished"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:revanced_manager/main.dart';
|
import 'package:revanced_manager/main.dart';
|
||||||
import 'package:revanced_manager/main_viewmodel.dart';
|
import 'package:revanced_manager/main_viewmodel.dart';
|
||||||
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/services/patcher_api.dart';
|
import 'package:revanced_manager/services/patcher_api.dart';
|
||||||
import 'package:revanced_manager/ui/views/app_selector/app_selector_view.dart';
|
import 'package:revanced_manager/ui/views/app_selector/app_selector_view.dart';
|
||||||
import 'package:revanced_manager/ui/views/contributors/contributors_view.dart';
|
import 'package:revanced_manager/ui/views/contributors/contributors_view.dart';
|
||||||
@ -34,6 +35,7 @@ import 'package:stacked_themes/stacked_themes.dart';
|
|||||||
classType: ThemeService,
|
classType: ThemeService,
|
||||||
resolveUsing: ThemeService.getInstance,
|
resolveUsing: ThemeService.getInstance,
|
||||||
),
|
),
|
||||||
|
LazySingleton(classType: ManagerAPI),
|
||||||
LazySingleton(classType: PatcherAPI),
|
LazySingleton(classType: PatcherAPI),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -5,19 +5,19 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||||||
import 'package:revanced_manager/app/app.locator.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/app/app.router.dart';
|
import 'package:revanced_manager/app/app.router.dart';
|
||||||
import 'package:revanced_manager/main_viewmodel.dart';
|
import 'package:revanced_manager/main_viewmodel.dart';
|
||||||
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/theme.dart';
|
import 'package:revanced_manager/theme.dart';
|
||||||
import 'package:revanced_manager/ui/views/home/home_view.dart';
|
import 'package:revanced_manager/ui/views/home/home_view.dart';
|
||||||
import 'package:revanced_manager/ui/views/patcher/patcher_view.dart';
|
import 'package:revanced_manager/ui/views/patcher/patcher_view.dart';
|
||||||
import 'package:revanced_manager/ui/views/root_checker/root_checker_view.dart';
|
import 'package:revanced_manager/ui/views/root_checker/root_checker_view.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settings_view.dart';
|
import 'package:revanced_manager/ui/views/settings/settings_view.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
import 'package:stacked_themes/stacked_themes.dart';
|
import 'package:stacked_themes/stacked_themes.dart';
|
||||||
|
|
||||||
Future main() async {
|
Future main() async {
|
||||||
await ThemeManager.initialise();
|
await ThemeManager.initialise();
|
||||||
setupLocator();
|
await setupLocator();
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
@ -68,8 +68,8 @@ class MyApp extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Widget> _init() async {
|
Future<Widget> _init() async {
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
await locator<ManagerAPI>().initialize();
|
||||||
bool? isRooted = prefs.getBool('isRooted');
|
bool? isRooted = locator<ManagerAPI>().isRooted();
|
||||||
if (isRooted != null) {
|
if (isRooted != null) {
|
||||||
return const Navigation();
|
return const Navigation();
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:device_apps/device_apps.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:revanced_manager/constants.dart';
|
import 'package:revanced_manager/constants.dart';
|
||||||
|
import 'package:revanced_manager/models/patched_application.dart';
|
||||||
import 'package:revanced_manager/services/github_api.dart';
|
import 'package:revanced_manager/services/github_api.dart';
|
||||||
|
import 'package:revanced_manager/services/root_api.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
@lazySingleton
|
||||||
class ManagerAPI {
|
class ManagerAPI {
|
||||||
final GithubAPI _githubAPI = GithubAPI();
|
final GithubAPI _githubAPI = GithubAPI();
|
||||||
|
final RootAPI _rootAPI = RootAPI();
|
||||||
|
late SharedPreferences _prefs;
|
||||||
|
|
||||||
|
Future<void> initialize() async {
|
||||||
|
_prefs = await SharedPreferences.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
Future<File?> downloadPatches(String extension) async {
|
Future<File?> downloadPatches(String extension) async {
|
||||||
return await _githubAPI.latestReleaseFile(extension, ghOrg, patchesRepo);
|
return await _githubAPI.latestReleaseFile(extension, ghOrg, patchesRepo);
|
||||||
@ -35,6 +48,89 @@ class ManagerAPI {
|
|||||||
return packageInfo.version;
|
return packageInfo.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool? isRooted() {
|
||||||
|
return _prefs.getBool('isRooted');
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PatchedApplication> getPatchedApps() {
|
||||||
|
List<String> apps = _prefs.getStringList('patchedApps') ?? [];
|
||||||
|
return apps
|
||||||
|
.map((a) => PatchedApplication.fromJson(json.decode(a)))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPatchedApps(List<PatchedApplication> patchedApps) {
|
||||||
|
_prefs.setStringList('patchedApps',
|
||||||
|
patchedApps.map((a) => json.encode(a.toJson())).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
void savePatchedApp(PatchedApplication app) {
|
||||||
|
List<PatchedApplication> patchedApps = getPatchedApps();
|
||||||
|
patchedApps.removeWhere((a) => a.packageName == app.packageName);
|
||||||
|
patchedApps.add(app);
|
||||||
|
setPatchedApps(patchedApps);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveApp(
|
||||||
|
ApplicationWithIcon application,
|
||||||
|
bool isRooted,
|
||||||
|
bool isFromStorage,
|
||||||
|
) {
|
||||||
|
savePatchedApp(
|
||||||
|
PatchedApplication(
|
||||||
|
name: application.appName,
|
||||||
|
packageName: application.packageName,
|
||||||
|
version: application.versionName!,
|
||||||
|
apkFilePath: application.apkFilePath,
|
||||||
|
icon: application.icon,
|
||||||
|
patchDate: DateTime.now(),
|
||||||
|
isRooted: isRooted,
|
||||||
|
isFromStorage: isFromStorage,
|
||||||
|
appliedPatches: [],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> reAssessSavedApps() async {
|
||||||
|
List<PatchedApplication> patchedApps = getPatchedApps();
|
||||||
|
bool isRoot = isRooted() ?? false;
|
||||||
|
for (PatchedApplication app in patchedApps) {
|
||||||
|
bool existsRoot = false;
|
||||||
|
if (isRoot) {
|
||||||
|
existsRoot = await _rootAPI.isAppInstalled(app.packageName);
|
||||||
|
}
|
||||||
|
bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName);
|
||||||
|
if (!existsRoot && !existsNonRoot) {
|
||||||
|
patchedApps.remove(app);
|
||||||
|
} else if (existsNonRoot) {
|
||||||
|
ApplicationWithIcon? application =
|
||||||
|
await DeviceApps.getApp(app.packageName, true)
|
||||||
|
as ApplicationWithIcon?;
|
||||||
|
if (application != null) {
|
||||||
|
int savedVersionInt =
|
||||||
|
int.parse(app.version.replaceFirst('v', '').replaceAll('.', ''));
|
||||||
|
int currentVersionInt = int.parse(application.versionName!
|
||||||
|
.replaceFirst('v', '')
|
||||||
|
.replaceAll('.', ''));
|
||||||
|
if (savedVersionInt < currentVersionInt) {
|
||||||
|
patchedApps.remove(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setPatchedApps(patchedApps);
|
||||||
|
List<String> apps = await _rootAPI.getInstalledApps();
|
||||||
|
for (String packageName in apps) {
|
||||||
|
if (!patchedApps.any((a) => a.packageName == packageName)) {
|
||||||
|
ApplicationWithIcon? application =
|
||||||
|
await DeviceApps.getApp(packageName, true) as ApplicationWithIcon?;
|
||||||
|
if (application != null) {
|
||||||
|
saveApp(application, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> hasAppUpdates(String packageName) async {
|
Future<bool> hasAppUpdates(String packageName) async {
|
||||||
// TODO: get status based on last update time on the folder of this app?
|
// TODO: get status based on last update time on the folder of this app?
|
||||||
return false;
|
return false;
|
||||||
|
@ -4,6 +4,7 @@ import 'package:device_apps/device_apps.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/models/patch.dart';
|
import 'package:revanced_manager/models/patch.dart';
|
||||||
import 'package:revanced_manager/models/patched_application.dart';
|
import 'package:revanced_manager/models/patched_application.dart';
|
||||||
import 'package:revanced_manager/services/manager_api.dart';
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
@ -16,7 +17,7 @@ class PatcherAPI {
|
|||||||
static const patcherChannel = MethodChannel(
|
static const patcherChannel = MethodChannel(
|
||||||
'app.revanced.manager/patcher',
|
'app.revanced.manager/patcher',
|
||||||
);
|
);
|
||||||
final ManagerAPI _managerAPI = ManagerAPI();
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
final RootAPI _rootAPI = RootAPI();
|
final RootAPI _rootAPI = RootAPI();
|
||||||
Directory? _tmpDir;
|
Directory? _tmpDir;
|
||||||
Directory? _workDir;
|
Directory? _workDir;
|
||||||
@ -248,7 +249,7 @@ class PatcherAPI {
|
|||||||
|
|
||||||
Future<bool> checkOldPatch(PatchedApplication patchedApp) async {
|
Future<bool> checkOldPatch(PatchedApplication patchedApp) async {
|
||||||
if (patchedApp.isRooted) {
|
if (patchedApp.isRooted) {
|
||||||
return await _rootAPI.checkApp(patchedApp.packageName);
|
return await _rootAPI.isAppInstalled(patchedApp.packageName);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,39 @@ class RootAPI {
|
|||||||
final String _postFsDataDirPath = "/data/adb/post-fs-data.d";
|
final String _postFsDataDirPath = "/data/adb/post-fs-data.d";
|
||||||
final String _serviceDDirPath = "/data/adb/service.d";
|
final String _serviceDDirPath = "/data/adb/service.d";
|
||||||
|
|
||||||
Future<bool> checkApp(String packageName) async {
|
Future<bool> isAppInstalled(String packageName) async {
|
||||||
|
if (packageName.isNotEmpty) {
|
||||||
|
String? res = await Root.exec(
|
||||||
|
cmd: 'ls "$_managerDirPath/$packageName"',
|
||||||
|
);
|
||||||
|
if (res != null && res.isNotEmpty) {
|
||||||
|
res = await Root.exec(
|
||||||
|
cmd: 'ls "$_serviceDDirPath/$packageName.sh"',
|
||||||
|
);
|
||||||
|
return res != null && res.isNotEmpty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<String>> getInstalledApps() async {
|
||||||
try {
|
try {
|
||||||
String? res = await Root.exec(
|
String? res = await Root.exec(
|
||||||
cmd: 'ls -la "$_managerDirPath/$packageName"',
|
cmd: 'ls "$_managerDirPath"',
|
||||||
);
|
);
|
||||||
return res != null && res.isNotEmpty;
|
if (res != null) {
|
||||||
|
List<String> apps = res.split('\n');
|
||||||
|
for (String packageName in apps) {
|
||||||
|
bool isInstalled = await isAppInstalled(packageName);
|
||||||
|
if (!isInstalled) {
|
||||||
|
apps.remove(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} on Exception {
|
} on Exception {
|
||||||
return false;
|
return List.empty();
|
||||||
}
|
}
|
||||||
|
return List.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteApp(String packageName, String originalFilePath) async {
|
Future<void> deleteApp(String packageName, String originalFilePath) async {
|
||||||
|
@ -19,7 +19,7 @@ import 'package:stacked/stacked.dart';
|
|||||||
|
|
||||||
@lazySingleton
|
@lazySingleton
|
||||||
class HomeViewModel extends BaseViewModel {
|
class HomeViewModel extends BaseViewModel {
|
||||||
final ManagerAPI _managerAPI = ManagerAPI();
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
|
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
|
||||||
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||||
FlutterLocalNotificationsPlugin();
|
FlutterLocalNotificationsPlugin();
|
||||||
@ -49,11 +49,10 @@ class HomeViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<PatchedApplication>> getPatchedApps(bool isUpdatable) async {
|
Future<List<PatchedApplication>> getPatchedApps(bool isUpdatable) async {
|
||||||
|
await _managerAPI.reAssessSavedApps();
|
||||||
List<PatchedApplication> list = [];
|
List<PatchedApplication> list = [];
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
List<PatchedApplication> patchedApps = _managerAPI.getPatchedApps();
|
||||||
List<String> patchedApps = prefs.getStringList('patchedApps') ?? [];
|
for (PatchedApplication app in patchedApps) {
|
||||||
for (String str in patchedApps) {
|
|
||||||
PatchedApplication app = PatchedApplication.fromJson(json.decode(str));
|
|
||||||
bool hasUpdates = await _managerAPI.hasAppUpdates(app.packageName);
|
bool hasUpdates = await _managerAPI.hasAppUpdates(app.packageName);
|
||||||
if (hasUpdates == isUpdatable) {
|
if (hasUpdates == isUpdatable) {
|
||||||
list.add(app);
|
list.add(app);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'package:device_apps/device_apps.dart';
|
import 'package:device_apps/device_apps.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -7,19 +6,20 @@ import 'package:flutter_i18n/flutter_i18n.dart';
|
|||||||
import 'package:revanced_manager/app/app.locator.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/models/patch.dart';
|
import 'package:revanced_manager/models/patch.dart';
|
||||||
import 'package:revanced_manager/models/patched_application.dart';
|
import 'package:revanced_manager/models/patched_application.dart';
|
||||||
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/services/patcher_api.dart';
|
import 'package:revanced_manager/services/patcher_api.dart';
|
||||||
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
class InstallerViewModel extends BaseViewModel {
|
class InstallerViewModel extends BaseViewModel {
|
||||||
final ScrollController scrollController = ScrollController();
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
|
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
|
||||||
final PatchedApplication? _app = locator<PatcherViewModel>().selectedApp;
|
final PatchedApplication? _app = locator<PatcherViewModel>().selectedApp;
|
||||||
final List<Patch> _patches = locator<PatcherViewModel>().selectedPatches;
|
final List<Patch> _patches = locator<PatcherViewModel>().selectedPatches;
|
||||||
static const _installerChannel = MethodChannel(
|
static const _installerChannel = MethodChannel(
|
||||||
'app.revanced.manager/installer',
|
'app.revanced.manager/installer',
|
||||||
);
|
);
|
||||||
|
final ScrollController scrollController = ScrollController();
|
||||||
double? progress = 0.0;
|
double? progress = 0.0;
|
||||||
String logs = '';
|
String logs = '';
|
||||||
String headerLogs = '';
|
String headerLogs = '';
|
||||||
@ -148,10 +148,10 @@ class InstallerViewModel extends BaseViewModel {
|
|||||||
);
|
);
|
||||||
isInstalled = await _patcherAPI.installPatchedFile(_app!);
|
isInstalled = await _patcherAPI.installPatchedFile(_app!);
|
||||||
if (isInstalled) {
|
if (isInstalled) {
|
||||||
update(1.0, 'Installed...', 'Installed');
|
update(1.0, 'Installed!', 'Installed');
|
||||||
_app!.patchDate = DateTime.now();
|
_app!.patchDate = DateTime.now();
|
||||||
_app!.appliedPatches.addAll(_patches.map((p) => p.name).toList());
|
_app!.appliedPatches.addAll(_patches.map((p) => p.name).toList());
|
||||||
await saveApp();
|
_managerAPI.savePatchedApp(_app!);
|
||||||
} else {
|
} else {
|
||||||
update(1.0, 'Aborting...', 'An error occurred! Aborting');
|
update(1.0, 'Aborting...', 'An error occurred! Aborting');
|
||||||
}
|
}
|
||||||
@ -176,16 +176,4 @@ class InstallerViewModel extends BaseViewModel {
|
|||||||
DeviceApps.openApp(_app!.packageName);
|
DeviceApps.openApp(_app!.packageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveApp() async {
|
|
||||||
if (_app != null) {
|
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
||||||
List<String> patchedApps = prefs.getStringList('patchedApps') ?? [];
|
|
||||||
String appStr = json.encode(_app!.toJson());
|
|
||||||
patchedApps.removeWhere(
|
|
||||||
(a) => json.decode(a)['packageName'] == _app!.packageName);
|
|
||||||
patchedApps.add(appStr);
|
|
||||||
prefs.setStringList('patchedApps', patchedApps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ class AvailableUpdatesCard extends StatelessWidget {
|
|||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final ManagerAPI _managerAPI = ManagerAPI();
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -11,7 +11,7 @@ class InstalledAppsCard extends StatelessWidget {
|
|||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final ManagerAPI _managerAPI = ManagerAPI();
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
Loading…
Reference in New Issue
Block a user