mirror of
https://github.com/revanced/revanced-manager.git
synced 2025-05-02 23:04:25 +02:00
fix: One more fix to root installations management
This commit is contained in:
parent
c92b889cd9
commit
6ef716b0e4
@ -31,18 +31,9 @@ class MainActivity : FlutterActivity() {
|
|||||||
installerChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, INSTALLER_CHANNEL)
|
installerChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, INSTALLER_CHANNEL)
|
||||||
mainChannel.setMethodCallHandler { call, result ->
|
mainChannel.setMethodCallHandler { call, result ->
|
||||||
when (call.method) {
|
when (call.method) {
|
||||||
"copyOriginalApk" -> {
|
|
||||||
val originalFilePath = call.argument<String>("originalFilePath")
|
|
||||||
val backupFilePath = call.argument<String>("backupFilePath")
|
|
||||||
if (originalFilePath != null && backupFilePath != null) {
|
|
||||||
File(originalFilePath).copyTo(File(backupFilePath), true)
|
|
||||||
result.success(null)
|
|
||||||
} else {
|
|
||||||
result.notImplemented()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"runPatcher" -> {
|
"runPatcher" -> {
|
||||||
val patchBundleFilePath = call.argument<String>("patchBundleFilePath")
|
val patchBundleFilePath = call.argument<String>("patchBundleFilePath")
|
||||||
|
val originalFilePath = call.argument<String>("originalFilePath")
|
||||||
val inputFilePath = call.argument<String>("inputFilePath")
|
val inputFilePath = call.argument<String>("inputFilePath")
|
||||||
val patchedFilePath = call.argument<String>("patchedFilePath")
|
val patchedFilePath = call.argument<String>("patchedFilePath")
|
||||||
val outFilePath = call.argument<String>("outFilePath")
|
val outFilePath = call.argument<String>("outFilePath")
|
||||||
@ -53,6 +44,7 @@ class MainActivity : FlutterActivity() {
|
|||||||
val resourcePatching = call.argument<Boolean>("resourcePatching")
|
val resourcePatching = call.argument<Boolean>("resourcePatching")
|
||||||
val keyStoreFilePath = call.argument<String>("keyStoreFilePath")
|
val keyStoreFilePath = call.argument<String>("keyStoreFilePath")
|
||||||
if (patchBundleFilePath != null &&
|
if (patchBundleFilePath != null &&
|
||||||
|
originalFilePath != null &&
|
||||||
inputFilePath != null &&
|
inputFilePath != null &&
|
||||||
patchedFilePath != null &&
|
patchedFilePath != null &&
|
||||||
outFilePath != null &&
|
outFilePath != null &&
|
||||||
@ -66,6 +58,7 @@ class MainActivity : FlutterActivity() {
|
|||||||
runPatcher(
|
runPatcher(
|
||||||
result,
|
result,
|
||||||
patchBundleFilePath,
|
patchBundleFilePath,
|
||||||
|
originalFilePath,
|
||||||
inputFilePath,
|
inputFilePath,
|
||||||
patchedFilePath,
|
patchedFilePath,
|
||||||
outFilePath,
|
outFilePath,
|
||||||
@ -88,6 +81,7 @@ class MainActivity : FlutterActivity() {
|
|||||||
fun runPatcher(
|
fun runPatcher(
|
||||||
result: MethodChannel.Result,
|
result: MethodChannel.Result,
|
||||||
patchBundleFilePath: String,
|
patchBundleFilePath: String,
|
||||||
|
originalFilePath: String,
|
||||||
inputFilePath: String,
|
inputFilePath: String,
|
||||||
patchedFilePath: String,
|
patchedFilePath: String,
|
||||||
outFilePath: String,
|
outFilePath: String,
|
||||||
@ -98,6 +92,7 @@ class MainActivity : FlutterActivity() {
|
|||||||
resourcePatching: Boolean,
|
resourcePatching: Boolean,
|
||||||
keyStoreFilePath: String
|
keyStoreFilePath: String
|
||||||
) {
|
) {
|
||||||
|
val originalFile = File(originalFilePath)
|
||||||
val inputFile = File(inputFilePath)
|
val inputFile = File(inputFilePath)
|
||||||
val patchedFile = File(patchedFilePath)
|
val patchedFile = File(patchedFilePath)
|
||||||
val outFile = File(outFilePath)
|
val outFile = File(outFilePath)
|
||||||
@ -119,6 +114,18 @@ class MainActivity : FlutterActivity() {
|
|||||||
|
|
||||||
Thread(
|
Thread(
|
||||||
Runnable {
|
Runnable {
|
||||||
|
handler.post {
|
||||||
|
installerChannel.invokeMethod(
|
||||||
|
"update",
|
||||||
|
mapOf(
|
||||||
|
"progress" to 0.1,
|
||||||
|
"header" to "",
|
||||||
|
"log" to "Copying original apk"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
originalFile.copyTo(inputFile, true)
|
||||||
|
|
||||||
handler.post {
|
handler.post {
|
||||||
installerChannel.invokeMethod(
|
installerChannel.invokeMethod(
|
||||||
"update",
|
"update",
|
||||||
|
@ -82,31 +82,23 @@ class PatcherAPI {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> copyOriginalApk(
|
Future<String> getOriginalFilePath(
|
||||||
String packageName,
|
String packageName,
|
||||||
String originalFilePath,
|
String originalFilePath,
|
||||||
) async {
|
) async {
|
||||||
bool hasRootPermissions = await _rootAPI.hasRootPermissions();
|
bool hasRootPermissions = await _rootAPI.hasRootPermissions();
|
||||||
if (hasRootPermissions) {
|
if (hasRootPermissions) {
|
||||||
String originalRootPath = await _rootAPI.getOriginalFilePath(packageName);
|
originalFilePath = await _rootAPI.getOriginalFilePath(
|
||||||
if (File(originalRootPath).existsSync()) {
|
packageName,
|
||||||
originalFilePath = originalRootPath;
|
originalFilePath,
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
String backupFilePath = '${_tmpDir.path}/$packageName.apk';
|
return originalFilePath;
|
||||||
await patcherChannel.invokeMethod(
|
|
||||||
'copyOriginalApk',
|
|
||||||
{
|
|
||||||
'originalFilePath': originalFilePath,
|
|
||||||
'backupFilePath': backupFilePath,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
return backupFilePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> runPatcher(
|
Future<void> runPatcher(
|
||||||
String packageName,
|
String packageName,
|
||||||
String inputFilePath,
|
String originalFilePath,
|
||||||
List<Patch> selectedPatches,
|
List<Patch> selectedPatches,
|
||||||
) async {
|
) async {
|
||||||
bool mergeIntegrations = selectedPatches.any(
|
bool mergeIntegrations = selectedPatches.any(
|
||||||
@ -140,6 +132,7 @@ class PatcherAPI {
|
|||||||
if (patchBundleFile != null) {
|
if (patchBundleFile != null) {
|
||||||
_tmpDir.createSync();
|
_tmpDir.createSync();
|
||||||
Directory workDir = _tmpDir.createTempSync('tmp-');
|
Directory workDir = _tmpDir.createTempSync('tmp-');
|
||||||
|
File inputFile = File('${workDir.path}/base.apk');
|
||||||
File patchedFile = File('${workDir.path}/patched.apk');
|
File patchedFile = File('${workDir.path}/patched.apk');
|
||||||
_outFile = File('${workDir.path}/out.apk');
|
_outFile = File('${workDir.path}/out.apk');
|
||||||
Directory cacheDir = Directory('${workDir.path}/cache');
|
Directory cacheDir = Directory('${workDir.path}/cache');
|
||||||
@ -148,7 +141,11 @@ class PatcherAPI {
|
|||||||
'runPatcher',
|
'runPatcher',
|
||||||
{
|
{
|
||||||
'patchBundleFilePath': patchBundleFile.path,
|
'patchBundleFilePath': patchBundleFile.path,
|
||||||
'inputFilePath': inputFilePath,
|
'originalFilePath': await getOriginalFilePath(
|
||||||
|
packageName,
|
||||||
|
originalFilePath,
|
||||||
|
),
|
||||||
|
'inputFilePath': inputFile.path,
|
||||||
'patchedFilePath': patchedFile.path,
|
'patchedFilePath': patchedFile.path,
|
||||||
'outFilePath': _outFile!.path,
|
'outFilePath': _outFile!.path,
|
||||||
'integrationsPath': mergeIntegrations ? integrationsFile!.path : '',
|
'integrationsPath': mergeIntegrations ? integrationsFile!.path : '',
|
||||||
|
@ -2,6 +2,7 @@ import 'package:root/root.dart';
|
|||||||
|
|
||||||
class RootAPI {
|
class RootAPI {
|
||||||
final String _managerDirPath = '/data/adb/revanced-manager';
|
final String _managerDirPath = '/data/adb/revanced-manager';
|
||||||
|
final String _managerTmpDirPath = '/data/local/tmp/revanced-manager';
|
||||||
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';
|
||||||
|
|
||||||
@ -10,6 +11,29 @@ class RootAPI {
|
|||||||
return isRooted != null && isRooted;
|
return isRooted != null && isRooted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> setPermissions(
|
||||||
|
String permissions,
|
||||||
|
ownerGroup,
|
||||||
|
seLinux,
|
||||||
|
String filePath,
|
||||||
|
) async {
|
||||||
|
if (permissions.isNotEmpty) {
|
||||||
|
await Root.exec(
|
||||||
|
cmd: 'chmod $permissions "$filePath"',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (ownerGroup.isNotEmpty) {
|
||||||
|
await Root.exec(
|
||||||
|
cmd: 'chown $ownerGroup "$filePath"',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (seLinux.isNotEmpty) {
|
||||||
|
await Root.exec(
|
||||||
|
cmd: 'chcon $seLinux "$filePath"',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> isAppInstalled(String packageName) async {
|
Future<bool> isAppInstalled(String packageName) async {
|
||||||
if (packageName.isNotEmpty) {
|
if (packageName.isNotEmpty) {
|
||||||
String? res = await Root.exec(
|
String? res = await Root.exec(
|
||||||
@ -76,6 +100,7 @@ class RootAPI {
|
|||||||
await Root.exec(
|
await Root.exec(
|
||||||
cmd: 'mkdir -p "$_managerDirPath/$packageName"',
|
cmd: 'mkdir -p "$_managerDirPath/$packageName"',
|
||||||
);
|
);
|
||||||
|
await setPermissions('0755', '', '', "$_managerDirPath/$packageName");
|
||||||
await saveOriginalFilePath(packageName, originalFilePath);
|
await saveOriginalFilePath(packageName, originalFilePath);
|
||||||
await installServiceDScript(packageName);
|
await installServiceDScript(packageName);
|
||||||
await installPostFsDataScript(packageName);
|
await installPostFsDataScript(packageName);
|
||||||
@ -97,9 +122,7 @@ class RootAPI {
|
|||||||
await Root.exec(
|
await Root.exec(
|
||||||
cmd: 'echo \'$content\' > "$scriptFilePath"',
|
cmd: 'echo \'$content\' > "$scriptFilePath"',
|
||||||
);
|
);
|
||||||
await Root.exec(
|
await setPermissions('0744', '', '', scriptFilePath);
|
||||||
cmd: 'chmod 744 "$scriptFilePath"',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> installPostFsDataScript(String packageName) async {
|
Future<void> installPostFsDataScript(String packageName) async {
|
||||||
@ -110,9 +133,7 @@ class RootAPI {
|
|||||||
await Root.exec(
|
await Root.exec(
|
||||||
cmd: 'echo \'$content\' > "$scriptFilePath"',
|
cmd: 'echo \'$content\' > "$scriptFilePath"',
|
||||||
);
|
);
|
||||||
await Root.exec(
|
await setPermissions('0744', '', '', scriptFilePath);
|
||||||
cmd: 'chmod 744 "$scriptFilePath"',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> installApk(String packageName, String patchedFilePath) async {
|
Future<void> installApk(String packageName, String patchedFilePath) async {
|
||||||
@ -120,14 +141,11 @@ class RootAPI {
|
|||||||
await Root.exec(
|
await Root.exec(
|
||||||
cmd: 'cp "$patchedFilePath" "$newPatchedFilePath"',
|
cmd: 'cp "$patchedFilePath" "$newPatchedFilePath"',
|
||||||
);
|
);
|
||||||
await Root.exec(
|
await setPermissions(
|
||||||
cmd: 'chmod 644 "$newPatchedFilePath"',
|
'0644',
|
||||||
);
|
'system:system',
|
||||||
await Root.exec(
|
'u:object_r:apk_data_file:s0',
|
||||||
cmd: 'chown system:system "$newPatchedFilePath"',
|
newPatchedFilePath,
|
||||||
);
|
|
||||||
await Root.exec(
|
|
||||||
cmd: 'chcon u:object_r:apk_data_file:s0 "$newPatchedFilePath"',
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,17 +162,52 @@ class RootAPI {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getOriginalFilePath(String packageName) async {
|
Future<bool> isMounted(String packageName) async {
|
||||||
return '$_managerDirPath/$packageName/original.apk';
|
String? res = await Root.exec(
|
||||||
|
cmd: 'cat /proc/mounts | grep $packageName',
|
||||||
|
);
|
||||||
|
return res != null && res.isNotEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> getOriginalFilePath(
|
||||||
|
String packageName,
|
||||||
|
String originalFilePath,
|
||||||
|
) async {
|
||||||
|
bool isInstalled = await isAppInstalled(packageName);
|
||||||
|
if (isInstalled && await isMounted(packageName)) {
|
||||||
|
originalFilePath = '$_managerTmpDirPath/$packageName/original.apk';
|
||||||
|
await setPermissions(
|
||||||
|
'0644',
|
||||||
|
'shell:shell',
|
||||||
|
'u:object_r:apk_data_file:s0',
|
||||||
|
originalFilePath,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return originalFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveOriginalFilePath(
|
Future<void> saveOriginalFilePath(
|
||||||
String packageName,
|
String packageName,
|
||||||
String originalFilePath,
|
String originalFilePath,
|
||||||
) async {
|
) async {
|
||||||
String originalRootPath = '$_managerDirPath/$packageName/original.apk';
|
String originalRootPath = '$_managerTmpDirPath/$packageName/original.apk';
|
||||||
|
await Root.exec(
|
||||||
|
cmd: 'mkdir -p "$_managerTmpDirPath/$packageName"',
|
||||||
|
);
|
||||||
|
await setPermissions(
|
||||||
|
'0755',
|
||||||
|
'shell:shell',
|
||||||
|
'',
|
||||||
|
'$_managerTmpDirPath/$packageName',
|
||||||
|
);
|
||||||
await Root.exec(
|
await Root.exec(
|
||||||
cmd: 'cp "$originalFilePath" "$originalRootPath"',
|
cmd: 'cp "$originalFilePath" "$originalRootPath"',
|
||||||
);
|
);
|
||||||
|
await setPermissions(
|
||||||
|
'0644',
|
||||||
|
'shell:shell',
|
||||||
|
'u:object_r:apk_data_file:s0',
|
||||||
|
originalFilePath,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,15 +105,10 @@ class InstallerViewModel extends BaseViewModel {
|
|||||||
update(0.0, 'Initializing...', 'Initializing installer');
|
update(0.0, 'Initializing...', 'Initializing installer');
|
||||||
if (_patches.isNotEmpty) {
|
if (_patches.isNotEmpty) {
|
||||||
try {
|
try {
|
||||||
update(0.1, '', 'Copying original apk');
|
|
||||||
String inputFilePath = await _patcherAPI.copyOriginalApk(
|
|
||||||
_app.packageName,
|
|
||||||
_app.apkFilePath,
|
|
||||||
);
|
|
||||||
update(0.1, '', 'Creating working directory');
|
update(0.1, '', 'Creating working directory');
|
||||||
await _patcherAPI.runPatcher(
|
await _patcherAPI.runPatcher(
|
||||||
_app.packageName,
|
_app.packageName,
|
||||||
inputFilePath,
|
_app.apkFilePath,
|
||||||
_patches,
|
_patches,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user