capacitor-dex-editor 0.0.4 → 0.0.6

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.
@@ -1,11 +1,16 @@
1
1
  package com.aetherlink.dexeditor;
2
2
 
3
3
  import android.content.Context;
4
+ import android.content.Intent;
4
5
  import android.content.pm.PackageInfo;
5
6
  import android.content.pm.PackageManager;
6
7
  import android.content.pm.Signature;
8
+ import android.net.Uri;
9
+ import android.os.Build;
7
10
  import android.util.Log;
8
11
 
12
+ import androidx.core.content.FileProvider;
13
+
9
14
  import com.getcapacitor.JSArray;
10
15
  import com.getcapacitor.JSObject;
11
16
 
@@ -365,6 +370,145 @@ public class ApkManager {
365
370
  return result;
366
371
  }
367
372
 
373
+ /**
374
+ * 安装 APK
375
+ */
376
+ public void installApk(String apkPath) throws Exception {
377
+ if (context == null) {
378
+ throw new Exception("Context not available");
379
+ }
380
+
381
+ File apkFile = new File(apkPath);
382
+ if (!apkFile.exists()) {
383
+ throw new IOException("APK file not found: " + apkPath);
384
+ }
385
+
386
+ Intent intent = new Intent(Intent.ACTION_VIEW);
387
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
388
+
389
+ Uri apkUri;
390
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
391
+ // Android 7.0+ 需要使用 FileProvider
392
+ String authority = context.getPackageName() + ".fileprovider";
393
+ apkUri = FileProvider.getUriForFile(context, authority, apkFile);
394
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
395
+ } else {
396
+ apkUri = Uri.fromFile(apkFile);
397
+ }
398
+
399
+ intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
400
+ context.startActivity(intent);
401
+
402
+ Log.d(TAG, "Started APK installation: " + apkPath);
403
+ }
404
+
405
+ /**
406
+ * 列出 APK 指定目录的内容(支持目录导航)
407
+ */
408
+ public JSObject listApkDirectory(String apkPath, String directory) throws Exception {
409
+ File apkFile = new File(apkPath);
410
+ if (!apkFile.exists()) {
411
+ throw new IOException("APK file not found: " + apkPath);
412
+ }
413
+
414
+ // 规范化目录路径
415
+ if (directory == null) directory = "";
416
+ if (directory.startsWith("/")) directory = directory.substring(1);
417
+ if (!directory.isEmpty() && !directory.endsWith("/")) directory += "/";
418
+
419
+ JSObject result = new JSObject();
420
+ result.put("currentPath", directory.isEmpty() ? "/" : "/" + directory);
421
+
422
+ JSArray items = new JSArray();
423
+ int folderCount = 0;
424
+ int fileCount = 0;
425
+
426
+ // 用于跟踪已添加的目录
427
+ java.util.Set<String> addedDirs = new java.util.HashSet<>();
428
+
429
+ try (ZipFile zipFile = new ZipFile(apkFile)) {
430
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
431
+ while (entries.hasMoreElements()) {
432
+ ZipEntry entry = entries.nextElement();
433
+ String name = entry.getName();
434
+
435
+ // 如果指定了目录,只显示该目录下的内容
436
+ if (!directory.isEmpty()) {
437
+ if (!name.startsWith(directory)) continue;
438
+ name = name.substring(directory.length());
439
+ }
440
+
441
+ if (name.isEmpty()) continue;
442
+
443
+ // 检查是否是直接子项(不包含更深层的路径)
444
+ int slashIndex = name.indexOf('/');
445
+ boolean isDirectChild = slashIndex == -1 || slashIndex == name.length() - 1;
446
+
447
+ if (isDirectChild) {
448
+ // 直接子项
449
+ JSObject item = new JSObject();
450
+ String displayName = name.endsWith("/") ? name.substring(0, name.length() - 1) : name;
451
+ item.put("name", displayName);
452
+ item.put("path", directory + name);
453
+ item.put("isDirectory", entry.isDirectory());
454
+ item.put("size", entry.getSize());
455
+ item.put("compressedSize", entry.getCompressedSize());
456
+ item.put("lastModified", entry.getTime());
457
+
458
+ // 根据文件类型设置图标类型
459
+ item.put("type", getFileType(displayName, entry.isDirectory()));
460
+
461
+ items.put(item);
462
+ if (entry.isDirectory()) folderCount++;
463
+ else fileCount++;
464
+ } else {
465
+ // 子目录中的文件,添加其父目录
466
+ String dirName = name.substring(0, slashIndex);
467
+ if (!addedDirs.contains(dirName)) {
468
+ addedDirs.add(dirName);
469
+
470
+ JSObject item = new JSObject();
471
+ item.put("name", dirName);
472
+ item.put("path", directory + dirName + "/");
473
+ item.put("isDirectory", true);
474
+ item.put("size", 0);
475
+ item.put("type", "folder");
476
+
477
+ items.put(item);
478
+ folderCount++;
479
+ }
480
+ }
481
+ }
482
+ }
483
+
484
+ result.put("items", items);
485
+ result.put("folderCount", folderCount);
486
+ result.put("fileCount", fileCount);
487
+
488
+ return result;
489
+ }
490
+
491
+ /**
492
+ * 获取文件类型
493
+ */
494
+ private String getFileType(String name, boolean isDirectory) {
495
+ if (isDirectory) return "folder";
496
+
497
+ String lowerName = name.toLowerCase();
498
+ if (lowerName.endsWith(".dex")) return "dex";
499
+ if (lowerName.endsWith(".xml")) return "xml";
500
+ if (lowerName.endsWith(".arsc")) return "resource";
501
+ if (lowerName.endsWith(".so")) return "native";
502
+ if (lowerName.endsWith(".png") || lowerName.endsWith(".jpg") ||
503
+ lowerName.endsWith(".jpeg") || lowerName.endsWith(".webp") ||
504
+ lowerName.endsWith(".gif")) return "image";
505
+ if (lowerName.endsWith(".smali")) return "smali";
506
+ if (lowerName.endsWith(".bin") || lowerName.endsWith(".dat")) return "binary";
507
+ if (lowerName.equals("androidmanifest.xml")) return "manifest";
508
+
509
+ return "file";
510
+ }
511
+
368
512
  /**
369
513
  * 关闭 APK 会话
370
514
  */
@@ -390,6 +390,17 @@ public class DexEditorPluginPlugin extends Plugin {
390
390
  result.put("data", apkManager.getSessionDexFiles(params.getString("sessionId")));
391
391
  break;
392
392
 
393
+ case "installApk":
394
+ apkManager.installApk(params.getString("apkPath"));
395
+ break;
396
+
397
+ case "listApkDirectory":
398
+ result.put("data", apkManager.listApkDirectory(
399
+ params.getString("apkPath"),
400
+ params.optString("directory", "")
401
+ ));
402
+ break;
403
+
393
404
  default:
394
405
  result.put("success", false);
395
406
  result.put("error", "Unknown action: " + action);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-dex-editor",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
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",