capacitor-dex-editor 0.0.59 → 0.0.60
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.
|
@@ -601,6 +601,22 @@ public class DexEditorPluginPlugin extends Plugin {
|
|
|
601
601
|
));
|
|
602
602
|
break;
|
|
603
603
|
|
|
604
|
+
case "deleteFileFromApk":
|
|
605
|
+
result.put("data", dexManager.deleteFileFromApk(
|
|
606
|
+
params.getString("apkPath"),
|
|
607
|
+
params.getString("filePath")
|
|
608
|
+
));
|
|
609
|
+
break;
|
|
610
|
+
|
|
611
|
+
case "addFileToApk":
|
|
612
|
+
result.put("data", dexManager.addFileToApk(
|
|
613
|
+
params.getString("apkPath"),
|
|
614
|
+
params.getString("filePath"),
|
|
615
|
+
params.getString("content"),
|
|
616
|
+
params.optBoolean("isBase64", false)
|
|
617
|
+
));
|
|
618
|
+
break;
|
|
619
|
+
|
|
604
620
|
case "listSessions":
|
|
605
621
|
result.put("data", dexManager.listAllSessions());
|
|
606
622
|
break;
|
|
@@ -2332,6 +2332,156 @@ public class DexManager {
|
|
|
2332
2332
|
return result;
|
|
2333
2333
|
}
|
|
2334
2334
|
|
|
2335
|
+
/**
|
|
2336
|
+
* 从 APK 中删除指定文件
|
|
2337
|
+
*/
|
|
2338
|
+
public JSObject deleteFileFromApk(String apkPath, String filePath) throws Exception {
|
|
2339
|
+
JSObject result = new JSObject();
|
|
2340
|
+
|
|
2341
|
+
java.io.File apkFile = new java.io.File(apkPath);
|
|
2342
|
+
java.io.File tempApkFile = new java.io.File(apkPath + ".tmp");
|
|
2343
|
+
|
|
2344
|
+
java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(new java.io.FileInputStream(apkFile));
|
|
2345
|
+
java.util.zip.ZipOutputStream zos = new java.util.zip.ZipOutputStream(new java.io.FileOutputStream(tempApkFile));
|
|
2346
|
+
|
|
2347
|
+
java.util.zip.ZipEntry entry;
|
|
2348
|
+
boolean found = false;
|
|
2349
|
+
String normalizedPath = filePath.replaceFirst("^/+", "");
|
|
2350
|
+
|
|
2351
|
+
while ((entry = zis.getNextEntry()) != null) {
|
|
2352
|
+
String entryName = entry.getName();
|
|
2353
|
+
|
|
2354
|
+
if (entryName.equals(filePath) || entryName.equals(normalizedPath)) {
|
|
2355
|
+
// 跳过要删除的文件
|
|
2356
|
+
found = true;
|
|
2357
|
+
continue;
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
// 复制其他文件
|
|
2361
|
+
java.util.zip.ZipEntry newEntry = new java.util.zip.ZipEntry(entryName);
|
|
2362
|
+
if (entry.getMethod() == java.util.zip.ZipEntry.STORED) {
|
|
2363
|
+
newEntry.setMethod(java.util.zip.ZipEntry.STORED);
|
|
2364
|
+
newEntry.setSize(entry.getSize());
|
|
2365
|
+
newEntry.setCrc(entry.getCrc());
|
|
2366
|
+
}
|
|
2367
|
+
zos.putNextEntry(newEntry);
|
|
2368
|
+
|
|
2369
|
+
byte[] buffer = new byte[8192];
|
|
2370
|
+
int len;
|
|
2371
|
+
while ((len = zis.read(buffer)) > 0) {
|
|
2372
|
+
zos.write(buffer, 0, len);
|
|
2373
|
+
}
|
|
2374
|
+
zos.closeEntry();
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
zis.close();
|
|
2378
|
+
zos.close();
|
|
2379
|
+
|
|
2380
|
+
if (!found) {
|
|
2381
|
+
tempApkFile.delete();
|
|
2382
|
+
result.put("success", false);
|
|
2383
|
+
result.put("error", "文件未找到: " + filePath);
|
|
2384
|
+
return result;
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
// 替换原文件
|
|
2388
|
+
if (!apkFile.delete()) {
|
|
2389
|
+
tempApkFile.delete();
|
|
2390
|
+
result.put("success", false);
|
|
2391
|
+
result.put("error", "无法删除原 APK");
|
|
2392
|
+
return result;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
if (!tempApkFile.renameTo(apkFile)) {
|
|
2396
|
+
copyFile(tempApkFile, apkFile);
|
|
2397
|
+
tempApkFile.delete();
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
result.put("success", true);
|
|
2401
|
+
result.put("message", "文件已删除: " + filePath);
|
|
2402
|
+
result.put("needSign", true);
|
|
2403
|
+
return result;
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
/**
|
|
2407
|
+
* 向 APK 中添加或替换文件
|
|
2408
|
+
*/
|
|
2409
|
+
public JSObject addFileToApk(String apkPath, String filePath, String content, boolean isBase64) throws Exception {
|
|
2410
|
+
JSObject result = new JSObject();
|
|
2411
|
+
|
|
2412
|
+
// 解码内容
|
|
2413
|
+
byte[] contentBytes;
|
|
2414
|
+
if (isBase64) {
|
|
2415
|
+
contentBytes = android.util.Base64.decode(content, android.util.Base64.DEFAULT);
|
|
2416
|
+
} else {
|
|
2417
|
+
contentBytes = content.getBytes("UTF-8");
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
java.io.File apkFile = new java.io.File(apkPath);
|
|
2421
|
+
java.io.File tempApkFile = new java.io.File(apkPath + ".tmp");
|
|
2422
|
+
|
|
2423
|
+
java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(new java.io.FileInputStream(apkFile));
|
|
2424
|
+
java.util.zip.ZipOutputStream zos = new java.util.zip.ZipOutputStream(new java.io.FileOutputStream(tempApkFile));
|
|
2425
|
+
|
|
2426
|
+
java.util.zip.ZipEntry entry;
|
|
2427
|
+
String normalizedPath = filePath.replaceFirst("^/+", "");
|
|
2428
|
+
boolean replaced = false;
|
|
2429
|
+
|
|
2430
|
+
while ((entry = zis.getNextEntry()) != null) {
|
|
2431
|
+
String entryName = entry.getName();
|
|
2432
|
+
|
|
2433
|
+
if (entryName.equals(filePath) || entryName.equals(normalizedPath)) {
|
|
2434
|
+
// 跳过要替换的文件,稍后添加新版本
|
|
2435
|
+
replaced = true;
|
|
2436
|
+
continue;
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
// 复制其他文件
|
|
2440
|
+
java.util.zip.ZipEntry newEntry = new java.util.zip.ZipEntry(entryName);
|
|
2441
|
+
if (entry.getMethod() == java.util.zip.ZipEntry.STORED) {
|
|
2442
|
+
newEntry.setMethod(java.util.zip.ZipEntry.STORED);
|
|
2443
|
+
newEntry.setSize(entry.getSize());
|
|
2444
|
+
newEntry.setCrc(entry.getCrc());
|
|
2445
|
+
}
|
|
2446
|
+
zos.putNextEntry(newEntry);
|
|
2447
|
+
|
|
2448
|
+
byte[] buffer = new byte[8192];
|
|
2449
|
+
int len;
|
|
2450
|
+
while ((len = zis.read(buffer)) > 0) {
|
|
2451
|
+
zos.write(buffer, 0, len);
|
|
2452
|
+
}
|
|
2453
|
+
zos.closeEntry();
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
// 添加新文件
|
|
2457
|
+
java.util.zip.ZipEntry newEntry = new java.util.zip.ZipEntry(normalizedPath);
|
|
2458
|
+
newEntry.setSize(contentBytes.length);
|
|
2459
|
+
zos.putNextEntry(newEntry);
|
|
2460
|
+
zos.write(contentBytes);
|
|
2461
|
+
zos.closeEntry();
|
|
2462
|
+
|
|
2463
|
+
zis.close();
|
|
2464
|
+
zos.close();
|
|
2465
|
+
|
|
2466
|
+
// 替换原文件
|
|
2467
|
+
if (!apkFile.delete()) {
|
|
2468
|
+
tempApkFile.delete();
|
|
2469
|
+
result.put("success", false);
|
|
2470
|
+
result.put("error", "无法删除原 APK");
|
|
2471
|
+
return result;
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
if (!tempApkFile.renameTo(apkFile)) {
|
|
2475
|
+
copyFile(tempApkFile, apkFile);
|
|
2476
|
+
tempApkFile.delete();
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
result.put("success", true);
|
|
2480
|
+
result.put("message", replaced ? "文件已替换: " + filePath : "文件已添加: " + filePath);
|
|
2481
|
+
result.put("needSign", true);
|
|
2482
|
+
return result;
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2335
2485
|
/**
|
|
2336
2486
|
* 保存多 DEX 会话的修改到 APK
|
|
2337
2487
|
*/
|