capacitor-dex-editor 0.0.17 → 0.0.18
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.
|
@@ -1679,20 +1679,127 @@ 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(复制原 APK 并替换 DEX)
|
|
1740
|
+
java.io.File outputApk = new java.io.File(apkPath + ".modified.apk");
|
|
1741
|
+
java.util.zip.ZipOutputStream zos = new java.util.zip.ZipOutputStream(
|
|
1742
|
+
new java.io.FileOutputStream(outputApk));
|
|
1743
|
+
|
|
1744
|
+
// 复制原 APK 中的所有条目(除了要替换的 DEX)
|
|
1745
|
+
java.util.Enumeration<? extends java.util.zip.ZipEntry> entries = zipFile.entries();
|
|
1746
|
+
while (entries.hasMoreElements()) {
|
|
1747
|
+
java.util.zip.ZipEntry entry = entries.nextElement();
|
|
1748
|
+
if (entry.getName().equals(dexPath)) {
|
|
1749
|
+
// 跳过原 DEX,稍后添加新的
|
|
1750
|
+
continue;
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
// 复制其他条目
|
|
1754
|
+
java.util.zip.ZipEntry newEntry = new java.util.zip.ZipEntry(entry.getName());
|
|
1755
|
+
zos.putNextEntry(newEntry);
|
|
1756
|
+
|
|
1757
|
+
if (!entry.isDirectory()) {
|
|
1758
|
+
java.io.InputStream is = zipFile.getInputStream(entry);
|
|
1759
|
+
while ((len = is.read(buffer)) != -1) {
|
|
1760
|
+
zos.write(buffer, 0, len);
|
|
1761
|
+
}
|
|
1762
|
+
is.close();
|
|
1763
|
+
}
|
|
1764
|
+
zos.closeEntry();
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
// 添加修改后的 DEX
|
|
1768
|
+
java.util.zip.ZipEntry newDexEntry = new java.util.zip.ZipEntry(dexPath);
|
|
1769
|
+
zos.putNextEntry(newDexEntry);
|
|
1770
|
+
java.io.FileInputStream fis = new java.io.FileInputStream(mergedDexFile);
|
|
1771
|
+
while ((len = fis.read(buffer)) != -1) {
|
|
1772
|
+
zos.write(buffer, 0, len);
|
|
1773
|
+
}
|
|
1774
|
+
fis.close();
|
|
1775
|
+
zos.closeEntry();
|
|
1776
|
+
|
|
1777
|
+
zos.close();
|
|
1778
|
+
zipFile.close();
|
|
1779
|
+
|
|
1780
|
+
Log.d(TAG, "Modified APK written to: " + outputApk.getAbsolutePath());
|
|
1781
|
+
|
|
1782
|
+
// 3. 替换原 APK(先备份)
|
|
1783
|
+
java.io.File backupApk = new java.io.File(apkPath + ".backup");
|
|
1784
|
+
java.io.File originalApkFile = new java.io.File(apkPath);
|
|
1785
|
+
|
|
1786
|
+
// 复制原 APK 作为备份
|
|
1787
|
+
copyFile(originalApkFile, backupApk);
|
|
1788
|
+
|
|
1789
|
+
// 用修改后的 APK 替换原 APK
|
|
1790
|
+
copyFile(outputApk, originalApkFile);
|
|
1791
|
+
|
|
1792
|
+
// 删除临时修改的 APK
|
|
1793
|
+
outputApk.delete();
|
|
1794
|
+
|
|
1795
|
+
Log.d(TAG, "APK updated successfully. Backup at: " + backupApk.getAbsolutePath());
|
|
1796
|
+
|
|
1690
1797
|
result.put("success", true);
|
|
1691
|
-
result.put("message", "Smali
|
|
1692
|
-
result.put("
|
|
1798
|
+
result.put("message", "Smali 保存成功!已更新 APK");
|
|
1799
|
+
result.put("backupPath", backupApk.getAbsolutePath());
|
|
1693
1800
|
|
|
1694
|
-
//
|
|
1695
|
-
|
|
1801
|
+
// 清理临时文件
|
|
1802
|
+
cleanupTempDir(tempDir);
|
|
1696
1803
|
|
|
1697
1804
|
} catch (Exception e) {
|
|
1698
1805
|
Log.e(TAG, "Error saving smali: " + e.getMessage(), e);
|
|
@@ -1703,6 +1810,21 @@ public class DexManager {
|
|
|
1703
1810
|
return result;
|
|
1704
1811
|
}
|
|
1705
1812
|
|
|
1813
|
+
/**
|
|
1814
|
+
* 复制文件
|
|
1815
|
+
*/
|
|
1816
|
+
private void copyFile(java.io.File src, java.io.File dst) throws java.io.IOException {
|
|
1817
|
+
java.io.FileInputStream fis = new java.io.FileInputStream(src);
|
|
1818
|
+
java.io.FileOutputStream fos = new java.io.FileOutputStream(dst);
|
|
1819
|
+
byte[] buffer = new byte[8192];
|
|
1820
|
+
int len;
|
|
1821
|
+
while ((len = fis.read(buffer)) != -1) {
|
|
1822
|
+
fos.write(buffer, 0, len);
|
|
1823
|
+
}
|
|
1824
|
+
fis.close();
|
|
1825
|
+
fos.close();
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1706
1828
|
/**
|
|
1707
1829
|
* 清理临时目录
|
|
1708
1830
|
*/
|