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
- getActivity().runOnUiThread(() -> {
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
- // TODO: 将编译后的 dex 合并回原 APK
1683
- // 这是一个复杂的操作,需要:
1684
- // 1. 解压 APK
1685
- // 2. 替换/合并 DEX 文件中的类
1686
- // 3. 重新打包 APK
1687
- // 4. 重新签名 APK
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("compiledDexPath", outputDex.getAbsolutePath());
1755
+ result.put("message", "Smali 编译成功!修改后的 DEX 已保存");
1756
+ result.put("modifiedDexPath", outputDexFile.getAbsolutePath());
1757
+ result.put("note", "请使用 MT 管理器或其他工具将修改后的 DEX 替换到 APK 中");
1693
1758
 
1694
- // 清理临时文件(暂时保留以便调试)
1695
- // cleanupTempDir(tempDir);
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
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-dex-editor",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "description": "Capacitor-plugin-for-editing-DEX-files-in-APK",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",