capacitor-dex-editor 0.0.70 → 0.0.71

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.
@@ -130,14 +130,16 @@ public class DexManager {
130
130
  String sessionId;
131
131
  String filePath;
132
132
  DexBackedDexFile originalDexFile;
133
+ byte[] dexBytes; // DEX 字节数据,用于 C++ 解析
133
134
  List<ClassDef> modifiedClasses;
134
135
  Set<String> removedClasses;
135
136
  boolean modified = false;
136
137
 
137
- DexSession(String sessionId, String filePath, DexBackedDexFile dexFile) {
138
+ DexSession(String sessionId, String filePath, DexBackedDexFile dexFile, byte[] bytes) {
138
139
  this.sessionId = sessionId;
139
140
  this.filePath = filePath;
140
141
  this.originalDexFile = dexFile;
142
+ this.dexBytes = bytes;
141
143
  this.modifiedClasses = new ArrayList<>();
142
144
  this.removedClasses = new HashSet<>();
143
145
  }
@@ -188,6 +190,9 @@ public class DexManager {
188
190
  // 生成或使用提供的 sessionId
189
191
  String sid = (sessionId != null && !sessionId.isEmpty()) ? sessionId : UUID.randomUUID().toString();
190
192
 
193
+ // 读取 DEX 字节数据(用于 C++ 解析)
194
+ byte[] dexBytes = readFileBytes(file);
195
+
191
196
  // 加载 DEX 文件 (使用官方推荐的 DexFileFactory)
192
197
  DexBackedDexFile dexFile = (DexBackedDexFile) DexFileFactory.loadDexFile(
193
198
  file,
@@ -195,7 +200,7 @@ public class DexManager {
195
200
  );
196
201
 
197
202
  // 创建会话
198
- DexSession session = new DexSession(sid, path, dexFile);
203
+ DexSession session = new DexSession(sid, path, dexFile, dexBytes);
199
204
  sessions.put(sid, session);
200
205
 
201
206
  Log.d(TAG, "Loaded DEX: " + path + " with session: " + sid);
@@ -262,18 +267,41 @@ public class DexManager {
262
267
  }
263
268
 
264
269
  /**
265
- * 获取 DEX 文件信息
270
+ * 获取 DEX 文件信息(优先使用 C++ 实现)
266
271
  */
267
272
  public JSObject getDexInfo(String sessionId) throws Exception {
268
273
  DexSession session = getSession(sessionId);
274
+
275
+ // 优先使用 C++ 实现
276
+ if (CppDex.isAvailable() && session.dexBytes != null) {
277
+ try {
278
+ String jsonResult = CppDex.getDexInfo(session.dexBytes);
279
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
280
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
281
+ JSObject info = new JSObject();
282
+ info.put("sessionId", sessionId);
283
+ info.put("filePath", session.filePath);
284
+ info.put("classCount", cppResult.optInt("classCount", 0));
285
+ info.put("methodCount", cppResult.optInt("methodCount", 0));
286
+ info.put("fieldCount", cppResult.optInt("fieldCount", 0));
287
+ info.put("stringCount", cppResult.optInt("stringCount", 0));
288
+ info.put("dexVersion", cppResult.optInt("version", 35));
289
+ info.put("modified", session.modified);
290
+ info.put("engine", "cpp");
291
+ return info;
292
+ }
293
+ } catch (Exception e) {
294
+ Log.w(TAG, "C++ getDexInfo failed, fallback to Java", e);
295
+ }
296
+ }
297
+
298
+ // Java 回退实现
269
299
  DexBackedDexFile dexFile = session.originalDexFile;
270
-
271
300
  JSObject info = new JSObject();
272
301
  info.put("sessionId", sessionId);
273
302
  info.put("filePath", session.filePath);
274
303
  info.put("classCount", dexFile.getClasses().size());
275
304
 
276
- // 统计方法和字段数量
277
305
  int methodCount = 0;
278
306
  int fieldCount = 0;
279
307
  for (ClassDef classDef : dexFile.getClasses()) {
@@ -284,18 +312,45 @@ public class DexManager {
284
312
  info.put("fieldCount", fieldCount);
285
313
  info.put("dexVersion", dexFile.getOpcodes().api);
286
314
  info.put("modified", session.modified);
315
+ info.put("engine", "java");
287
316
  return info;
288
317
  }
289
318
 
290
319
  // ==================== 类操作 ====================
291
320
 
292
321
  /**
293
- * 获取所有类列表
322
+ * 获取所有类列表(优先使用 C++ 实现)
294
323
  */
295
324
  public JSArray getClasses(String sessionId) throws Exception {
296
325
  DexSession session = getSession(sessionId);
326
+
327
+ // 优先使用 C++ 实现
328
+ if (CppDex.isAvailable() && session.dexBytes != null) {
329
+ try {
330
+ String jsonResult = CppDex.listClasses(session.dexBytes, "", 0, 100000);
331
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
332
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
333
+ org.json.JSONArray cppClasses = cppResult.optJSONArray("classes");
334
+ if (cppClasses != null) {
335
+ JSArray classes = new JSArray();
336
+ for (int i = 0; i < cppClasses.length(); i++) {
337
+ String className = cppClasses.getString(i);
338
+ if (!session.removedClasses.contains(className)) {
339
+ JSObject classInfo = new JSObject();
340
+ classInfo.put("type", className);
341
+ classes.put(classInfo);
342
+ }
343
+ }
344
+ return classes;
345
+ }
346
+ }
347
+ } catch (Exception e) {
348
+ Log.w(TAG, "C++ getClasses failed, fallback to Java", e);
349
+ }
350
+ }
351
+
352
+ // Java 回退实现
297
353
  JSArray classes = new JSArray();
298
-
299
354
  for (ClassDef classDef : session.originalDexFile.getClasses()) {
300
355
  if (!session.removedClasses.contains(classDef.getType())) {
301
356
  JSObject classInfo = new JSObject();
@@ -305,7 +360,6 @@ public class DexManager {
305
360
  classes.put(classInfo);
306
361
  }
307
362
  }
308
-
309
363
  return classes;
310
364
  }
311
365
 
@@ -407,12 +461,38 @@ public class DexManager {
407
461
  // ==================== 方法操作 ====================
408
462
 
409
463
  /**
410
- * 获取类的所有方法
464
+ * 获取类的所有方法(优先使用 C++ 实现)
411
465
  */
412
466
  public JSArray getMethods(String sessionId, String className) throws Exception {
413
467
  DexSession session = getSession(sessionId);
468
+
469
+ // 优先使用 C++ 实现
470
+ if (CppDex.isAvailable() && session.dexBytes != null) {
471
+ try {
472
+ String jsonResult = CppDex.listMethods(session.dexBytes, className);
473
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
474
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
475
+ org.json.JSONArray cppMethods = cppResult.optJSONArray("methods");
476
+ if (cppMethods != null) {
477
+ JSArray methods = new JSArray();
478
+ for (int i = 0; i < cppMethods.length(); i++) {
479
+ org.json.JSONObject m = cppMethods.getJSONObject(i);
480
+ JSObject methodInfo = new JSObject();
481
+ methodInfo.put("name", m.optString("name"));
482
+ methodInfo.put("signature", m.optString("prototype"));
483
+ methodInfo.put("accessFlags", m.optInt("accessFlags"));
484
+ methods.put(methodInfo);
485
+ }
486
+ return methods;
487
+ }
488
+ }
489
+ } catch (Exception e) {
490
+ Log.w(TAG, "C++ getMethods failed, fallback to Java", e);
491
+ }
492
+ }
493
+
494
+ // Java 回退实现
414
495
  ClassDef classDef = findClass(session, className);
415
-
416
496
  if (classDef == null) {
417
497
  throw new IllegalArgumentException("Class not found: " + className);
418
498
  }
@@ -424,14 +504,12 @@ public class DexManager {
424
504
  methodInfo.put("returnType", method.getReturnType());
425
505
  methodInfo.put("accessFlags", method.getAccessFlags());
426
506
 
427
- // 参数类型
428
507
  JSArray params = new JSArray();
429
508
  for (CharSequence param : method.getParameterTypes()) {
430
509
  params.put(param.toString());
431
510
  }
432
511
  methodInfo.put("parameters", params);
433
512
 
434
- // 方法签名
435
513
  StringBuilder sig = new StringBuilder("(");
436
514
  for (CharSequence param : method.getParameterTypes()) {
437
515
  sig.append(param);
@@ -441,7 +519,6 @@ public class DexManager {
441
519
 
442
520
  methods.put(methodInfo);
443
521
  }
444
-
445
522
  return methods;
446
523
  }
447
524
 
@@ -583,12 +660,38 @@ public class DexManager {
583
660
  // ==================== 字段操作 ====================
584
661
 
585
662
  /**
586
- * 获取类的所有字段
663
+ * 获取类的所有字段(优先使用 C++ 实现)
587
664
  */
588
665
  public JSArray getFields(String sessionId, String className) throws Exception {
589
666
  DexSession session = getSession(sessionId);
667
+
668
+ // 优先使用 C++ 实现
669
+ if (CppDex.isAvailable() && session.dexBytes != null) {
670
+ try {
671
+ String jsonResult = CppDex.listFields(session.dexBytes, className);
672
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
673
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
674
+ org.json.JSONArray cppFields = cppResult.optJSONArray("fields");
675
+ if (cppFields != null) {
676
+ JSArray fields = new JSArray();
677
+ for (int i = 0; i < cppFields.length(); i++) {
678
+ org.json.JSONObject f = cppFields.getJSONObject(i);
679
+ JSObject fieldInfo = new JSObject();
680
+ fieldInfo.put("name", f.optString("name"));
681
+ fieldInfo.put("type", f.optString("type"));
682
+ fieldInfo.put("accessFlags", f.optInt("accessFlags"));
683
+ fields.put(fieldInfo);
684
+ }
685
+ return fields;
686
+ }
687
+ }
688
+ } catch (Exception e) {
689
+ Log.w(TAG, "C++ getFields failed, fallback to Java", e);
690
+ }
691
+ }
692
+
693
+ // Java 回退实现
590
694
  ClassDef classDef = findClass(session, className);
591
-
592
695
  if (classDef == null) {
593
696
  throw new IllegalArgumentException("Class not found: " + className);
594
697
  }
@@ -1254,6 +1357,14 @@ public class DexManager {
1254
1357
  return content.toString();
1255
1358
  }
1256
1359
 
1360
+ private byte[] readFileBytes(File file) throws IOException {
1361
+ byte[] bytes = new byte[(int) file.length()];
1362
+ try (FileInputStream fis = new FileInputStream(file)) {
1363
+ fis.read(bytes);
1364
+ }
1365
+ return bytes;
1366
+ }
1367
+
1257
1368
  private void deleteRecursive(File file) {
1258
1369
  if (file.isDirectory()) {
1259
1370
  File[] children = file.listFiles();
@@ -2903,21 +3014,6 @@ public class DexManager {
2903
3014
  return result;
2904
3015
  }
2905
3016
 
2906
- /**
2907
- * 读取文件为字节数组
2908
- */
2909
- private byte[] readFileBytes(java.io.File file) throws java.io.IOException {
2910
- java.io.FileInputStream fis = new java.io.FileInputStream(file);
2911
- java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
2912
- byte[] buffer = new byte[8192];
2913
- int len;
2914
- while ((len = fis.read(buffer)) != -1) {
2915
- baos.write(buffer, 0, len);
2916
- }
2917
- fis.close();
2918
- return baos.toByteArray();
2919
- }
2920
-
2921
3017
  /**
2922
3018
  * 计算 CRC32
2923
3019
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-dex-editor",
3
- "version": "0.0.70",
3
+ "version": "0.0.71",
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",