capacitor-dex-editor 0.0.17 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -44,7 +44,7 @@ public class DexEditorPluginPlugin extends Plugin {
|
|
|
44
44
|
Log.d(TAG, "Executing action: " + action);
|
|
45
45
|
|
|
46
46
|
// 在后台线程执行,避免阻塞UI
|
|
47
|
-
|
|
47
|
+
new Thread(() -> {
|
|
48
48
|
try {
|
|
49
49
|
JSObject result = dispatchAction(action, params);
|
|
50
50
|
call.resolve(result);
|
|
@@ -55,7 +55,7 @@ public class DexEditorPluginPlugin extends Plugin {
|
|
|
55
55
|
error.put("error", e.getMessage());
|
|
56
56
|
call.resolve(error);
|
|
57
57
|
}
|
|
58
|
-
});
|
|
58
|
+
}).start();
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -1679,20 +1679,85 @@ public class DexManager {
|
|
|
1679
1679
|
|
|
1680
1680
|
Log.d(TAG, "Smali compiled successfully to: " + outputDex.getAbsolutePath());
|
|
1681
1681
|
|
|
1682
|
-
//
|
|
1683
|
-
//
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1682
|
+
// 将编译后的类合并到原 DEX 文件中
|
|
1683
|
+
// 1. 读取原 APK 中的 DEX 文件
|
|
1684
|
+
java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(apkPath);
|
|
1685
|
+
java.util.zip.ZipEntry dexEntry = zipFile.getEntry(dexPath);
|
|
1686
|
+
|
|
1687
|
+
if (dexEntry == null) {
|
|
1688
|
+
result.put("success", false);
|
|
1689
|
+
result.put("error", "DEX 文件未找到: " + dexPath);
|
|
1690
|
+
zipFile.close();
|
|
1691
|
+
cleanupTempDir(tempDir);
|
|
1692
|
+
return result;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
// 读取原 DEX
|
|
1696
|
+
java.io.InputStream dexInputStream = zipFile.getInputStream(dexEntry);
|
|
1697
|
+
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
|
|
1698
|
+
byte[] buffer = new byte[8192];
|
|
1699
|
+
int len;
|
|
1700
|
+
while ((len = dexInputStream.read(buffer)) != -1) {
|
|
1701
|
+
baos.write(buffer, 0, len);
|
|
1702
|
+
}
|
|
1703
|
+
byte[] originalDexBytes = baos.toByteArray();
|
|
1704
|
+
dexInputStream.close();
|
|
1705
|
+
|
|
1706
|
+
// 解析原 DEX 和新编译的 DEX
|
|
1707
|
+
DexBackedDexFile originalDex = new DexBackedDexFile(Opcodes.getDefault(), originalDexBytes);
|
|
1708
|
+
DexBackedDexFile newDex = DexBackedDexFile.fromInputStream(Opcodes.getDefault(),
|
|
1709
|
+
new java.io.BufferedInputStream(new java.io.FileInputStream(outputDex)));
|
|
1710
|
+
|
|
1711
|
+
// 合并 DEX:用新类替换原类
|
|
1712
|
+
String targetType = "L" + className.replace(".", "/") + ";";
|
|
1713
|
+
java.util.List<ClassDef> mergedClasses = new java.util.ArrayList<>();
|
|
1714
|
+
|
|
1715
|
+
// 添加原 DEX 中除目标类外的所有类
|
|
1716
|
+
for (ClassDef classDef : originalDex.getClasses()) {
|
|
1717
|
+
if (!classDef.getType().equals(targetType)) {
|
|
1718
|
+
mergedClasses.add(classDef);
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
// 添加新编译的类
|
|
1723
|
+
for (ClassDef classDef : newDex.getClasses()) {
|
|
1724
|
+
mergedClasses.add(classDef);
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
Log.d(TAG, "Merged " + mergedClasses.size() + " classes");
|
|
1728
|
+
|
|
1729
|
+
// 创建新的 DEX 文件
|
|
1730
|
+
java.io.File mergedDexFile = new java.io.File(tempDir, "classes_merged.dex");
|
|
1731
|
+
DexPool dexPool = new DexPool(Opcodes.getDefault());
|
|
1732
|
+
for (ClassDef classDef : mergedClasses) {
|
|
1733
|
+
dexPool.internClass(classDef);
|
|
1734
|
+
}
|
|
1735
|
+
dexPool.writeTo(new FileDataStore(mergedDexFile));
|
|
1736
|
+
|
|
1737
|
+
Log.d(TAG, "Merged DEX written to: " + mergedDexFile.getAbsolutePath());
|
|
1738
|
+
|
|
1739
|
+
// 2. 直接替换 APK 中的 DEX(使用 RandomAccessFile 原地修改,避免复制整个 APK)
|
|
1740
|
+
// 简化方案:只保存修改后的 DEX 到输出目录,让用户手动替换或使用其他工具
|
|
1741
|
+
java.io.File outputDir = new java.io.File(new java.io.File(apkPath).getParent(), "dex_modified");
|
|
1742
|
+
if (!outputDir.exists()) {
|
|
1743
|
+
outputDir.mkdirs();
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
// 复制修改后的 DEX 到输出目录
|
|
1747
|
+
java.io.File outputDexFile = new java.io.File(outputDir, dexPath);
|
|
1748
|
+
copyFile(mergedDexFile, outputDexFile);
|
|
1749
|
+
|
|
1750
|
+
Log.d(TAG, "Modified DEX saved to: " + outputDexFile.getAbsolutePath());
|
|
1751
|
+
|
|
1752
|
+
zipFile.close();
|
|
1753
|
+
|
|
1690
1754
|
result.put("success", true);
|
|
1691
|
-
result.put("message", "Smali
|
|
1692
|
-
result.put("
|
|
1755
|
+
result.put("message", "Smali 编译成功!修改后的 DEX 已保存");
|
|
1756
|
+
result.put("modifiedDexPath", outputDexFile.getAbsolutePath());
|
|
1757
|
+
result.put("note", "请使用 MT 管理器或其他工具将修改后的 DEX 替换到 APK 中");
|
|
1693
1758
|
|
|
1694
|
-
//
|
|
1695
|
-
|
|
1759
|
+
// 清理临时文件
|
|
1760
|
+
cleanupTempDir(tempDir);
|
|
1696
1761
|
|
|
1697
1762
|
} catch (Exception e) {
|
|
1698
1763
|
Log.e(TAG, "Error saving smali: " + e.getMessage(), e);
|
|
@@ -1703,6 +1768,21 @@ public class DexManager {
|
|
|
1703
1768
|
return result;
|
|
1704
1769
|
}
|
|
1705
1770
|
|
|
1771
|
+
/**
|
|
1772
|
+
* 复制文件
|
|
1773
|
+
*/
|
|
1774
|
+
private void copyFile(java.io.File src, java.io.File dst) throws java.io.IOException {
|
|
1775
|
+
java.io.FileInputStream fis = new java.io.FileInputStream(src);
|
|
1776
|
+
java.io.FileOutputStream fos = new java.io.FileOutputStream(dst);
|
|
1777
|
+
byte[] buffer = new byte[8192];
|
|
1778
|
+
int len;
|
|
1779
|
+
while ((len = fis.read(buffer)) != -1) {
|
|
1780
|
+
fos.write(buffer, 0, len);
|
|
1781
|
+
}
|
|
1782
|
+
fis.close();
|
|
1783
|
+
fos.close();
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1706
1786
|
/**
|
|
1707
1787
|
* 清理临时目录
|
|
1708
1788
|
*/
|