|
4 | 4 | import android.util.Log; |
5 | 5 |
|
6 | 6 | import java.io.File; |
| 7 | +import java.lang.reflect.Field; |
7 | 8 | import java.lang.reflect.InvocationTargetException; |
8 | 9 | import java.lang.reflect.Method; |
9 | 10 | import java.util.HashMap; |
@@ -38,19 +39,23 @@ of this software and associated documentation files (the "Software"), to deal |
38 | 39 | */ |
39 | 40 |
|
40 | 41 | public class Hotpatch { |
41 | | - Context context; |
42 | | - String jarpath; |
43 | | - DexClassLoader dexClassLoader; |
44 | | - HashMap<String, Class<Object> > classLoaded; |
45 | | - HashMap<String, Object > classInstance; |
46 | | - HashMap<String, Method> method; |
| 42 | + public static final String TAG = "AndroidHotpatch"; |
| 43 | + |
| 44 | + private Context context; |
| 45 | + private String jarpath; |
| 46 | + private DexClassLoader dexClassLoader; |
| 47 | + private HashMap<String, Class<Object> > classLoaded; |
| 48 | + private HashMap<String, Object> classInstance; |
| 49 | + private HashMap<String, Field> fields; |
| 50 | + private HashMap<String, Method> method; |
47 | 51 |
|
48 | 52 | public void Hotpatch() { |
49 | 53 | jarpath = null; |
50 | 54 | dexClassLoader = null; |
51 | | - classLoaded = new HashMap<>(); |
52 | | - classInstance = new HashMap<>(); |
53 | | - method = new HashMap<>(); |
| 55 | + classLoaded = null; |
| 56 | + classInstance = null; |
| 57 | + method = null; |
| 58 | + fields = null; |
54 | 59 |
|
55 | 60 | } |
56 | 61 |
|
@@ -83,34 +88,70 @@ public void loadClass(String className) throws ClassNotFoundException, |
83 | 88 | classLoaded = new HashMap<>(); |
84 | 89 |
|
85 | 90 | if (classLoaded.containsKey(className)) { |
86 | | - Log.d("AndroidHotpatch", "Class " + className + " is already loaded"); |
| 91 | + Log.d(TAG, "Class " + className + " is already loaded"); |
87 | 92 | return; |
88 | 93 | } |
89 | 94 |
|
90 | 95 | Class<Object> tmpClass = (Class<Object>)dexClassLoader.loadClass(className); |
91 | 96 | classLoaded.put(className, tmpClass); |
92 | 97 |
|
93 | | - Object tmpClassInstance = tmpClass.newInstance(); |
94 | 98 | if(classInstance == null) |
95 | 99 | classInstance = new HashMap<>(); |
96 | 100 |
|
| 101 | + Object tmpClassInstance = tmpClass.newInstance(); |
97 | 102 | classInstance.put(className, tmpClassInstance); |
98 | 103 | } |
99 | 104 |
|
| 105 | + public void loadClasses() { |
| 106 | + /* TODO */ |
| 107 | + } |
| 108 | + |
| 109 | + public void loadFields(String className) { |
| 110 | + Field fields[] = classLoaded.get(className).getFields(); |
| 111 | + |
| 112 | + if (this.fields == null) |
| 113 | + this.fields = new HashMap<>(); |
| 114 | + |
| 115 | + for (Field field : fields) { |
| 116 | + Log.d(TAG, "Field " + field.getName() + ": " + field.toGenericString()); |
| 117 | + this.fields.put(className + ":" + field.getName(), field); |
| 118 | + } |
| 119 | + |
| 120 | + } |
| 121 | + |
100 | 122 | public void loadMethods(String className, String methods[]) throws NoSuchMethodException { |
101 | 123 | if (!classLoaded.containsKey(className)) |
102 | 124 | throw new IllegalArgumentException("Class " + className + " is not loaded"); |
103 | 125 |
|
104 | | - if(this.method == null) |
| 126 | + if (this.method == null) |
105 | 127 | this.method = new HashMap<>(); |
106 | 128 |
|
107 | 129 | for (String methodName: methods) { |
| 130 | + Log.d(TAG, "Loading method " + className + "." + methodName); |
108 | 131 | Method tmpMethod = classLoaded.get(className).getMethod(methodName); |
109 | 132 |
|
110 | 133 | method.put(className + ":" + methodName, tmpMethod); |
111 | 134 | } |
112 | 135 | } |
113 | 136 |
|
| 137 | + public void loadMethods(String className) { |
| 138 | + /* FIX: java.lang.NoSuchMethodException: equals [] */ |
| 139 | + |
| 140 | + if (!classLoaded.containsKey(className)) |
| 141 | + throw new IllegalArgumentException("Class " + className + " is not loaded"); |
| 142 | + |
| 143 | + if (this.method == null) |
| 144 | + this.method = new HashMap<>(); |
| 145 | + |
| 146 | + Method methods[] = classLoaded.get(className).getMethods(); |
| 147 | + |
| 148 | + for (Method method : methods) { |
| 149 | + String name = method.getName(); |
| 150 | + |
| 151 | + this.method.put(className + ":" + name, method); |
| 152 | + } |
| 153 | + } |
| 154 | + |
114 | 155 | public Object call(String className, String methodName, Object... args) throws IllegalAccessException, |
115 | 156 | InvocationTargetException { |
116 | 157 |
|
@@ -144,4 +185,17 @@ public void reload() throws InstantiationException, IllegalAccessException, Clas |
144 | 185 | } |
145 | 186 |
|
146 | 187 | } |
| 188 | + |
| 189 | + public void autoload() { |
| 190 | + if (this.classLoaded == null) |
| 191 | + throw new RuntimeException("You must load classes first!"); |
| 192 | + |
| 193 | + Set<String> classNames = this.classLoaded.keySet(); |
| 194 | + |
| 195 | + for (String className : classNames) { |
| 196 | + this.loadMethods(className); |
| 197 | + this.loadFields(className); |
| 198 | + } |
| 199 | + |
| 200 | + } |
147 | 201 | } |
0 commit comments